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