1   /*
2    *  BootStrap.java
3    *
4    *  Copyright (c) 1998-2005, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   *
11   *  Oana Hamza 14/Nov/2000
12   *
13   *  $Id: BootStrap.java,v 1.18 2005/02/17 10:43:00 julien Exp $
14   */
15  package gate.creole;
16  
17  import java.io.*;
18  import java.lang.reflect.Method;
19  import java.util.*;
20  
21  import gate.util.*;
22  
23  
24  /**
25    * This class creates a resource (e.g.ProcessingResource, VisualResource or
26    * Language Resource) with the information from the user and generates a
27    * project in the directory provided by the user
28    */
29  
30  public class BootStrap {
31  
32    /** the name of the resource of the template project from the gate resources*/
33    //protected String oldResource = "creole/templateproject";
34    protected static final String oldResource = "creole/bootstrap/";
35  
36    /** the name of jar resource*/
37    protected static final String nameProject = "Template";
38  
39    /** new line for different platforms*/
40    protected static final String newLine = Strings.getNl();
41  
42    /** a map from the variants of the names of the files and the
43      * directories of the empty project to the variants of the names of the
44      * files and the directories the new project
45      */
46    protected Map names = null;
47  
48    protected Map oldNames = null;
49  
50    /** the methods from the class that implements the resource*/
51    protected List listMethodsResource = null;
52  
53    /** the list with the packages name where the main class can be find*/
54    protected List listPackages;
55  
56    /** the packages used by the class which creates the resources */
57    protected Set allPackages = null;
58  
59    /** the enumeration of the variables from main class*/
60    protected Map fields = null;
61  
62    /** a buffer in order to read an array of char */
63    protected char cbuffer[] = null;
64  
65    /** the size of the buffer */
66    protected final static int BUFF_SIZE = 65000;
67  
68  
69    public BootStrap() {
70  
71      names = new HashMap();
72  
73      oldNames = new HashMap();
74  
75      listMethodsResource = new ArrayList();
76  
77      listPackages = new ArrayList();
78  
79      cbuffer = new char[BUFF_SIZE];
80  
81      allPackages = new HashSet();
82  
83      fields = new HashMap();
84    }
85  
86    /** Determines all the keys from the map "names" in the text and replaces them
87      * with their values
88      */
89    public String changeKeyValue ( String text, Map map ){
90  
91      Set keys = map.keySet();
92      Iterator iteratorKeys = keys.iterator();
93      while (iteratorKeys.hasNext()) {
94        String key = (String) iteratorKeys.next();
95        String value = (String)map.get(key);
96        text = text.replaceAll(key,value);
97      } // while
98      return text;
99    } // changeKeyValue ( String text )
100 
101   /** determines the package of the main class
102     */
103   public String determineTypePackage(String text) {
104 
105     // determine the position of the last "."
106     int index = text.lastIndexOf(".");
107     int ind = text.lastIndexOf(";");
108     String type = new String();
109     String packageName = new String();
110 
111     if (index != -1){
112       // determine the package and add to the list of packages
113       if (ind != -1) {
114         type = text.substring(index+1,text.length()-1)+"[]";
115         packageName = (text.substring(2,index))+".*";
116       }
117       else {
118         packageName = (text.substring(0,index))+".*";
119         type = text.substring(index+1,text.length());
120       }
121       // add the name of the package
122       if ((!allPackages.contains(packageName))&&
123                               (packageName.compareTo("java.lang.*")!=0))
124         allPackages.add(packageName);
125     } else {type = text;}
126 
127     return type;
128   }
129 
130   /** returns the string with the interfaces that implement the main class and
131     *  the class that extends it
132     */
133   public String getInterfacesAndClass (String typeResource, Set interfacesList)
134                                     throws ClassNotFoundException {
135 
136     String abstractClass = null;
137     // add the class that it extends
138     String interfacesAndClass = null;
139     // the class corresponding to the current interface from list interfaces.
140     Class currentClass = null;
141 
142     // determine the abstract class
143     if (typeResource.equals("ProcessingResource")) {
144       abstractClass = "AbstractProcessingResource";
145     } else if (typeResource.equals("VisualResource")) {
146       abstractClass = "AbstractVisualResource";
147     } else if (typeResource.equals("LanguageResource")) {
148       abstractClass = "AbstractLanguageResource";}
149 
150     interfacesAndClass = " extends " + abstractClass;
151 
152     // a map from all the methods from interfaces to the lists which contains
153     // the features of every method
154     List methodsInterfaces = new ArrayList();
155     if (interfacesList!=null) {
156       interfacesAndClass = interfacesAndClass+ newLine+ "  implements ";
157       Iterator iter = interfacesList.iterator();
158       while (iter.hasNext()) {
159         String nameInterface =(String)iter.next();
160         String nameClass = null;
161         int index = nameInterface.lastIndexOf(".");
162         if (index != -1) {
163           currentClass = Class.forName(nameInterface);
164           nameClass = nameInterface.substring(index+1,nameInterface.length());
165         } else {
166           nameClass = nameInterface;
167           currentClass = Class.forName("gate."+nameInterface);
168         }// else
169 
170         // add the package to the list
171         if (!allPackages.contains(currentClass.getPackage())){
172           allPackages.add(currentClass.getPackage().getName()+".*");
173         }
174 
175         interfacesAndClass = interfacesAndClass + nameClass + ", ";
176 
177         methodsInterfaces = featuresClass(currentClass,methodsInterfaces);
178       }//while
179     }// if
180 
181     // add the abstract class
182     if (!interfacesList.contains("gate."+typeResource))
183       interfacesAndClass = interfacesAndClass + typeResource;
184     else if (interfacesAndClass.endsWith(", "))
185       interfacesAndClass = interfacesAndClass.substring
186                                             (0,interfacesAndClass.length()-2);
187 
188     // methods from the class that extends the resource
189     List methodsClassExtend = new ArrayList();
190     Class currentClassExtend = Class.forName("gate.creole."+abstractClass);
191     methodsClassExtend = featuresClass(currentClassExtend, methodsClassExtend);
192 
193     // get the methods and fields for the main class
194     getMethodsAndFields(methodsClassExtend,methodsInterfaces);
195 
196     return interfacesAndClass;
197   } // getInterfacesAndClass
198 
199   /**go through all methods and determines return type, parameters, exceptions*/
200   public List featuresClass (Class currentClass, List methodsList){
201 
202     // go through all the methods
203     Method[] listMethodsCurrentClass = currentClass.getMethods();
204     for (int i=0;i<listMethodsCurrentClass.length;i++) {
205       FeatureMethod featureMethod = new FeatureMethod();
206       featureMethod.setNameMethod(listMethodsCurrentClass[i].getName());
207       featureMethod.setValueReturn(
208                           listMethodsCurrentClass[i].getReturnType().getName());
209 
210       Class[] parameters = (Class[])(
211                                 listMethodsCurrentClass[i].getParameterTypes());
212       Class[] exceptions = (Class[])(
213                                 listMethodsCurrentClass[i].getExceptionTypes());
214 
215       // determine the parameters for the current method
216       List aux = new ArrayList();
217       for (int k=0;k<parameters.length;k++)
218         aux.add(parameters[k].getName());
219       featureMethod.setParameterTypes(aux);
220 
221       // determine the exceptions for the current method
222       aux = new ArrayList();
223       for (int k=0;k<exceptions.length;k++)
224         aux.add(exceptions[k].getName());
225       featureMethod.setExceptionTypes(aux);
226 
227       if (!methodsList.contains(featureMethod)){
228         methodsList.add(featureMethod);
229       }
230     }// for
231     return methodsList;
232   }// List featureClass (Class currentClass)
233 
234   /** create the form for the methods from the class that create the resource
235     * @param methodsExtendList is the list with all methods from the class that extends
236     *  the resource
237     * @param methodsInterfacesList is the list with all methods from the interfaces
238     * that implement the resource
239     */
240   public void getMethodsAndFields(List methodsExtendList,
241                                                   List methodsInterfacesList){
242     // determine all the methods from the interfaces which are not among the
243     // methods of the class that extends the resource
244 
245     int j = 0;
246     for (int i=0;i<methodsInterfacesList.size();i++) {
247       FeatureMethod featureMethod = (FeatureMethod)methodsInterfacesList.get(i);
248       if (methodsExtendList.contains(featureMethod) == false) {
249         // the name of the method
250         String nameMethod = (String)(featureMethod.getNameMethod());
251 
252         // the types of the parameters of the method
253         List valTypes = (List)(featureMethod.getParameterTypes());
254 
255         // the value which the method returns
256         String typeReturn = determineTypePackage(
257                                       (String)(featureMethod.getValueReturn()));
258 
259         // get the list of exceptions for the current method
260         List valException = (List)(featureMethod.getExceptionTypes());
261 
262         String declaration = "public "+ typeReturn +" "+
263                              nameMethod +"(";
264         // parameters
265         if (valTypes.size() == 0)
266           declaration = declaration+")";
267         else
268           for (int k=0;k<valTypes.size();k++) {
269             String type = (String)valTypes.get(k);
270             if (type.endsWith("[]"))
271               declaration = declaration +
272                   determineTypePackage(type.substring(0,type.length()-2)) +
273                   " parameter"+ k;
274             else
275               declaration = declaration +
276                             determineTypePackage((String)valTypes.get(k)) +
277                             " parameter"+ k;
278 
279             if (k==valTypes.size()-1)
280               declaration = declaration + ")";
281             else
282               declaration = declaration + ", ";
283 
284           } // for
285 
286         // exceptions
287         if (valException.size() == 0) {
288           if (!typeReturn.equals("void")){
289             if (!typeReturn.endsWith("[]"))
290               declaration = declaration + "{ " + "return "+
291                             typeReturn.toLowerCase()+ j + "; }";
292             else
293               declaration = declaration + "{ " + "return "+
294                             typeReturn.toLowerCase().substring(
295                             0,typeReturn.length()-2)+ j + "; }";
296 
297             fields.put(new Integer(j),typeReturn);
298             j =j+1;
299           }
300           else {declaration = declaration+" {}" ;}
301         } // if
302         else {
303           declaration = declaration + newLine+ "                throws ";
304           for (int k=0;k<valException.size();k++) {
305             declaration = declaration + determineTypePackage((String)
306                                                     valException.get(k));
307 
308             if (k == valException.size()-1) {
309               if (!typeReturn.equals("void")){
310                 if (!typeReturn.endsWith("[]"))
311                   declaration = declaration + "{ " + "return "+
312                           typeReturn.toLowerCase()+ j+"; }";
313                 else
314                   declaration = declaration + "{ " + "return "+
315                             typeReturn.toLowerCase().substring(
316                             0,typeReturn.length()-2)+ j + "; }";
317 
318                 fields.put(new Integer(j),typeReturn);
319                 j=j+1;
320               }
321               else
322                 declaration = declaration+" {}" ;
323             } else
324               declaration = declaration + ", ";
325 
326           } // for
327         } // else
328 
329         // add the form of the method
330         listMethodsResource.add(declaration);
331 
332       } // if
333     } // while
334 
335   } // getMethodsAndFields
336 
337   /**
338     * write the methods and the fields in the right form
339     */
340   public String displayMethodsAndFields(List methods, Map fields) {
341 
342     String methodsFields = "";
343 
344     // go through all methods
345     Iterator iterator = listMethodsResource.iterator();
346     while (iterator.hasNext()) {
347       methodsFields = methodsFields + newLine + (String)iterator.next()+newLine;
348     }
349 
350     // go through all fields
351     Iterator iter = fields.keySet().iterator();
352     int i=0;
353     while (iter.hasNext()) {
354       Integer index = (Integer)iter.next();
355       String type = (String)fields.get(index);
356       if (type.endsWith("[]"))
357         methodsFields = methodsFields + newLine + "protected " + type +" " +
358                        type.substring(0,type.length()-2).toLowerCase() +
359                         index.toString() +";";
360 
361       else
362         methodsFields = methodsFields + newLine + "protected " + type +" " +
363                         type.toLowerCase() + index.toString() +";";
364         i+=1;
365     }
366     return methodsFields;
367   }// displayMethodsAndFields(List methods, List fields)
368 
369 
370   /** create the map with variants of the names... */
371   public Map createNames ( String packageName,
372                            String resourceName,
373                            String className,
374                            String stringPackages,
375                            String interfacesAndClass) {
376 
377      // all the packages from the class, which creates the resource
378     String packages = namesPackages(allPackages);
379 
380     // determine the name of the current user and the current day
381     Calendar calendar = Calendar.getInstance();
382     int month = calendar.get(Calendar.MONTH)+1;
383     int year = calendar.get(Calendar.YEAR);
384     int day = calendar.get(Calendar.DAY_OF_MONTH);
385     String date = day+"/"+month+"/"+year;
386     String user = System.getProperty("user.name");
387 
388     // the a map with the variants of names and the current date
389     // and the current user
390     names.put(nameProject,resourceName);
391     names.put(nameProject.toUpperCase(),resourceName.toUpperCase());
392     names.put(nameProject.toLowerCase(),resourceName.toLowerCase());
393     names.put("___CLASSNAME___",className);
394     names.put("___INTERFACES___",interfacesAndClass);
395     names.put("___CONTENT___",
396                           displayMethodsAndFields(listMethodsResource,fields));
397     names.put("___DATE___",date);
398     names.put("___AUTHOR___",user);
399     // "___ALLPACKAGE___" is the packages separated by "/"
400     // e.g. "sheffied/creole/tokeniser"
401     names.put("___ALLPACKAGES___",stringPackages);
402     // "___PACKAGE___" is the packages separated by "."
403     // e.g. "sheffied.creole.tokeniser"
404     names.put("___PACKAGE___",packageName);
405     names.put("___PACKAGETOP___",listPackages.get(0));
406     names.put("___RESOURCE___",resourceName);;
407     names.put(
408       "___GATECLASSPATH___",
409       System.getProperty("path.separator") +
410         System.getProperty("java.class.path")
411     );
412 
413     if (packages.length() == 0){
414       names.put("import ___packages___.*;", "");
415     } else {
416       names.put("import ___packages___.*;", packages);
417     }
418 
419     oldNames.put("___PACKAGE___","template");
420     oldNames.put("___ALLPACKAGES___","template");
421     oldNames.put("___PACKAGETOP___","template");
422 
423     return names;
424   }// End createNames()
425 
426   /** determine all the packages */
427   public String namesPackages (Set listPackages) {
428     Iterator iterator = listPackages.iterator();
429     String packages = new String();
430     while (iterator.hasNext()) {
431       String currentPackage = (String)iterator.next();
432       if ((!currentPackage.equals("gate.*"))&&
433          (!currentPackage.equals("gate.creole.*"))&&
434          (!currentPackage.equals("gate.util.*"))&&
435          (!currentPackage.equals("java.util.*")))
436           packages = packages + newLine + "import "+ currentPackage+";";
437     }// while
438     return packages;
439   }
440 
441   /** determines the name of the packages and adds them to a list
442     */
443   public List determinePath (String packageName)throws IOException {
444     List list = new ArrayList();
445     StringTokenizer token = new StringTokenizer(packageName,".");
446     //if (token.countTokens()>1) {
447       while (token.hasMoreTokens()) {
448         list.add(token.nextToken());
449       }
450     //} else list.add(packageName);
451     return list;
452   }
453 
454   /** verify if the class name contains only letters and digits
455    *  the path of the new project is a directory
456    */
457   public void verifyInput(String className, String pathNewProject)
458                           throws GateException {
459     // verify the input
460     // class name contains only letters and digits
461     char[] classNameChars = className.toCharArray();
462     for (int i=0;i<classNameChars.length;i++){
463       Character classNameCharacter = new Character(classNameChars[i]);
464       if (!Character.isLetterOrDigit(classNameChars[i]))
465         throw new GateException("Only letters and digits in the class name");
466     }
467 
468     // verify if it exits a directory of given path
469     File dir = new File(pathNewProject);
470     if (!dir.isDirectory())
471       throw new GateException("The folder is not a directory");
472   }
473 
474   /***/
475   public void executableFile(String nameFile)
476                                     throws IOException,InterruptedException{
477     String osName = System.getProperty("os.name" );
478     if( !osName.startsWith("Windows") ){
479       Runtime rt = Runtime.getRuntime();
480       Process proc = rt.exec("chmod 711 "+nameFile);
481 
482       // any error???
483       int exitVal = proc.waitFor();
484       if (exitVal!=0)
485         Out.prln("Warning: it is necessary to make executable the "+
486           "following file: " + nameFile);
487     }//if
488   }// executableFile
489 
490   /**  Creates the resource and dumps out a project structure using the
491     *  structure from gate/resource/creole/templateproject/Template and the
492     *  information provided by the user
493     * @param resourceName is the name of the resource
494     * @param packageName is the name of the new resource
495     * @param typeResource is the type of the resource (e.g.ProcessingResource,
496     *  LanguageResource or VisualResource)
497     * @param className is the name of the class which implements the resource
498     * @param interfacesList is the set of the interfaces that implements the resource
499     * @param pathNewProject is the path where it will be the new resource
500     */
501   public void createResource( String resourceName,String packageName,
502                               String typeResource,String className,
503                               Set interfacesList,String pathNewProject)
504                               throws
505                               IOException,ClassNotFoundException,
506                               GateException,InterruptedException {
507     // the current file created by the system
508     File newFile = null;
509 
510     // define for reading from a file.properties
511     Properties properties = new Properties();
512 
513     // the new path of the current file
514     String newPathFile = null;
515 
516     // the path of file from template project
517     String oldPathFile = null;
518 
519     // verify the input
520     verifyInput(className,pathNewProject);
521 
522     // determine the interfaces that the resource implements and the class
523     // that it extends
524     String interfacesAndClass = getInterfacesAndClass (typeResource,
525                                                   interfacesList);
526 
527     //determine the list with packages
528     listPackages = determinePath(packageName);
529 
530     //add "/" at the end of the path of project
531     if (!pathNewProject.endsWith("/")) pathNewProject = pathNewProject + "/";
532 
533     // determine the path of the main class
534     String stringPackages = (String)listPackages.get(0);
535     for (int i=1;i<listPackages.size();i++) {
536       stringPackages = stringPackages + "/"+listPackages.get(i);
537     }
538 
539     // create the map with the names
540     createNames(packageName,resourceName,className,
541                                             stringPackages,interfacesAndClass);
542 
543     // take the content of the file with the structure of the template project
544     InputStream inputStream = Files.getGateResourceAsStream(oldResource +
545                               "file-list.properties");
546 
547     // put all the files and directories
548     properties.load(inputStream);
549 
550     // close the input stream
551     inputStream.close();
552 
553     // firstly create the directories
554     String oldDirectories = properties.getProperty("directories");
555     StringTokenizer token = new StringTokenizer(oldDirectories,",");
556     while (token.hasMoreTokens()) {
557       String propPathDirectory = (String)token.nextToken();
558       if (propPathDirectory.endsWith("___ALLPACKAGES___")) {
559         //create every directory from the path of package
560         newPathFile =
561           propPathDirectory.substring(0,propPathDirectory.length()-18);
562         // change the path according to input
563         newPathFile = changeKeyValue(newPathFile,names);
564         for (int i=0;i<listPackages.size();i++) {
565           newPathFile = newPathFile + "/"+listPackages.get(i);
566           newFile = new File(pathNewProject + newPathFile);
567           newFile.mkdir();
568         }//for
569       } else {
570         newPathFile = changeKeyValue(propPathDirectory,names);
571         // change the path according to input
572         newFile = new File(pathNewProject + newPathFile);
573         newFile.mkdir();
574       }//else
575     }// while
576 
577     // secondly, create the files
578     Enumeration keyProperties = properties.propertyNames();
579     // goes through all the files from the template project
580     while (keyProperties.hasMoreElements()) {
581       String key = (String)keyProperties.nextElement();
582       if (!key.equals("directories")) {
583         String oldFiles = properties.getProperty(key);
584         token = new StringTokenizer(oldFiles,",");
585         //go through all the files
586         while (token.hasMoreTokens()) {
587           String propPathFiles = (String)token.nextToken();
588           oldPathFile = changeKeyValue(propPathFiles,oldNames);
589 
590           // change the path according to input
591           newPathFile = changeKeyValue(propPathFiles,names);
592 
593           // change the extension of the current file from "jav" to "java"
594           if (newPathFile.endsWith("jav")) newPathFile = newPathFile +"a";
595 
596           // the content of the current file is copied on the disk
597 
598           // the current file for writing characters
599           newFile = new File(pathNewProject+newPathFile);
600 
601           //create a filewriter for writing
602           FileWriter fileWriter = new FileWriter(newFile);
603 
604           // get the input stream from
605           InputStream currentInputStream =
606               Files.getGateResourceAsStream(oldResource+oldPathFile);
607 
608           InputStreamReader inputStreamReader = new InputStreamReader (
609                                                     currentInputStream);
610           int  charRead = 0;
611           String text = null;
612           while(
613           (charRead = inputStreamReader.read(cbuffer,0,BUFF_SIZE)) != -1){
614             text = new String (cbuffer,0,charRead);
615             text = changeKeyValue(text,names);
616             fileWriter.write(text ,0,text.length());
617            }//while
618            inputStreamReader.close();
619            // close the input stream
620            currentInputStream.close();
621            // close the file for writing
622            fileWriter.close();
623 
624           // change sh files in executable
625           if (newPathFile.endsWith("configure")||newPathFile.endsWith(".sh"))
626             executableFile(pathNewProject+newPathFile);
627 
628         }//while
629       }//if
630     }//while
631 
632   } // modify
633 
634   public static void main(String[] args) {
635     System.out.println(System.getProperty("path.separator"));
636     System.out.println("intre");
637     System.out.println(System.getProperty("java.class.path"));
638     BootStrap bootStrap = new BootStrap();
639     Set interfaces = new HashSet();
640     interfaces.add("gate.Document");
641     interfaces.add("gate.ProcessingResource");
642     try{
643 
644     bootStrap.createResource("morph","creole.sheffield.ac.lisa","LanguageResource",
645       "Documente", interfaces, "z:/test");
646     } catch (GateException ge) {
647       ge.printStackTrace(Err.getPrintWriter());
648     } catch (ClassNotFoundException cnfe) {
649       cnfe.printStackTrace(Err.getPrintWriter());
650     } catch (IOException ioe) {
651       ioe.printStackTrace(Err.getPrintWriter());
652     } catch (InterruptedException ie){
653       ie.printStackTrace(Err.getPrintWriter());
654     }
655   }// main
656 
657 } // class BootStrap
658 
659 /** FeatureMethod is a class encapsulating
660   * information about the feature of a method such as the name, the return
661   * type, the parameters types or exceptions types
662   */
663 class FeatureMethod {
664   /** the name of the method*/
665   protected String nameMethod;
666 
667   /** the return value*/
668   protected String valueReturn;
669 
670   /** the list with the types of the parameters */
671   protected List parameterTypes;
672 
673   /** the list with the types of the exceptions */
674   protected List exceptionTypes;
675 
676   FeatureMethod() {
677     nameMethod = new String();
678     valueReturn = new String();
679     parameterTypes = new ArrayList();
680     exceptionTypes = new ArrayList();
681   }
682 
683   public String getNameMethod() {
684     return nameMethod;
685   }//getNameMethod
686 
687   public String getValueReturn() {
688     return valueReturn;
689   }//getValueReturn
690 
691   public List getParameterTypes() {
692     return parameterTypes;
693   }//getParameterTypes
694 
695   public List getExceptionTypes() {
696     return exceptionTypes;
697   }//getExceptionTypes
698 
699   public void setNameMethod(String newNameMethod) {
700     nameMethod = newNameMethod;
701   }//setDocument
702 
703   public void setValueReturn(String newValueReturn) {
704     valueReturn = newValueReturn;
705   }//setValueReturn
706 
707   public void setParameterTypes(List newParameterTypes) {
708     parameterTypes = newParameterTypes;
709   }//setParameterTypes
710 
711   public void setExceptionTypes(List newExceptionTypes) {
712     exceptionTypes = newExceptionTypes;
713   }//setExceptionTypes
714 
715   public boolean equals(Object obj){
716     if(obj == null)
717       return false;
718     FeatureMethod other;
719     if(obj instanceof FeatureMethod){
720       other = (FeatureMethod) obj;
721     }else return false;
722 
723     // If their names are not equals then return false
724     if((nameMethod == null) ^ (other.getNameMethod() == null))
725       return false;
726     if(nameMethod != null && (!nameMethod.equals(other.getNameMethod())))
727       return false;
728 
729     // If their return values are not equals then return false
730     if((valueReturn == null) ^ (other.getValueReturn() == null))
731       return false;
732     if(valueReturn != null && (!valueReturn.equals(other.getValueReturn())))
733       return false;
734 
735     // If their parameters types are not equals then return false
736     if((parameterTypes == null) ^ (other.getParameterTypes() == null))
737       return false;
738     if(parameterTypes != null &&
739                             (!parameterTypes.equals(other.getParameterTypes())))
740       return false;
741 
742     // If their exceptions types are not equals then return false
743     if((exceptionTypes == null) ^ (other.getExceptionTypes() == null))
744       return false;
745     if(exceptionTypes != null &&
746                             (!exceptionTypes.equals(other.getExceptionTypes())))
747       return false;
748     return true;
749   }// equals
750 
751    public int hashCode(){
752     int hashCodeRes = 0;
753     if (nameMethod != null )
754        hashCodeRes ^= nameMethod.hashCode();
755     if (valueReturn != null)
756       hashCodeRes ^= valueReturn.hashCode();
757     if(exceptionTypes != null)
758       hashCodeRes ^= exceptionTypes.hashCode();
759     if(parameterTypes != null)
760       hashCodeRes ^= parameterTypes.hashCode();
761 
762     return  hashCodeRes;
763   }// hashCode
764 }// class FeatureMethod
765 
766