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