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