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