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