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