1   /*
2    *  CreoleRegisterImpl.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   *  Hamish Cunningham, 1/Sept/2000
12   *
13   *  $Id: CreoleRegisterImpl.java,v 1.51 2002/02/26 10:30:07 valyt Exp $
14   */
15  
16  package gate.creole;
17  
18  import java.util.*;
19  import java.net.*;
20  import java.io.*;
21  
22  import org.xml.sax.*;
23  import javax.xml.parsers.*;
24  import org.xml.sax.helpers.*;
25  
26  import gate.*;
27  import gate.util.*;
28  import gate.event.*;
29  
30  
31  /** This class implements the CREOLE register interface. DO NOT
32    * construct objects of this class unless your name is gate.Gate
33    * (in which case please go back to the source code repository and stop
34    * looking at other class's code).
35    * <P>
36    * The CREOLE register records the set of resources that are currently
37    * known to the system. Each member of the register is a
38    * {@link gate.creole.ResourceData} object, indexed by
39    * the class name of the resource.
40    * @see gate.CreoleRegister
41    */
42  public class CreoleRegisterImpl extends HashMap
43            implements CreoleRegister, CreoleListener
44  {
45    /** Debug flag */
46    protected static final boolean DEBUG = false;
47  
48    /** The set of CREOLE directories (URLs). */
49    protected Set directories;
50  
51    /** The parser for the CREOLE directory files */
52    protected transient SAXParser parser = null;
53  
54    /**
55     * Default constructor. Sets up directory files parser. <B>NOTE:</B>
56     * only Factory should call this method.
57     */
58    public CreoleRegisterImpl() throws GateException {
59  
60      // initialise the various maps
61      directories = new HashSet();
62      lrTypes = new HashSet();
63      prTypes = new HashSet();
64      vrTypes = new LinkedList();
65      toolTypes = new HashSet();
66  
67      // construct a SAX parser for parsing the CREOLE directory files
68      try {
69        // Get a parser factory.
70        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
71  
72        // Set up the factory to create the appropriate type of parser:
73        // non validating one
74        saxParserFactory.setValidating(false);
75        // non namespace aware one
76        saxParserFactory.setNamespaceAware(true);
77  
78        // create the parser
79        parser = saxParserFactory.newSAXParser();
80  
81      } catch (SAXException e) {
82        if(DEBUG) Out.println(e);
83        throw(new GateException(e));
84      } catch (ParserConfigurationException e) {
85        if(DEBUG) Out.println(e);
86        throw(new GateException(e));
87      }
88  
89    } // default constructor
90  
91    /** Add a CREOLE directory URL to the register and to the GATE classloader.
92      * The directory is <B>not</B> registered.
93      */
94    public void addDirectory(URL directoryUrl) {
95      directories.add(directoryUrl);
96    } // addDirectory
97  
98    /** Get the list of CREOLE directory URLs. */
99    public Set getDirectories() {
100     return Collections.unmodifiableSet(directories);
101   } // getDirectories
102 
103   /** Register all the CREOLE directories that we know of.
104     * The <CODE>creole.xml</CODE> files
105     * at the URLs are parsed, and <CODE>ResourceData</CODE> objects added
106     * to the register.
107     * URLs for resource JAR files are added to the GATE class loader.
108     */
109   public void registerDirectories() throws GateException {
110     Iterator iter = directories.iterator();
111 
112     while(iter.hasNext()) {
113       URL directoryUrl = (URL) iter.next();
114       registerDirectories(directoryUrl);
115     }
116   } // registerDirectories
117 
118   /** Register a single CREOLE directory. The <CODE>creole.xml</CODE>
119     * file at the URL is parsed, and <CODE>CreoleData</CODE> objects added
120     * to the register. If the directory URL has not yet been added it
121     * is now added.
122     * URLs for resource JAR files are added to the GATE class loader.
123     */
124   public void registerDirectories(URL directoryUrl) throws GateException {
125 
126     // directory URLs shouldn't include "creole.xml"
127     String urlName = directoryUrl.toExternalForm();
128     if(urlName.toLowerCase().endsWith("creole.xml")) {
129       throw new GateException(
130         "CREOLE directory URLs should point to the parent location of " +
131         "the creole.xml file, not the file itself; bad URL was: " + urlName
132       );
133     }
134 
135     // create a URL for the creole.xml file, based on the directory URL
136     URL directoryXmlFileUrl = directoryUrl;
137     String separator = "/";
138     if(urlName.endsWith(separator)) separator = "";
139     try {
140       directoryXmlFileUrl = new URL(urlName + separator + "creole.xml");
141     } catch(MalformedURLException e) {
142       throw(new GateException("bad creole.xml URL, based on " + urlName));
143     }
144 
145     // add the URL
146     //if already present do nothing
147     directories.add(directoryUrl);
148     // parse the directory file
149     try {
150       parseDirectory(directoryXmlFileUrl.openStream(), directoryUrl);
151     } catch(IOException e) {
152       throw(new GateException("couldn't open creole.xml: " + e.toString()));
153     }
154   } // registerDirectories(URL)
155 
156   /** Parse a directory file (represented as an open stream), adding
157     * resource data objects to the CREOLE register as they occur.
158     * If the resource is from a URL then that location is passed (otherwise
159     * null).
160     */
161   protected void parseDirectory(InputStream directoryStream, URL directoryUrl)
162   throws GateException
163   {
164     // create a handler for the directory file and parse it;
165     // this will create ResourceData entries in the register
166     try {
167       DefaultHandler handler = new CreoleXmlHandler(this, directoryUrl);
168       parser.parse(directoryStream, handler);
169       if(DEBUG) {
170         Out.prln(
171           "done parsing " +
172           ((directoryUrl == null) ? "null" : directoryUrl.toString())
173         );
174       }
175     } catch (IOException e) {
176       throw(new GateException(e));
177     } catch (SAXException e) {
178       if(DEBUG) Out.println(e.toString());
179       throw(new GateException(e));
180     }
181 
182   } // parseDirectory
183 
184   /** Register resources that are built in to the GATE distribution.
185     * These resources are described by the <TT>creole.xml</TT> file in
186     * <TT>resources/creole</TT>.
187     */
188   public void registerBuiltins() throws GateException {
189 
190     try {
191       parseDirectory(
192         new URL("gate:/creole/creole.xml").openStream(),
193         new URL("gate:/creole/")
194       );
195     } catch(IOException e) {
196       if (DEBUG) Out.println(e);
197       throw(new GateException(e));
198     }
199   } // registerBuiltins()
200 
201   /** This is a utility method for creating CREOLE directory files
202     * (typically called <CODE>creole.xml</CODE>) from a list of Jar
203     * files that contain resources. The method concatenates the
204     * <CODE>resource.xml</CODE> files that the Jars contain.
205     * <P>
206     * If Java allowed class methods in interfaces this would be static.
207     */
208   public File createCreoleDirectoryFile(File directoryFile, Set jarFileNames)
209   {
210     ////////////////////
211     // dump xml header and comment header and <CREOLE-DIRECTORY> into dirfile
212     // for each jar file pick out resource.xml
213     // strip xml header
214     // dump into dirfile
215     // put </CREOLE-DIRECTORY> into dirfile
216     throw new LazyProgrammerException();
217   } // createCreoleDirectoryFile
218 
219   /** Overide HashMap's put method to maintain a list of all the
220     * types of LR in the register, and a list of tool types. The key is
221     * the resource type, the value its data.
222     */
223   public Object put(Object key, Object value) {
224     ResourceData rd = (ResourceData) value;
225 
226     // get the resource implementation class
227     Class resClass = null;
228     try {
229       resClass = rd.getResourceClass();
230     } catch(ClassNotFoundException e) {
231       throw new GateRuntimeException(
232         "Couldn't get resource class from the resource data:" + e
233       );
234     }
235 
236     // add class names to the type lists
237     if(LanguageResource.class.isAssignableFrom(resClass)) {
238       if(DEBUG) Out.prln("LR: " + resClass);
239       if(lrTypes == null) lrTypes = new HashSet(); // for deserialisation
240       lrTypes.add(rd.getClassName());
241     } else if(ProcessingResource.class.isAssignableFrom(resClass)) {
242       if(DEBUG) {
243         Out.prln("PR: " + resClass);
244         //Out.prln("prTypes: " + prTypes);
245         //Out.prln("rd.getClassName(): " + rd.getClassName());
246       }
247       if(prTypes == null) prTypes = new HashSet(); // for deserialisation
248       prTypes.add(rd.getClassName());
249     } else if(VisualResource.class.isAssignableFrom(resClass)) {
250       if(DEBUG) Out.prln("VR: " + resClass);
251       if(vrTypes == null) vrTypes = new LinkedList(); // for deserialisation
252       //we have to simulate Set behaviour as this is a list
253       if(!vrTypes.contains(rd.getClassName())) vrTypes.add(rd.getClassName());
254     }else if(Controller.class.isAssignableFrom(resClass)) {
255       if(DEBUG) Out.prln("Controller: " + resClass);
256       if(controllerTypes == null) controllerTypes = new HashSet(); // for deserialisation
257       controllerTypes.add(rd.getClassName());
258     }
259 
260     // maintain tool types list
261     if(rd.isTool()) {
262       if(toolTypes == null) toolTypes = new HashSet(); // for deserialisation
263       toolTypes.add(rd.getClassName());
264     }
265 
266     return super.put(key, value);
267   } // put(key, value)
268 
269   /** Overide HashMap's delete method to update the lists of types
270     * in the register.
271     */
272   public Object remove(Object key) {
273     ResourceData rd = (ResourceData) get(key);
274     if(rd == null) return null;
275 
276     if(DEBUG) {
277       Out.prln(key);
278       Out.prln(rd);
279     }
280     if(LanguageResource.class.isAssignableFrom(rd.getClass()))
281       lrTypes.remove(rd.getClassName());
282     else if(ProcessingResource.class.isAssignableFrom(rd.getClass()))
283       prTypes.remove(rd.getClassName());
284     else if(VisualResource.class.isAssignableFrom(rd.getClass()))
285       vrTypes.remove(rd.getClassName());
286 
287     // maintain tool types list
288     if(rd.isTool())
289       toolTypes.remove(rd.getClassName());
290 
291     return super.remove(key);
292   } // remove(Object)
293 
294   /** Overide HashMap's clear to update the list of LR types in the register,
295     * and remove all resources and forgets all directories.
296     */
297   public void clear() {
298     lrTypes.clear();
299     prTypes.clear();
300     vrTypes.clear();
301     toolTypes.clear();
302     directories.clear();
303     super.clear();
304   } // clear()
305 
306   /** Get the list of types of LR in the register. */
307   public Set getLrTypes() { return Collections.unmodifiableSet(lrTypes);}
308 
309   /** Get the list of types of PR in the register. */
310   public Set getPrTypes() { return Collections.unmodifiableSet(prTypes);}
311 
312   /** Get the list of types of VR in the register. */
313   public Set getVrTypes() { return Collections.unmodifiableSet(new HashSet(vrTypes));}
314 
315   /** Get the list of types of VR in the register. */
316   public Set getControllerTypes() {
317     return Collections.unmodifiableSet(controllerTypes);
318   }
319 
320   /** Get the list of types of TOOL respurces in the register. */
321   public Set getToolTypes() { return Collections.unmodifiableSet(toolTypes);}
322 
323   /** Get a list of all instantiations of LR in the register. */
324   public List getLrInstances() {
325     Set lrTypeSet = getLrTypes();
326     List instances = new ArrayList();
327 
328     Iterator iter = lrTypeSet.iterator();
329     while(iter.hasNext()) {
330       String type = (String) iter.next();
331       instances.addAll(getLrInstances(type));
332     }// End while
333     return Collections.unmodifiableList(instances);
334   } // getLrInstances()
335 
336   /** Get a list of all instantiations of PR in the register. */
337   public List getPrInstances() {
338     Set prTypeSet = getPrTypes();
339     List instances = new ArrayList();
340 
341     Iterator iter = prTypeSet.iterator();
342     while(iter.hasNext()) {
343       String type = (String) iter.next();
344       instances.addAll(getPrInstances(type));
345     }// End while
346 
347     return Collections.unmodifiableList(instances);
348   } // getPrInstances()
349 
350   /** Get a list of all instantiations of VR in the register. */
351   public List getVrInstances() {
352     Set vrTypeSet = getVrTypes();
353     List instances = new ArrayList();
354 
355     Iterator iter = vrTypeSet.iterator();
356     while(iter.hasNext()) {
357       String type = (String) iter.next();
358       instances.addAll(getVrInstances(type));
359     }// End while
360 
361     return Collections.unmodifiableList(instances);
362   } // getVrInstances()
363 
364   /** Get a list of instantiations of a type of LR in the register. */
365   public List getLrInstances(String resourceTypeName) {
366     ResourceData resData = (ResourceData) get(resourceTypeName);
367     if(resData == null)
368       return Collections.unmodifiableList(new ArrayList());
369 
370     return Collections.unmodifiableList(resData.getInstantiations());
371   } // getLrInstances
372 
373   /** Get a list of instantiations of a type of PR in the register. */
374   public List getPrInstances(String resourceTypeName) {
375     ResourceData resData = (ResourceData) get(resourceTypeName);
376     if(resData == null)
377       return Collections.unmodifiableList(new ArrayList());
378 
379     return Collections.unmodifiableList(resData.getInstantiations());
380   } // getPrInstances
381 
382   /** Get a list of instantiations of a type of VR in the register. */
383   public List getVrInstances(String resourceTypeName) {
384     ResourceData resData = (ResourceData) get(resourceTypeName);
385     if(resData == null)
386       return Collections.unmodifiableList(new ArrayList());
387 
388     return Collections.unmodifiableList(resData.getInstantiations());
389   } // getVrInstances
390 
391   /** Get a list of all non-private instantiations of LR in the register. */
392   public List getPublicLrInstances() {
393     return Collections.unmodifiableList(getPublics(getLrInstances()));
394   }// getPublicLrInstances()
395 
396   /** Get a list of all non-private instantiations of PR in the register. */
397   public List getPublicPrInstances() {
398     return Collections.unmodifiableList(getPublics(getPrInstances()));
399   }// getPublicPrInstances()
400 
401   /** Get a list of all non-private instantiations of VR in the register. */
402   public List getPublicVrInstances() {
403     return Collections.unmodifiableList(getPublics(getVrInstances()));
404   }//getPublicVrInstances()
405 
406   /** Get a list of all non-private types of LR in the register. */
407   public List getPublicLrTypes() {
408     return Collections.unmodifiableList(getPublicTypes(getLrTypes()));
409   }//getPublicLrTypes()
410 
411   /** Get a list of all non-private types of PR in the register. */
412   public List getPublicPrTypes() {
413     return Collections.unmodifiableList(getPublicTypes(getPrTypes()));
414   }//getPublicPrTypes()
415 
416   /** Get a list of all non-private types of VR in the register. */
417   public List getPublicVrTypes() {
418     return Collections.unmodifiableList(getPublicTypes(getVrTypes()));
419   }//getPublicVrTypes()
420 
421   /** Get a list of all non-private types of controller in the register. */
422   public List getPublicControllerTypes() {
423     return Collections.unmodifiableList(getPublicTypes(getControllerTypes()));
424   }//getPublicPrTypes()
425 
426 
427   /**
428    * Gets all the instantiations of a given type and all its derivate types;
429    * It doesn't return instances that have the hidden attribute set to "true"
430    */
431   public List getAllInstances(String type) throws GateException{
432     Iterator typesIter = keySet().iterator();
433     List res = new ArrayList();
434     Class targetClass;
435     try{
436       targetClass = Gate.getClassLoader().loadClass(type);
437     }catch(ClassNotFoundException cnfe){
438       throw new GateException("Invalid type " + type);
439     }
440     while(typesIter.hasNext()){
441       String aType = (String)typesIter.next();
442       Class aClass;
443       try{
444         aClass = Gate.getClassLoader().loadClass(aType);
445         if(targetClass.isAssignableFrom(aClass)){
446           //filter out hidden instances
447           Iterator newInstancesIter = ((ResourceData)get(aType)).
448                                       getInstantiations().iterator();
449           while(newInstancesIter.hasNext()){
450             Resource instance = (Resource)newInstancesIter.next();
451             if(!Gate.getHiddenAttribute(instance.getFeatures())){
452               res.add(instance);
453             }
454           }
455         }
456       }catch(ClassNotFoundException cnfe){
457         throw new LuckyException(
458           "A type registered in the creole register does not exist in the VM!");
459       }
460 
461     }//while(typesIter.hasNext())
462 
463     return res;
464   }
465 
466   /**
467    * Returns a list of strings representing class names for large VRs valid
468    * for a given type of language/processing resource.
469    * The default VR will be the first in the returned list.
470    * @param resoureClassName the name of the resource that has large viewers. If
471    * resourceClassName is <b>null</b> then an empty list will be returned.
472    * @return a list with Strings representing the large VRs for the
473    * resourceClassName
474    */
475   public List getLargeVRsForResource(String resourceClassName){
476     return getVRsForResource(resourceClassName, ResourceData.LARGE_GUI);
477   }// getLargeVRsForResource()
478 
479   /**
480    * Returns a list of strings representing class names for small VRs valid
481    * for a given type of language/processing resource
482    * The default VR will be the first in the returned list.
483    * @param resoureClassName the name of the resource that has large viewers. If
484    * resourceClassName is <b>null</b> then an empty list will be returned.
485    * @return a list with Strings representing the large VRs for the
486    * resourceClassName
487    */
488   public List getSmallVRsForResource(String resourceClassName){
489     return getVRsForResource(resourceClassName, ResourceData.SMALL_GUI);
490   }// getSmallVRsForResource
491 
492   /**
493    * Returns a list of strings representing class names for guiType VRs valid
494    * for a given type of language/processing resource
495    * The default VR will be the first in the returned list.
496    * @param resoureClassName the name of the resource that has large viewers. If
497    * resourceClassName is <b>null</b> then an empty list will be returned.
498    * @param guiType can be ResourceData's LARGE_GUI or SMALL_GUI
499    * @return a list with Strings representing the large VRs for the
500    * resourceClassName
501    */
502   private List getVRsForResource(String resourceClassName, int guiType){
503     // If resurceClassName is null return a simply list
504     if (resourceClassName == null)
505       return Collections.unmodifiableList(new ArrayList());
506     // create a Class object for the resource
507     Class resourceClass = null;
508     GateClassLoader classLoader = Gate.getClassLoader();
509     try{
510       resourceClass = classLoader.loadClass(resourceClassName);
511     } catch (ClassNotFoundException ex){
512       throw new GateRuntimeException(
513         "Couldn't get resource class from the resource name:" + ex
514       );
515     }// End try
516     LinkedList responseList = new LinkedList();
517     String defaultVR = null;
518     // Take all VRs and for each large one, test if
519     // resourceClassName is asignable form VR's RESOURCE_DISPLAYED
520     Iterator vrIterator = vrTypes.iterator();
521     while (vrIterator.hasNext()){
522       String vrClassName = (String) vrIterator.next();
523       ResourceData vrResourceData = (ResourceData) this.get(vrClassName);
524       if (vrResourceData == null)
525         throw new GateRuntimeException(
526           "Couldn't get resource data for VR called " + vrClassName
527         );
528       if (vrResourceData.getGuiType() == guiType){
529         String resourceDisplayed = vrResourceData.getResourceDisplayed();
530         if (resourceDisplayed != null){
531           Class resourceDisplayedClass = null;
532           try{
533             resourceDisplayedClass = classLoader.loadClass(resourceDisplayed);
534           } catch (ClassNotFoundException ex){
535               throw new GateRuntimeException(
536                 "Couldn't get resource class from the resource name :" +
537                 resourceDisplayed + " " +ex );
538           }// End try
539           if (resourceDisplayedClass.isAssignableFrom(resourceClass)){
540             responseList.add(vrClassName);
541             if (vrResourceData.isMainView()){
542               defaultVR = vrClassName;
543             }// End if
544           }// End if
545         }// End if
546       }// End if
547     }// End while
548     if (defaultVR != null){
549       responseList.remove(defaultVR);
550       responseList.addFirst(defaultVR);
551     }// End if
552     return Collections.unmodifiableList(responseList);
553   }// getVRsForResource()
554 
555   /**
556    * Returns a list of strings representing class names for annotation VRs
557    * that are able to display/edit all types of annotations.
558    * The default VR will be the first in the returned list.
559    * @return a list with all VRs that can display all annotation types
560    */
561   public List getAnnotationVRs(){
562     LinkedList responseList = new LinkedList();
563     String defaultVR = null;
564     Iterator vrIterator = vrTypes.iterator();
565     while (vrIterator.hasNext()){
566       String vrClassName = (String) vrIterator.next();
567       ResourceData vrResourceData = (ResourceData) this.get(vrClassName);
568       if (vrResourceData == null)
569         throw new GateRuntimeException(
570           "Couldn't get resource data for VR called " + vrClassName
571         );
572       Class vrResourceClass = null;
573       try{
574         vrResourceClass = vrResourceData.getResourceClass();
575       } catch(ClassNotFoundException ex){
576         throw new GateRuntimeException(
577           "Couldn't create a class object for VR called " + vrClassName
578         );
579       }// End try
580       // Test if VR can display all types of annotations
581       if ( vrResourceData.getGuiType() == ResourceData.NULL_GUI &&
582            vrResourceData.getAnnotationTypeDisplayed() == null &&
583            vrResourceData.getResourceDisplayed() == null &&
584            gate.creole.AnnotationVisualResource.class.
585                                           isAssignableFrom(vrResourceClass)){
586 
587           responseList.add(vrClassName);
588           if (vrResourceData.isMainView())
589               defaultVR = vrClassName;
590       }// End if
591     }// End while
592     if (defaultVR != null){
593       responseList.remove(defaultVR);
594       responseList.addFirst(defaultVR);
595     }// End if
596     return Collections.unmodifiableList(responseList);
597   }// getAnnotationVRs()
598 
599   /**
600    * Returns a list of strings representing class names for annotation VRs
601    * that are able to display/edit a given annotation type
602    * The default VR will be the first in the returned list.
603    */
604   public List getAnnotationVRs(String annotationType){
605     if (annotationType == null)
606       return Collections.unmodifiableList(new ArrayList());
607     LinkedList responseList = new LinkedList();
608     String defaultVR = null;
609     Iterator vrIterator = vrTypes.iterator();
610     while (vrIterator.hasNext()){
611       String vrClassName = (String) vrIterator.next();
612       ResourceData vrResourceData = (ResourceData) this.get(vrClassName);
613       if (vrResourceData == null)
614         throw new GateRuntimeException(
615           "Couldn't get resource data for VR called " + vrClassName
616         );
617       Class vrResourceClass = null;
618       try{
619         vrResourceClass = vrResourceData.getResourceClass();
620       } catch(ClassNotFoundException ex){
621         throw new GateRuntimeException(
622           "Couldn't create a class object for VR called " + vrClassName
623         );
624       }// End try
625       // Test if VR can display all types of annotations
626       if ( vrResourceData.getGuiType() == ResourceData.NULL_GUI &&
627            vrResourceData.getAnnotationTypeDisplayed() != null &&
628            gate.creole.AnnotationVisualResource.class.
629                                           isAssignableFrom(vrResourceClass)){
630 
631           String annotationTypeDisplayed =
632                                   vrResourceData.getAnnotationTypeDisplayed();
633           if (annotationTypeDisplayed.equals(annotationType)){
634             responseList.add(vrClassName);
635             if (vrResourceData.isMainView())
636               defaultVR = vrClassName;
637           }// End if
638       }// End if
639     }// End while
640     if (defaultVR != null){
641       responseList.remove(defaultVR);
642       responseList.addFirst(defaultVR);
643     }// End if
644     return Collections.unmodifiableList(responseList);
645   }//getAnnotationVRs()
646 
647    /**
648     * Renames an existing resource.
649     */
650    public void setResourceName(Resource res, String newName){
651     String oldName = res.getName();
652     res.setName(newName);
653     fireResourceRenamed(res, oldName, newName);
654    }
655 
656 
657   /**
658    * Returns a list of strings representing annotations types for which
659    * there are custom viewers/editor registered.
660    */
661   public List getVREnabledAnnotationTypes(){
662     LinkedList responseList = new LinkedList();
663     Iterator vrIterator = vrTypes.iterator();
664     while (vrIterator.hasNext()){
665       String vrClassName = (String) vrIterator.next();
666       ResourceData vrResourceData = (ResourceData) this.get(vrClassName);
667       if (vrResourceData == null)
668         throw new GateRuntimeException(
669           "Couldn't get resource data for VR called " + vrClassName
670         );
671       // Test if VR can display all types of annotations
672       if ( vrResourceData.getGuiType() == ResourceData.NULL_GUI &&
673            vrResourceData.getAnnotationTypeDisplayed() != null ){
674 
675           String annotationTypeDisplayed =
676                                   vrResourceData.getAnnotationTypeDisplayed();
677           responseList.add(annotationTypeDisplayed);
678       }// End if
679     }// End while
680     return Collections.unmodifiableList(responseList);
681   }// getVREnabledAnnotationTypes()
682 
683 
684 
685   /** Get a list of all non-private instantiations. */
686   protected List getPublics(List instances) {
687     Iterator iter = instances.iterator();
688     List publics = new ArrayList();
689 
690     // for each instance, if resource data specifies it isn't private,
691     // add to the publics list
692     while(iter.hasNext()) {
693       Resource res = (Resource) iter.next();
694       ResourceData rd = (ResourceData) get(res.getClass().getName());
695       if(! rd.isPrivate()) publics.add(res);
696     }
697 
698     return Collections.unmodifiableList(publics);
699   } // getPublics
700 
701   /** Gets a list of all non private types from alist of types*/
702   protected List getPublicTypes(Collection types){
703     Iterator iter = types.iterator();
704     List publics = new ArrayList();
705     while(iter.hasNext()){
706       String oneType = (String)iter.next();
707       ResourceData rData = (ResourceData)get(oneType);
708       if(rData != null && !rData.isPrivate()) publics.add(oneType);
709     }
710     return Collections.unmodifiableList(publics);
711   }//getPublicTypes
712 
713   public synchronized void removeCreoleListener(CreoleListener l) {
714     if (creoleListeners != null && creoleListeners.contains(l)) {
715       Vector v = (Vector) creoleListeners.clone();
716       v.removeElement(l);
717       creoleListeners = v;
718     }
719   }
720 
721   public synchronized void addCreoleListener(CreoleListener l) {
722     Vector v = creoleListeners == null ? new Vector(2) : (Vector) creoleListeners.clone();
723     if (!v.contains(l)) {
724       v.addElement(l);
725       creoleListeners = v;
726     }
727   } // getPublicTypes
728 
729   /**
730    * Removes a {@link gate.event.CreoleListener} previously registered with this
731    * CreoleRegister. {@see #addCreoleListener()}
732    */
733 
734   /**
735    * Registers a {@link gate.event.CreoleListener}with this CreoleRegister.
736    * The register will fire events every time a resource is added to or removed
737    * from the system.
738    */// addCreoleListener
739 
740   /**
741    * Notifies all listeners that a new {@link gate.Resource} has been loaded
742    * into the system
743    */// fireResourceLoaded
744 
745   /**
746    * Notifies all listeners that a {@link gate.Resource} has been unloaded
747    * from the system
748    */// fireResourceUnloaded
749 
750   /** A list of the types of LR in the register. */
751   protected Set lrTypes;
752 
753   /** A list of the types of PR in the register. */
754   protected Set prTypes;
755 
756   /** A list of the types of VR in the register. */
757   protected List vrTypes;
758 
759   /** A list of the types of VR in the register. */
760   protected Set controllerTypes;
761 
762   /** A list of the types of TOOL in the register. */
763   protected Set toolTypes;
764 
765   private transient Vector creoleListeners;
766   protected void fireResourceLoaded(CreoleEvent e) {
767     if (creoleListeners != null) {
768       Vector listeners = creoleListeners;
769       int count = listeners.size();
770       for (int i = 0; i < count; i++) {
771         ((CreoleListener) listeners.elementAt(i)).resourceLoaded(e);
772       }
773     }
774   }
775 
776   protected void fireResourceUnloaded(CreoleEvent e) {
777     if (creoleListeners != null) {
778       Vector listeners = creoleListeners;
779       int count = listeners.size();
780       for (int i = 0; i < count; i++) {
781         ((CreoleListener) listeners.elementAt(i)).resourceUnloaded(e);
782       }
783     }
784   }
785 
786   protected void fireResourceRenamed(Resource res, String oldName,
787                                      String newName) {
788     if (creoleListeners != null) {
789       Vector listeners = creoleListeners;
790       int count = listeners.size();
791       for (int i = 0; i < count; i++) {
792         ((CreoleListener) listeners.elementAt(i)).resourceRenamed(res,
793                                                                   oldName,
794                                                                   newName);
795       }
796     }
797   }
798 
799   protected void fireDatastoreOpened(CreoleEvent e) {
800     if (creoleListeners != null) {
801       Vector listeners = creoleListeners;
802       int count = listeners.size();
803       for (int i = 0; i < count; i++) {
804         ((CreoleListener) listeners.elementAt(i)).datastoreOpened(e);
805       }
806     }
807   }
808   protected void fireDatastoreCreated(CreoleEvent e) {
809     if (creoleListeners != null) {
810       Vector listeners = creoleListeners;
811       int count = listeners.size();
812       for (int i = 0; i < count; i++) {
813         ((CreoleListener) listeners.elementAt(i)).datastoreCreated(e);
814       }
815     }
816   }
817 
818   protected void fireDatastoreClosed(CreoleEvent e) {
819     if (creoleListeners != null) {
820       Vector listeners = creoleListeners;
821       int count = listeners.size();
822       for (int i = 0; i < count; i++) {
823         ((CreoleListener) listeners.elementAt(i)).datastoreClosed(e);
824       }
825     }
826   }
827 
828   public void resourceLoaded(CreoleEvent e) {
829     fireResourceLoaded(e);
830   }
831 
832   public void resourceUnloaded(CreoleEvent e) {
833     fireResourceUnloaded(e);
834   }
835 
836   public void resourceRenamed(Resource resource, String oldName,
837                               String newName){
838     fireResourceRenamed(resource, oldName, newName);
839   }
840 
841   public void datastoreOpened(CreoleEvent e) {
842     fireDatastoreOpened(e);
843   }
844 
845   public void datastoreCreated(CreoleEvent e) {
846     fireDatastoreCreated(e);
847   }
848 
849   public void datastoreClosed(CreoleEvent e) {
850     fireDatastoreClosed(e);
851   }
852 
853   /**The lists of listeners registered with this CreoleRegister*/
854 } // class CreoleRegisterImpl
855