BootStrap.java
001 /*
002  *  BootStrap.java
003  *
004  *  Copyright (c) 1995-2012, 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 17590 2014-03-08 08:17:28Z markagreenwood $
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<String,String> names = null;
048 
049   protected Map<String,String> oldNames = null;
050 
051   /** the methods from the class that implements the resource*/
052   protected List<String> listMethodsResource = null;
053 
054   /** the list with the packages name where the main class can be find*/
055   protected List<String> listPackages;
056 
057   /** the packages used by the class which creates the resources */
058   protected Set<String> allPackages = null;
059 
060   /** the enumeration of the variables from main class*/
061   protected Map<Integer,String> 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<String,String>();
073 
074     oldNames = new HashMap<String,String>();
075 
076     listMethodsResource = new ArrayList<String>();
077 
078     listPackages = new ArrayList<String>();
079 
080     cbuffer = new char[BUFF_SIZE];
081 
082     allPackages = new HashSet<String>();
083 
084     fields = new HashMap<Integer,String>();
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<String,String> map ){
091 
092     Set<String> keys = map.keySet();
093     Iterator<String> iteratorKeys = keys.iterator();
094     while (iteratorKeys.hasNext()) {
095       String key = iteratorKeys.next();
096       String value = 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<String> 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<FeatureMethod> methodsInterfaces = new ArrayList<FeatureMethod>();
156     if (interfacesList!=null) {
157       interfacesAndClass = interfacesAndClass+ newLine+ "  implements ";
158       Iterator<String> iter = interfacesList.iterator();
159       while (iter.hasNext()) {
160         String nameInterface = 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         allPackages.add(currentClass.getPackage().getName()+".*");
173         
174         interfacesAndClass = interfacesAndClass + nameClass + ", ";
175 
176         methodsInterfaces = featuresClass(currentClass,methodsInterfaces);
177       }//while
178     }// if
179 
180     // add the abstract class
181     if (!interfacesList.contains("gate."+typeResource))
182       interfacesAndClass = interfacesAndClass + typeResource;
183     else if (interfacesAndClass.endsWith(", "))
184       interfacesAndClass = interfacesAndClass.substring
185                                             (0,interfacesAndClass.length()-2);
186 
187     // methods from the class that extends the resource
188     List<FeatureMethod> methodsClassExtend = new ArrayList<FeatureMethod>();
189     Class<?> currentClassExtend = Class.forName("gate.creole."+abstractClass);
190     methodsClassExtend = featuresClass(currentClassExtend, methodsClassExtend);
191 
192     // get the methods and fields for the main class
193     getMethodsAndFields(methodsClassExtend,methodsInterfaces);
194 
195     return interfacesAndClass;
196   // getInterfacesAndClass
197 
198   /**go through all methods and determines return type, parameters, exceptions*/
199   public List<FeatureMethod> featuresClass (Class<?> currentClass, List<FeatureMethod> methodsList){
200 
201     // go through all the methods
202     Method[] listMethodsCurrentClass = currentClass.getMethods();
203     for (int i=0;i<listMethodsCurrentClass.length;i++) {
204       FeatureMethod featureMethod = new FeatureMethod();
205       featureMethod.setNameMethod(listMethodsCurrentClass[i].getName());
206       featureMethod.setValueReturn(
207                           listMethodsCurrentClass[i].getReturnType().getName());
208 
209       Class<?>[] parameters = (
210                                 listMethodsCurrentClass[i].getParameterTypes());
211       Class<?>[] exceptions = (
212                                 listMethodsCurrentClass[i].getExceptionTypes());
213 
214       // determine the parameters for the current method
215       List<String> aux = new ArrayList<String>();
216       for (int k=0;k<parameters.length;k++)
217         aux.add(parameters[k].getName());
218       featureMethod.setParameterTypes(aux);
219 
220       // determine the exceptions for the current method
221       aux = new ArrayList<String>();
222       for (int k=0;k<exceptions.length;k++)
223         aux.add(exceptions[k].getName());
224       featureMethod.setExceptionTypes(aux);
225 
226       if (!methodsList.contains(featureMethod)){
227         methodsList.add(featureMethod);
228       }
229     }// for
230     return methodsList;
231   }// List featureClass (Class currentClass)
232 
233   /** create the form for the methods from the class that create the resource
234     @param methodsExtendList is the list with all methods from the class that extends
235     *  the resource
236     @param methodsInterfacesList is the list with all methods from the interfaces
237     * that implement the resource
238     */
239   public void getMethodsAndFields(List<FeatureMethod> methodsExtendList,
240                                                   List<FeatureMethod> methodsInterfacesList){
241     // determine all the methods from the interfaces which are not among the
242     // methods of the class that extends the resource
243 
244     int j = 0;
245     for (int i=0;i<methodsInterfacesList.size();i++) {
246       FeatureMethod featureMethod = methodsInterfacesList.get(i);
247       if (methodsExtendList.contains(featureMethod== false) {
248         // the name of the method
249         String nameMethod = (featureMethod.getNameMethod());
250 
251         // the types of the parameters of the method
252         List<String> valTypes = (featureMethod.getParameterTypes());
253 
254         // the value which the method returns
255         String typeReturn = determineTypePackage(
256                                       (featureMethod.getValueReturn()));
257 
258         // get the list of exceptions for the current method
259         List<String> valException = (featureMethod.getExceptionTypes());
260 
261         String declaration = "public "+ typeReturn +" "+
262                              nameMethod +"(";
263         // parameters
264         if (valTypes.size() == 0)
265           declaration = declaration+")";
266         else
267           for (int k=0;k<valTypes.size();k++) {
268             String type = valTypes.get(k);
269             if (type.endsWith("[]"))
270               declaration = declaration +
271                   determineTypePackage(type.substring(0,type.length()-2)) +
272                   " parameter"+ k;
273             else
274               declaration = declaration +
275                             determineTypePackage(valTypes.get(k)) +
276                             " parameter"+ k;
277 
278             if (k==valTypes.size()-1)
279               declaration = declaration + ")";
280             else
281               declaration = declaration + ", ";
282 
283           // for
284 
285         // exceptions
286         if (valException.size() == 0) {
287           if (!typeReturn.equals("void")){
288             if (!typeReturn.endsWith("[]"))
289               declaration = declaration + "{ " "return "+
290                             typeReturn.toLowerCase()+ j + "; }";
291             else
292               declaration = declaration + "{ " "return "+
293                             typeReturn.toLowerCase().substring(
294                             0,typeReturn.length()-2)+ j + "; }";
295 
296             fields.put(new Integer(j),typeReturn);
297             j =j+1;
298           }
299           else {declaration = declaration+" {}" ;}
300         // if
301         else {
302           declaration = declaration + newLine+ "                throws ";
303           for (int k=0;k<valException.size();k++) {
304             declaration = declaration + determineTypePackage(valException.get(k));
305 
306             if (k == valException.size()-1) {
307               if (!typeReturn.equals("void")){
308                 if (!typeReturn.endsWith("[]"))
309                   declaration = declaration + "{ " "return "+
310                           typeReturn.toLowerCase()+ j+"; }";
311                 else
312                   declaration = declaration + "{ " "return "+
313                             typeReturn.toLowerCase().substring(
314                             0,typeReturn.length()-2)+ j + "; }";
315 
316                 fields.put(new Integer(j),typeReturn);
317                 j=j+1;
318               }
319               else
320                 declaration = declaration+" {}" ;
321             else
322               declaration = declaration + ", ";
323 
324           // for
325         // else
326 
327         // add the form of the method
328         listMethodsResource.add(declaration);
329 
330       // if
331     // while
332 
333   // getMethodsAndFields
334 
335   /**
336     * write the methods and the fields in the right form
337     */
338   public String displayMethodsAndFields(List<String> methods, Map<Integer,String> fields) {
339 
340     String methodsFields = "";
341 
342     // go through all methods
343     Iterator<String> iterator = listMethodsResource.iterator();
344     while (iterator.hasNext()) {
345       methodsFields = methodsFields + newLine + iterator.next()+newLine;
346     }
347 
348     // go through all fields
349     Iterator<Integer> iter = fields.keySet().iterator();
350     while (iter.hasNext()) {
351       Integer index = iter.next();
352       String type = fields.get(index);
353       if (type.endsWith("[]"))
354         methodsFields = methodsFields + newLine + "protected " + type +" " +
355                        type.substring(0,type.length()-2).toLowerCase() +
356                         index.toString() +";";
357 
358       else
359         methodsFields = methodsFields + newLine + "protected " + type +" " +
360                         type.toLowerCase() + index.toString() +";";
361     }
362     return methodsFields;
363   }// displayMethodsAndFields(List methods, List fields)
364 
365 
366   /** create the map with variants of the names... */
367   public Map<String,String> createNames String packageName,
368                            String resourceName,
369                            String className,
370                            String stringPackages,
371                            String interfacesAndClass) {
372 
373      // all the packages from the class, which creates the resource
374     String packages = namesPackages(allPackages);
375 
376     // determine the name of the current user and the current day
377     Calendar calendar = Calendar.getInstance();
378     int month = calendar.get(Calendar.MONTH)+1;
379     int year = calendar.get(Calendar.YEAR);
380     int day = calendar.get(Calendar.DAY_OF_MONTH);
381     String date = day+"/"+month+"/"+year;
382     String user = System.getProperty("user.name");
383 
384     // the a map with the variants of names and the current date
385     // and the current user
386     names.put(nameProject,resourceName);
387     names.put(nameProject.toUpperCase(),resourceName.toUpperCase());
388     names.put(nameProject.toLowerCase(),resourceName.toLowerCase());
389     names.put("___CLASSNAME___",className);
390     names.put("___INTERFACES___",interfacesAndClass);
391     names.put("___CONTENT___",
392                           displayMethodsAndFields(listMethodsResource,fields));
393     names.put("___DATE___",date);
394     names.put("___AUTHOR___",user);
395     // "___ALLPACKAGE___" is the packages separated by "/"
396     // e.g. "sheffied/creole/tokeniser"
397     names.put("___ALLPACKAGES___",stringPackages);
398     // "___PACKAGE___" is the packages separated by "."
399     // e.g. "sheffied.creole.tokeniser"
400     names.put("___PACKAGE___",packageName);
401     names.put("___PACKAGETOP___",listPackages.get(0));
402     names.put("___RESOURCE___",resourceName);;
403     names.put(
404       "___GATECLASSPATH___",
405       System.getProperty("path.separator"+
406         System.getProperty("java.class.path")
407     );
408     // ___GATEHOME___ is the GATE home dir, in the form suitable for an Ant
409     // property
410     File gateHome = gate.Gate.getGateHome();
411     if(gateHome == null) {
412       // put a fake gate home location in here if we can't get the real one
413       names.put("___GATEHOME___",
414           gate.Gate.runningOnUnix() "/path/to/gate"
415                                     "C:/Program Files/GATE");
416     }
417     else {
418       names.put("___GATEHOME___",
419           gateHome.getPath().replace('\\''/'));
420     }
421 
422     if (packages.length() == 0){
423       names.put("import ___packages___.*;""");
424     else {
425       names.put("import ___packages___.*;", packages);
426     }
427 
428     oldNames.put("___PACKAGE___","template");
429     oldNames.put("___ALLPACKAGES___","template");
430     oldNames.put("___PACKAGETOP___","template");
431 
432     return names;
433   }// End createNames()
434 
435   /** determine all the packages */
436   public String namesPackages (Set<String> listPackages) {
437     Iterator<String> iterator = listPackages.iterator();
438     String packages = new String();
439     while (iterator.hasNext()) {
440       String currentPackage = iterator.next();
441       if ((!currentPackage.equals("gate.*"))&&
442          (!currentPackage.equals("gate.creole.*"))&&
443          (!currentPackage.equals("gate.util.*"))&&
444          (!currentPackage.equals("java.util.*")))
445           packages = packages + newLine + "import "+ currentPackage+";";
446     }// while
447     return packages;
448   }
449 
450   /** determines the name of the packages and adds them to a list
451     */
452   public List<String> determinePath (String packageName)throws IOException {
453     List<String> list = new ArrayList<String>();
454     StringTokenizer token = new StringTokenizer(packageName,".");
455     //if (token.countTokens()>1) {
456       while (token.hasMoreTokens()) {
457         list.add(token.nextToken());
458       }
459     //} else list.add(packageName);
460     return list;
461   }
462 
463   /** verify if the class name contains only letters and digits
464    *  the path of the new project is a directory
465    */
466   public void verifyInput(String className, String pathNewProject)
467                           throws GateException {
468     // verify the input
469     // class name contains only letters and digits
470     char[] classNameChars = className.toCharArray();
471     for (int i=0;i<classNameChars.length;i++){
472       if (!Character.isLetterOrDigit(classNameChars[i]))
473         throw new GateException("Only letters and digits in the class name");
474     }
475 
476     // verify if it exits a directory of given path
477     File dir = new File(pathNewProject);
478     if (!dir.isDirectory())
479       throw new GateException("The folder is not a directory");
480   }
481 
482   /***/
483   public void executableFile(String nameFile)
484                                     throws IOException,InterruptedException{
485     String osName = System.getProperty("os.name" );
486     if( !osName.startsWith("Windows") ){
487       Runtime rt = Runtime.getRuntime();
488       Process proc = rt.exec("chmod 711 "+nameFile);
489 
490       // any error???
491       int exitVal = proc.waitFor();
492       if (exitVal!=0)
493         Out.prln("Warning: it is necessary to make executable the "+
494           "following file: " + nameFile);
495     }//if
496   }// executableFile
497 
498   /**  Creates the resource and dumps out a project structure using the
499     *  structure from gate/resource/creole/bootstrap/Template and the
500     *  information provided by the user
501     @param resourceName is the name of the resource
502     @param packageName is the name of the new resource
503     @param typeResource is the type of the resource (e.g.ProcessingResource,
504     *  LanguageResource or VisualResource)
505     @param className is the name of the class which implements the resource
506     @param interfacesList is the set of the interfaces that implements the resource
507     @param pathNewProject is the path where it will be the new resource
508     */
509   public void createResourceString resourceName,String packageName,
510                               String typeResource,String className,
511                               Set<String> interfacesList,String pathNewProject)
512                               throws
513                               IOException,ClassNotFoundException,
514                               GateException,InterruptedException {
515     // the current file created by the system
516     File newFile = null;
517 
518     // define for reading from a file.properties
519     Properties properties = new Properties();
520 
521     // the new path of the current file
522     String newPathFile = null;
523 
524     // the path of file from template project
525     String oldPathFile = null;
526 
527     // verify the input
528     verifyInput(className,pathNewProject);
529 
530     // determine the interfaces that the resource implements and the class
531     // that it extends
532     String interfacesAndClass = getInterfacesAndClass (typeResource,
533                                                   interfacesList);
534 
535     //determine the list with packages
536     listPackages = determinePath(packageName);
537 
538     //add "/" at the end of the path of project
539     if (!pathNewProject.endsWith("/")) pathNewProject = pathNewProject + "/";
540 
541     // determine the path of the main class
542     String stringPackages = listPackages.get(0);
543     for (int i=1;i<listPackages.size();i++) {
544       stringPackages = stringPackages + "/"+listPackages.get(i);
545     }
546 
547     // create the map with the names
548     createNames(packageName,resourceName,className,
549                                             stringPackages,interfacesAndClass);
550 
551     // take the content of the file with the structure of the template project
552     InputStream inputStream = Files.getGateResourceAsStream(oldResource +
553                               "file-list.properties");
554 
555     // put all the files and directories
556     properties.load(inputStream);
557 
558     // close the input stream
559     inputStream.close();
560 
561     // firstly create the directories
562     String oldDirectories = properties.getProperty("directories");
563     StringTokenizer token = new StringTokenizer(oldDirectories,",");
564     while (token.hasMoreTokens()) {
565       String propPathDirectory = token.nextToken();
566       if (propPathDirectory.endsWith("___ALLPACKAGES___")) {
567         //create every directory from the path of package
568         newPathFile =
569           propPathDirectory.substring(0,propPathDirectory.length()-18);
570         // change the path according to input
571         newPathFile = changeKeyValue(newPathFile,names);
572         for (int i=0;i<listPackages.size();i++) {
573           newPathFile = newPathFile + "/"+listPackages.get(i);
574           newFile = new File(pathNewProject + newPathFile);
575           newFile.mkdir();
576         }//for
577       else {
578         newPathFile = changeKeyValue(propPathDirectory,names);
579         // change the path according to input
580         newFile = new File(pathNewProject + newPathFile);
581         newFile.mkdir();
582       }//else
583     }// while
584 
585     // secondly, create the files
586     Enumeration<?> keyProperties = properties.propertyNames();
587     // goes through all the files from the template project
588     while (keyProperties.hasMoreElements()) {
589       String key = (String)keyProperties.nextElement();
590       if (!key.equals("directories")) {
591         String oldFiles = properties.getProperty(key);
592         token = new StringTokenizer(oldFiles,",");
593         //go through all the files
594         while (token.hasMoreTokens()) {
595           String propPathFiles = token.nextToken();
596           oldPathFile = changeKeyValue(propPathFiles,oldNames);
597 
598           // change the path according to input
599           newPathFile = changeKeyValue(propPathFiles,names);
600 
601           // change the extension of the current file from "jav" to "java"
602           if (newPathFile.endsWith("jav")) newPathFile = newPathFile +"a";
603 
604           // the content of the current file is copied on the disk
605 
606           // the current file for writing characters
607           newFile = new File(pathNewProject+newPathFile);
608 
609           //create a filewriter for writing
610           FileWriter fileWriter = new FileWriter(newFile);
611 
612           // get the input stream from
613           InputStream currentInputStream =
614               Files.getGateResourceAsStream(oldResource+oldPathFile);
615 
616           Reader inputStreamReader = new BomStrippingInputStreamReader(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<String> interfaces = new HashSet<String>();
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 (ClassNotFoundException cnfe) {
656       cnfe.printStackTrace(Err.getPrintWriter());
657     catch (IOException ioe) {
658       ioe.printStackTrace(Err.getPrintWriter());
659     catch (InterruptedException ie){
660       ie.printStackTrace(Err.getPrintWriter());
661     }
662   }// main
663 
664 // class BootStrap
665 
666 /** FeatureMethod is a class encapsulating
667   * information about the feature of a method such as the name, the return
668   * type, the parameters types or exceptions types
669   */
670 class FeatureMethod {
671   /** the name of the method*/
672   protected String nameMethod;
673 
674   /** the return value*/
675   protected String valueReturn;
676 
677   /** the list with the types of the parameters */
678   protected List<String> parameterTypes;
679 
680   /** the list with the types of the exceptions */
681   protected List<String> exceptionTypes;
682 
683   FeatureMethod() {
684     nameMethod = new String();
685     valueReturn = new String();
686     parameterTypes = new ArrayList<String>();
687     exceptionTypes = new ArrayList<String>();
688   }
689 
690   public String getNameMethod() {
691     return nameMethod;
692   }//getNameMethod
693 
694   public String getValueReturn() {
695     return valueReturn;
696   }//getValueReturn
697 
698   public List<String> getParameterTypes() {
699     return parameterTypes;
700   }//getParameterTypes
701 
702   public List<String> getExceptionTypes() {
703     return exceptionTypes;
704   }//getExceptionTypes
705 
706   public void setNameMethod(String newNameMethod) {
707     nameMethod = newNameMethod;
708   }//setDocument
709 
710   public void setValueReturn(String newValueReturn) {
711     valueReturn = newValueReturn;
712   }//setValueReturn
713 
714   public void setParameterTypes(List<String> newParameterTypes) {
715     parameterTypes = newParameterTypes;
716   }//setParameterTypes
717 
718   public void setExceptionTypes(List<String> newExceptionTypes) {
719     exceptionTypes = newExceptionTypes;
720   }//setExceptionTypes
721 
722   @Override
723   public boolean equals(Object obj){
724     if(obj == null)
725       return false;
726     FeatureMethod other;
727     if(obj instanceof FeatureMethod){
728       other = (FeatureMethodobj;
729     }else return false;
730 
731     // If their names are not equals then return false
732     if((nameMethod == null(other.getNameMethod() == null))
733       return false;
734     if(nameMethod != null && (!nameMethod.equals(other.getNameMethod())))
735       return false;
736 
737     // If their return values are not equals then return false
738     if((valueReturn == null(other.getValueReturn() == null))
739       return false;
740     if(valueReturn != null && (!valueReturn.equals(other.getValueReturn())))
741       return false;
742 
743     // If their parameters types are not equals then return false
744     if((parameterTypes == null(other.getParameterTypes() == null))
745       return false;
746     if(parameterTypes != null &&
747                             (!parameterTypes.equals(other.getParameterTypes())))
748       return false;
749 
750     // If their exceptions types are not equals then return false
751     if((exceptionTypes == null(other.getExceptionTypes() == null))
752       return false;
753     if(exceptionTypes != null &&
754                             (!exceptionTypes.equals(other.getExceptionTypes())))
755       return false;
756     return true;
757   }// equals
758 
759    @Override
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