0001 /*
0002 * CreoleRegisterImpl.java
0003 *
0004 * Copyright (c) 1995-2010, The University of Sheffield. See the file
0005 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
0006 *
0007 * This file is part of GATE (see http://gate.ac.uk/), and is free
0008 * software, licenced under the GNU Library General Public License,
0009 * Version 2, June 1991 (in the distribution as file licence.html,
0010 * and also available at http://gate.ac.uk/gate/licence.html).
0011 *
0012 * Hamish Cunningham, 1/Sept/2000
0013 *
0014 * $Id: CreoleRegisterImpl.java 13569 2011-03-28 14:15:16Z ian_roberts $
0015 */
0016
0017 package gate.creole;
0018
0019 import gate.Controller;
0020 import gate.CreoleRegister;
0021 import gate.Gate;
0022 import gate.LanguageResource;
0023 import gate.ProcessingResource;
0024 import gate.Resource;
0025 import gate.VisualResource;
0026 import gate.Gate.DirectoryInfo;
0027 import gate.Gate.ResourceInfo;
0028 import gate.event.CreoleEvent;
0029 import gate.event.CreoleListener;
0030 import gate.util.CreoleXmlUpperCaseFilter;
0031 import gate.util.Err;
0032 import gate.util.GateClassLoader;
0033 import gate.util.GateException;
0034 import gate.util.GateRuntimeException;
0035 import gate.util.LazyProgrammerException;
0036 import gate.util.LuckyException;
0037 import gate.util.Out;
0038
0039 import java.io.File;
0040 import java.io.IOException;
0041 import java.io.InputStream;
0042 import java.net.MalformedURLException;
0043 import java.net.URL;
0044 import java.util.AbstractList;
0045 import java.util.ArrayList;
0046 import java.util.Collection;
0047 import java.util.Collections;
0048 import java.util.HashMap;
0049 import java.util.HashSet;
0050 import java.util.Iterator;
0051 import java.util.LinkedList;
0052 import java.util.List;
0053 import java.util.Map;
0054 import java.util.Set;
0055 import java.util.Vector;
0056
0057 import org.apache.log4j.Logger;
0058 import org.jdom.Document;
0059 import org.jdom.Element;
0060 import org.jdom.JDOMException;
0061 import org.jdom.input.SAXBuilder;
0062 import org.jdom.output.Format;
0063 import org.jdom.output.SAXOutputter;
0064 import org.jdom.output.XMLOutputter;
0065 import org.xml.sax.helpers.DefaultHandler;
0066
0067 /**
0068 * This class implements the CREOLE register interface. DO NOT construct objects
0069 * of this class unless your name is gate.Gate (in which case please go back to
0070 * the source code repository and stop looking at other class's code).
0071 * <P>
0072 * The CREOLE register records the set of resources that are currently known to
0073 * the system. Each member of the register is a {@link gate.creole.ResourceData}
0074 * object, indexed by the class name of the resource.
0075 *
0076 * @see gate.CreoleRegister
0077 */
0078 public class CreoleRegisterImpl extends HashMap<String, ResourceData>
0079 implements
0080 CreoleRegister,
0081 CreoleListener {
0082
0083 /** A logger to use instead of sending messages to Out or Err **/
0084 protected static final Logger log = Logger.getLogger(CreoleRegisterImpl.class);
0085
0086 /** Debug flag */
0087 protected static final boolean DEBUG = false;
0088
0089 /** The set of CREOLE directories (URLs). */
0090 protected Set<URL> directories;
0091
0092 /** The parser for the CREOLE directory files */
0093 protected transient SAXBuilder jdomBuilder = null;
0094
0095 /**
0096 * Name of the plugin-mappings file
0097 */
0098 public static final String PLUGIN_NAMES_MAPPING_FILE = "plugin-mappings.xml";
0099
0100 /**
0101 * maps previous plugin names to new plugin names
0102 */
0103 protected Map<String, String> pluginNamesMappings = null;
0104
0105 /**
0106 * Default constructor. Sets up directory files parser. <B>NOTE:</B> only
0107 * Factory should call this method.
0108 */
0109 public CreoleRegisterImpl() throws GateException {
0110
0111 // initialise the various maps
0112 directories = new HashSet<URL>();
0113 lrTypes = new HashSet<String>();
0114 prTypes = new HashSet<String>();
0115 vrTypes = new LinkedList<String>();
0116 toolTypes = new HashSet<String>();
0117
0118 // construct a SAX parser for parsing the CREOLE directory files
0119 jdomBuilder = new SAXBuilder(false);
0120 jdomBuilder.setXMLFilter(new CreoleXmlUpperCaseFilter());
0121
0122 // read plugin name mappings file
0123 readPluginNamesMappings();
0124
0125 } // default constructor
0126
0127 /**
0128 * reads plugins-mapping.xml file which is used for mapping old plugin
0129 * names to new plugin names
0130 */
0131 private void readPluginNamesMappings() {
0132 // should load it only once
0133 if(pluginNamesMappings != null) return;
0134
0135 pluginNamesMappings = new HashMap<String, String>();
0136
0137 // use jdom
0138 SAXBuilder builder = new SAXBuilder();
0139
0140 // command line should offer URIs or file names
0141 try {
0142 URL creoleDirURL = Gate.getBuiltinCreoleDir();
0143 URL pluginMappingsFileURL =
0144 new URL(creoleDirURL, PLUGIN_NAMES_MAPPING_FILE);
0145 Document document = builder.build(pluginMappingsFileURL);
0146 List<Element> plugins = document.getRootElement().getChildren("Plugin");
0147 if(plugins != null) {
0148 for(Element aPlugin : plugins) {
0149 String oldName = aPlugin.getChildText("OldName");
0150 String newName = aPlugin.getChildText("NewName");
0151 pluginNamesMappings.put(oldName, newName);
0152 }
0153 }
0154 }
0155 // indicates a well-formedness error
0156 catch(JDOMException e) {
0157 log.warn(PLUGIN_NAMES_MAPPING_FILE + " is not well-formed.", e);
0158 }
0159 catch(IOException e) {
0160 log.warn("Could not check " + PLUGIN_NAMES_MAPPING_FILE,e);
0161 }
0162 }
0163
0164 /**
0165 * Add a CREOLE directory URL to the register and to the GATE classloader. The
0166 * directory will be automatically registered. This method is equivalent with
0167 * #registerDirectories(URL) which it actually calls and it's only kept here
0168 * for backwards compatibility reasons.
0169 *
0170 * @deprecated
0171 */
0172 public void addDirectory(URL directoryUrl) {
0173 try {
0174 registerDirectories(directoryUrl);
0175 }
0176 catch(GateException ge) {
0177 throw new GateRuntimeException(ge);
0178 }
0179 } // addDirectory
0180
0181 /** Get the list of CREOLE directory URLs. */
0182 public Set<URL> getDirectories() {
0183 return Collections.unmodifiableSet(directories);
0184 } // getDirectories
0185
0186 /**
0187 * All CREOLE directories are now automatically registered when they are added
0188 * so this method does nothing now. It is only kept here for backwards
0189 * compatibility reasons.
0190 *
0191 * @deprecated
0192 */
0193 public void registerDirectories() throws GateException {
0194 // Iterator iter = directories.iterator();
0195 //
0196 // while(iter.hasNext()) {
0197 // URL directoryUrl = (URL) iter.next();
0198 // registerDirectories(directoryUrl);
0199 // }
0200 } // registerDirectories
0201
0202
0203 public void registerComponent(Class<? extends Resource> resourceClass) throws GateException {
0204 URL creoleFileUrl = resourceClass.getResource("/gate/creole/CreoleRegisterImpl.class");
0205 Gate.addKnownPlugin(creoleFileUrl);
0206 Document doc = new Document();
0207 Element element;
0208 doc.addContent(element = new Element("CREOLE-DIRECTORY"));
0209 element.addContent(element = new Element("CREOLE"));
0210 element.addContent(element = new Element("RESOURCE"));
0211 Element classElement = new Element("CLASS");
0212 classElement.setText(resourceClass.getName());
0213 element.addContent(classElement);
0214 CreoleAnnotationHandler annotationHandler = new CreoleAnnotationHandler(creoleFileUrl);
0215 annotationHandler.processCreoleResourceAnnotations(element, resourceClass);
0216 try {
0217 processFullCreoleXmlTree(new URL(creoleFileUrl, "."), creoleFileUrl, doc, annotationHandler);
0218 }
0219 catch(IOException e) {
0220 throw new GateException(e);
0221 }
0222 catch(JDOMException e) {
0223 throw new GateException(e);
0224 }
0225 }
0226
0227 /**
0228 * Register a single CREOLE directory. The <CODE>creole.xml</CODE> file at the
0229 * URL is parsed, and <CODE>CreoleData</CODE> objects added to the register.
0230 * If the directory URL has not yet been added it is now added. URLs for
0231 * resource JAR files are added to the GATE class loader.
0232 */
0233 public void registerDirectories(URL directoryUrl) throws GateException {
0234
0235 // directory URLs shouldn't include "creole.xml"
0236 String urlName = directoryUrl.toExternalForm();
0237 if(urlName.toLowerCase().endsWith("creole.xml")) { throw new GateException(
0238 "CREOLE directory URLs should point to the parent location of "
0239 + "the creole.xml file, not the file itself; bad URL was: " + urlName); }
0240 // CREOLE URLs are directory URLs so they should end with "/"
0241 String separator = "/";
0242 if(!urlName.endsWith(separator)) {
0243 urlName += separator;
0244 try {
0245 directoryUrl = new URL(urlName);
0246 }
0247 catch(MalformedURLException mue) {
0248 throw new GateRuntimeException(mue);
0249 }
0250 }
0251 // normalise to remove any /../ path components
0252 try {
0253 directoryUrl = new URL(directoryUrl, ".");
0254 urlName = directoryUrl.toExternalForm();
0255 }
0256 catch(MalformedURLException mue) {
0257 throw new GateRuntimeException(mue);
0258 }
0259 // create a URL for the creole.xml file, based on the directory URL
0260 URL directoryXmlFileUrl = directoryUrl;
0261 try {
0262 directoryXmlFileUrl = new URL(urlName + "creole.xml");
0263 }
0264 catch(MalformedURLException e) {
0265 throw (new GateException("bad creole.xml URL, based on " + urlName));
0266 }
0267
0268 // creole stream
0269 InputStream creoleStream = null;
0270
0271 // lets check if it is an old plugin name
0272 try {
0273 creoleStream = directoryXmlFileUrl.openStream();
0274 }
0275 catch(IOException ioe) {
0276
0277 // if this happens
0278 // locating last separator
0279 int indexOfSeparator = urlName.lastIndexOf('/', urlName.length() - 2);
0280
0281 // plugin name
0282 String pluginName =
0283 urlName.substring(indexOfSeparator + 1, urlName.length() - 1);
0284
0285 if(pluginNamesMappings != null && pluginNamesMappings.containsKey(pluginName)) {
0286 String newPluginName = pluginNamesMappings.get(pluginName);
0287
0288 urlName =
0289 urlName.substring(0, indexOfSeparator + 1) + newPluginName + "/";
0290
0291 try {
0292 log.warn("Trying to use new plugin name for " + pluginName);
0293 directoryXmlFileUrl = new URL(urlName + "creole.xml");
0294 creoleStream = directoryXmlFileUrl.openStream();
0295 log.warn("Please note that plugin names have changed. "
0296 + "Please correct your application to rename " + pluginName
0297 + " to " + newPluginName);
0298 }
0299 catch(IOException e) {
0300 throw new GateException("couldn't open creole.xml: " + e.toString());
0301 }
0302 } else {
0303 throw new GateException("couldn't find:" + directoryUrl);
0304 }
0305 }
0306
0307 // add the URL
0308 // if already present do nothing
0309 if(directories.add(directoryUrl)) {
0310 // add it to the list of known directories
0311 Gate.addKnownPlugin(directoryUrl);
0312 // parse the directory file
0313 try {
0314 parseDirectory(creoleStream, directoryUrl,
0315 directoryXmlFileUrl);
0316 log.info("CREOLE plugin loaded: " + urlName);
0317 }
0318 catch(GateException e) {
0319 // it failed: remove it
0320 directories.remove(directoryUrl);
0321 Gate.removeKnownPlugin(directoryUrl);
0322 throw (new GateException("couldn't open creole.xml: " + e.toString()));
0323 }
0324 }
0325 } // registerDirectories(URL)
0326
0327 /**
0328 * Parse a directory file (represented as an open stream), adding resource
0329 * data objects to the CREOLE register as they occur. If the resource is from
0330 * a URL then that location is passed (otherwise null).
0331 */
0332 protected void parseDirectory(InputStream directoryStream, URL directoryUrl,
0333 URL creoleFileUrl) throws GateException {
0334 // create a handler for the directory file and parse it;
0335 // this will create ResourceData entries in the register
0336 try {
0337 Document jdomDoc =
0338 jdomBuilder.build(directoryStream, creoleFileUrl.toExternalForm());
0339 CreoleAnnotationHandler annotationHandler =
0340 new CreoleAnnotationHandler(creoleFileUrl);
0341
0342 // Add any JARs from the creole.xml to the GATE ClassLoader
0343 annotationHandler.addJarsToClassLoader(jdomDoc);
0344
0345 // Make sure there is a RESOURCE element for every resource type the
0346 // directory defines
0347 annotationHandler.createResourceElementsForDirInfo(jdomDoc);
0348
0349 processFullCreoleXmlTree(directoryUrl, creoleFileUrl, jdomDoc, annotationHandler);
0350 }
0351 catch(IOException e) {
0352 throw (new GateException(e));
0353 }
0354 catch(JDOMException je) {
0355 if(DEBUG) je.printStackTrace(Err.getPrintWriter());
0356 throw (new GateException(je));
0357 }
0358
0359 } // parseDirectory
0360
0361 private void processFullCreoleXmlTree(URL directoryUrl, URL creoleFileUrl,
0362 Document jdomDoc, CreoleAnnotationHandler annotationHandler)
0363 throws GateException, IOException, JDOMException {
0364 // now we can process any annotations on the new classes
0365 // and augment the XML definition
0366 annotationHandler.processAnnotations(jdomDoc);
0367
0368 // debugging
0369 if(DEBUG) {
0370 XMLOutputter xmlOut = new XMLOutputter(Format.getPrettyFormat());
0371 xmlOut.output(jdomDoc, System.out);
0372 }
0373
0374 // finally, parse the augmented definition with the normal parser
0375 DefaultHandler handler =
0376 new CreoleXmlHandler(this, directoryUrl, creoleFileUrl);
0377 SAXOutputter outputter =
0378 new SAXOutputter(handler, handler, handler, handler);
0379 outputter.output(jdomDoc);
0380 if(DEBUG) {
0381 Out.prln("done parsing "
0382 + ((directoryUrl == null) ? "null" : directoryUrl.toString()));
0383 }
0384 }
0385
0386 /**
0387 * Register resources that are built in to the GATE distribution. These
0388 * resources are described by the <TT>creole.xml</TT> file in
0389 * <TT>resources/creole</TT>.
0390 */
0391 public void registerBuiltins() throws GateException {
0392
0393 try {
0394 URL creoleDirURL = Gate.getBuiltinCreoleDir();
0395 URL creoleFileURL = new URL(creoleDirURL, "creole.xml");
0396 // URL creoleFileURL = Files.getGateResource("/creole/creole.xml");
0397 parseDirectory(creoleFileURL.openStream(), creoleDirURL, creoleFileURL);
0398 }
0399 catch(IOException e) {
0400 if(DEBUG) log.debug(e);
0401 throw (new GateException(e));
0402 }
0403 } // registerBuiltins()
0404
0405 /**
0406 * This is a utility method for creating CREOLE directory files (typically
0407 * called <CODE>creole.xml</CODE>) from a list of Jar files that contain
0408 * resources. The method concatenates the <CODE>resource.xml</CODE> files that
0409 * the Jars contain.
0410 * <P>
0411 * If Java allowed class methods in interfaces this would be static.
0412 */
0413 public File createCreoleDirectoryFile(File directoryFile, Set jarFileNames) {
0414 // //////////////////
0415 // dump xml header and comment header and <CREOLE-DIRECTORY> into dirfile
0416 // for each jar file pick out resource.xml
0417 // strip xml header
0418 // dump into dirfile
0419 // put </CREOLE-DIRECTORY> into dirfile
0420 throw new LazyProgrammerException();
0421 } // createCreoleDirectoryFile
0422
0423 /**
0424 * Overide HashMap's put method to maintain a list of all the types of LR in
0425 * the register, and a list of tool types. The key is the resource type, the
0426 * value its data.
0427 */
0428 public ResourceData put(String key, ResourceData rd) {
0429
0430 // get the resource implementation class
0431 Class<? extends Resource> resClass = null;
0432 try {
0433 resClass = rd.getResourceClass();
0434 }
0435 catch(ClassNotFoundException e) {
0436 throw new GateRuntimeException(
0437 "Couldn't get resource class from the resource data:" + e);
0438 }
0439
0440 // add class names to the type lists
0441 if(LanguageResource.class.isAssignableFrom(resClass)) {
0442 if(DEBUG) Out.prln("LR: " + resClass);
0443 if(lrTypes == null) lrTypes = new HashSet<String>(); // for
0444 // deserialisation
0445 lrTypes.add(rd.getClassName());
0446 }
0447 if(ProcessingResource.class.isAssignableFrom(resClass)) {
0448 if(DEBUG) {
0449 Out.prln("PR: " + resClass);
0450 // Out.prln("prTypes: " + prTypes);
0451 // Out.prln("rd.getClassName(): " + rd.getClassName());
0452 }
0453 if(prTypes == null) prTypes = new HashSet<String>(); // for
0454 // deserialisation
0455 prTypes.add(rd.getClassName());
0456 }
0457 if(VisualResource.class.isAssignableFrom(resClass)) {
0458 if(DEBUG) Out.prln("VR: " + resClass);
0459 if(vrTypes == null) vrTypes = new LinkedList<String>(); // for
0460 // deserialisation
0461 // we have to simulate Set behaviour as this is a list
0462 if(!vrTypes.contains(rd.getClassName())) vrTypes.add(rd.getClassName());
0463 }
0464 if(Controller.class.isAssignableFrom(resClass)) {
0465 if(DEBUG) Out.prln("Controller: " + resClass);
0466 if(controllerTypes == null) controllerTypes = new HashSet<String>(); // for
0467 // deserialisation
0468 controllerTypes.add(rd.getClassName());
0469 }
0470
0471 // maintain tool types list
0472 if(rd.isTool()) {
0473 if(toolTypes == null) toolTypes = new HashSet<String>(); // for
0474 // deserialisation
0475 toolTypes.add(rd.getClassName());
0476 }
0477
0478 return super.put(key, rd);
0479 } // put(key, value)
0480
0481 /**
0482 * Removes a CREOLE directory from the set of loaded directories.
0483 *
0484 * @param directory
0485 */
0486 public void removeDirectory(URL directory) {
0487 if(directories.remove(directory)) {
0488 DirectoryInfo dInfo = Gate.getDirectoryInfo(directory);
0489 if(dInfo != null) {
0490 for(ResourceInfo rInfo : dInfo.getResourceInfoList()) {
0491 remove(rInfo.getResourceClassName());
0492 }
0493 }
0494 log.info("CREOLE plugin unloaded: " + directory);
0495 }
0496 }
0497
0498 /**
0499 * Overide HashMap's delete method to update the lists of types in the
0500 * register.
0501 */
0502 public ResourceData remove(Object key) {
0503 ResourceData rd = get(key);
0504 if(rd == null) return null;
0505 if(DEBUG) {
0506 Out.prln(key);
0507 Out.prln(rd);
0508 }
0509 try {
0510 if(LanguageResource.class.isAssignableFrom(rd.getResourceClass())) {
0511 lrTypes.remove(rd.getClassName());
0512 }
0513 else if(ProcessingResource.class.isAssignableFrom(rd.getResourceClass())) {
0514 prTypes.remove(rd.getClassName());
0515 }
0516 else if(VisualResource.class.isAssignableFrom(rd.getResourceClass())) {
0517 vrTypes.remove(rd.getClassName());
0518 }
0519 else if(Controller.class.isAssignableFrom(rd.getResourceClass())) {
0520 controllerTypes.remove(rd.getClassName());
0521 }
0522 }
0523 catch(ClassNotFoundException cnfe) {
0524 throw new GateRuntimeException(
0525 "Could not load class specified in CREOLE data.", cnfe);
0526 }
0527 // maintain tool types list
0528 if(rd.isTool()) toolTypes.remove(rd.getClassName());
0529
0530 return super.remove(key);
0531 } // remove(Object)
0532
0533 /**
0534 * Overide HashMap's clear to update the list of LR types in the register, and
0535 * remove all resources and forgets all directories.
0536 */
0537 public void clear() {
0538 lrTypes.clear();
0539 prTypes.clear();
0540 vrTypes.clear();
0541 toolTypes.clear();
0542 directories.clear();
0543 super.clear();
0544 } // clear()
0545
0546 /** Get the list of types of LR in the register. */
0547 public Set<String> getLrTypes() {
0548 return Collections.unmodifiableSet(lrTypes);
0549 }
0550
0551 /** Get the list of types of PR in the register. */
0552 public Set<String> getPrTypes() {
0553 return Collections.unmodifiableSet(prTypes);
0554 }
0555
0556 /** Get the list of types of VR in the register. */
0557 public Set<String> getVrTypes() {
0558 return Collections.unmodifiableSet(new HashSet<String>(vrTypes));
0559 }
0560
0561 /** Get the list of types of Controller in the register. */
0562 public Set<String> getControllerTypes() {
0563 return Collections.unmodifiableSet(controllerTypes);
0564 }
0565
0566 /** Get the list of types of TOOL resources in the register. */
0567 public Set<String> getToolTypes() {
0568 return Collections.unmodifiableSet(toolTypes);
0569 }
0570
0571 /** Get a list of all instantiations of LR in the register. */
0572 public List<LanguageResource> getLrInstances() {
0573 Set<String> lrTypeSet = getLrTypes();
0574 List<LanguageResource> instances = new ArrayList<LanguageResource>();
0575
0576 Iterator<String> iter = lrTypeSet.iterator();
0577 while(iter.hasNext()) {
0578 String type = iter.next();
0579 instances.addAll(getLrInstances(type));
0580 }// End while
0581 return Collections.unmodifiableList(instances);
0582 } // getLrInstances()
0583
0584 /** Get a list of all instantiations of PR in the register. */
0585 public List<ProcessingResource> getPrInstances() {
0586 Set<String> prTypeSet = getPrTypes();
0587 List<ProcessingResource> instances = new ArrayList<ProcessingResource>();
0588
0589 Iterator<String> iter = prTypeSet.iterator();
0590 while(iter.hasNext()) {
0591 String type = iter.next();
0592 instances.addAll(getPrInstances(type));
0593 }// End while
0594
0595 return Collections.unmodifiableList(instances);
0596 } // getPrInstances()
0597
0598 /** Get a list of all instantiations of VR in the register. */
0599 public List<VisualResource> getVrInstances() {
0600 Set<String> vrTypeSet = getVrTypes();
0601 List<VisualResource> instances = new ArrayList<VisualResource>();
0602
0603 Iterator<String> iter = vrTypeSet.iterator();
0604 while(iter.hasNext()) {
0605 String type = iter.next();
0606 instances.addAll(getVrInstances(type));
0607 }// End while
0608
0609 return Collections.unmodifiableList(instances);
0610 } // getVrInstances()
0611
0612 /** Get a list of instantiations of a type of LR in the register. */
0613 public List<LanguageResource> getLrInstances(String resourceTypeName) {
0614 ResourceData resData = get(resourceTypeName);
0615 if(resData == null) return Collections.emptyList();
0616
0617 return new TypedResourceList<LanguageResource>(resData.getInstantiations(),
0618 LanguageResource.class);
0619 } // getLrInstances
0620
0621 /** Get a list of instantiations of a type of PR in the register. */
0622 public List<ProcessingResource> getPrInstances(String resourceTypeName) {
0623 ResourceData resData = get(resourceTypeName);
0624 if(resData == null) return Collections.emptyList();
0625
0626 return new TypedResourceList<ProcessingResource>(resData
0627 .getInstantiations(), ProcessingResource.class);
0628 } // getPrInstances
0629
0630 /** Get a list of instantiations of a type of VR in the register. */
0631 public List<VisualResource> getVrInstances(String resourceTypeName) {
0632 ResourceData resData = get(resourceTypeName);
0633 if(resData == null) return Collections.emptyList();
0634
0635 return new TypedResourceList<VisualResource>(resData.getInstantiations(),
0636 VisualResource.class);
0637 } // getVrInstances
0638
0639 /** Get a list of all non-private instantiations of LR in the register. */
0640 public List<LanguageResource> getPublicLrInstances() {
0641 return Collections.unmodifiableList(getPublics(getLrInstances()));
0642 }// getPublicLrInstances()
0643
0644 /** Get a list of all non-private instantiations of PR in the register. */
0645 public List<ProcessingResource> getPublicPrInstances() {
0646 return Collections.unmodifiableList(getPublics(getPrInstances()));
0647 }// getPublicPrInstances()
0648
0649 /** Get a list of all non-private instantiations of VR in the register. */
0650 public List<VisualResource> getPublicVrInstances() {
0651 return Collections.unmodifiableList(getPublics(getVrInstances()));
0652 }// getPublicVrInstances()
0653
0654 /** Get a list of all non-private types of LR in the register. */
0655 public List<String> getPublicLrTypes() {
0656 return Collections.unmodifiableList(getPublicTypes(getLrTypes()));
0657 }// getPublicLrTypes()
0658
0659 /** Get a list of all non-private types of PR in the register. */
0660 public List<String> getPublicPrTypes() {
0661 return Collections.unmodifiableList(getPublicTypes(getPrTypes()));
0662 }// getPublicPrTypes()
0663
0664 /** Get a list of all non-private types of VR in the register. */
0665 public List<String> getPublicVrTypes() {
0666 return Collections.unmodifiableList(getPublicTypes(vrTypes));
0667 }// getPublicVrTypes()
0668
0669 /** Get a list of all non-private types of controller in the register. */
0670 public List<String> getPublicControllerTypes() {
0671 return Collections.unmodifiableList(getPublicTypes(getControllerTypes()));
0672 }// getPublicPrTypes()
0673
0674 /**
0675 * Gets all the instantiations of a given type and all its derivate types; It
0676 * doesn't return instances that have the hidden attribute set to "true"
0677 */
0678 public List<Resource> getAllInstances(String type) throws GateException {
0679 Iterator<String> typesIter = keySet().iterator();
0680 List<Resource> res = new ArrayList<Resource>();
0681 Class<? extends Resource> targetClass;
0682 try {
0683 targetClass =
0684 Gate.getClassLoader().loadClass(type).asSubclass(Resource.class);
0685 }
0686 catch(ClassNotFoundException cnfe) {
0687 throw new GateException("Invalid type " + type);
0688 }
0689 while(typesIter.hasNext()) {
0690 String aType = typesIter.next();
0691 Class<?> aClass;
0692 try {
0693 aClass = Gate.getClassLoader().loadClass(aType);
0694 if(targetClass.isAssignableFrom(aClass)) {
0695 // filter out hidden instances
0696 Iterator<? extends Resource> newInstancesIter =
0697 get(aType).getInstantiations().iterator();
0698 while(newInstancesIter.hasNext()) {
0699 Resource instance = newInstancesIter.next();
0700 if(!Gate.getHiddenAttribute(instance.getFeatures())) {
0701 res.add(instance);
0702 }
0703 }
0704 }
0705 }
0706 catch(ClassNotFoundException cnfe) {
0707 throw new LuckyException(
0708 "A type registered in the creole register does not exist in the VM!");
0709 }
0710
0711 }// while(typesIter.hasNext())
0712
0713 return res;
0714 }
0715
0716 /**
0717 * Returns a list of strings representing class names for large VRs valid for
0718 * a given type of language/processing resource. The default VR will be the
0719 * first in the returned list.
0720 *
0721 * @param resourceClassName
0722 * the name of the resource that has large viewers. If
0723 * resourceClassName is <b>null</b> then an empty list will be
0724 * returned.
0725 * @return a list with Strings representing the large VRs for the
0726 * resourceClassName
0727 */
0728 public List<String> getLargeVRsForResource(String resourceClassName) {
0729 return getVRsForResource(resourceClassName, ResourceData.LARGE_GUI);
0730 }// getLargeVRsForResource()
0731
0732 /**
0733 * Returns a list of strings representing class names for small VRs valid for
0734 * a given type of language/processing resource The default VR will be the
0735 * first in the returned list.
0736 *
0737 * @param resourceClassName
0738 * the name of the resource that has large viewers. If
0739 * resourceClassName is <b>null</b> then an empty list will be
0740 * returned.
0741 * @return a list with Strings representing the large VRs for the
0742 * resourceClassName
0743 */
0744 public List<String> getSmallVRsForResource(String resourceClassName) {
0745 return getVRsForResource(resourceClassName, ResourceData.SMALL_GUI);
0746 }// getSmallVRsForResource
0747
0748 /**
0749 * Returns a list of strings representing class names for guiType VRs valid
0750 * for a given type of language/processing resource The default VR will be the
0751 * first in the returned list.
0752 *
0753 * @param resourceClassName
0754 * the name of the resource that has large viewers. If
0755 * resourceClassName is <b>null</b> then an empty list will be
0756 * returned.
0757 * @param guiType
0758 * can be ResourceData's LARGE_GUI or SMALL_GUI
0759 * @return a list with Strings representing the large VRs for the
0760 * resourceClassName
0761 */
0762 private List<String> getVRsForResource(String resourceClassName, int guiType) {
0763 // If resurceClassName is null return a simply list
0764 if(resourceClassName == null)
0765 return Collections.unmodifiableList(new ArrayList<String>());
0766 // create a Class object for the resource
0767 Class<?> resourceClass = null;
0768 GateClassLoader classLoader = Gate.getClassLoader();
0769 try {
0770 resourceClass = classLoader.loadClass(resourceClassName);
0771 }
0772 catch(ClassNotFoundException ex) {
0773 throw new GateRuntimeException(
0774 "Couldn't get resource class from the resource name:" + ex);
0775 }// End try
0776 LinkedList<String> responseList = new LinkedList<String>();
0777 String defaultVR = null;
0778 // Take all VRs and for each large one, test if
0779 // resourceClassName is asignable form VR's RESOURCE_DISPLAYED
0780 Iterator<String> vrIterator = vrTypes.iterator();
0781 while(vrIterator.hasNext()) {
0782 String vrClassName = vrIterator.next();
0783 ResourceData vrResourceData = this.get(vrClassName);
0784 if(vrResourceData == null)
0785 throw new GateRuntimeException(
0786 "Couldn't get resource data for VR called " + vrClassName);
0787 if(vrResourceData.getGuiType() == guiType) {
0788 String resourceDisplayed = vrResourceData.getResourceDisplayed();
0789 if(resourceDisplayed != null) {
0790 Class<?> resourceDisplayedClass = null;
0791 try {
0792 resourceDisplayedClass = classLoader.loadClass(resourceDisplayed);
0793 }
0794 catch(ClassNotFoundException ex) {
0795 throw new GateRuntimeException(
0796 "Couldn't get resource class from the resource name :"
0797 + resourceDisplayed + " " + ex);
0798 }// End try
0799 if(resourceDisplayedClass.isAssignableFrom(resourceClass)) {
0800 responseList.add(vrClassName);
0801 if(vrResourceData.isMainView()) {
0802 defaultVR = vrClassName;
0803 }// End if
0804 }// End if
0805 }// End if
0806 }// End if
0807 }// End while
0808 if(defaultVR != null) {
0809 responseList.remove(defaultVR);
0810 responseList.addFirst(defaultVR);
0811 }// End if
0812 return Collections.unmodifiableList(responseList);
0813 }// getVRsForResource()
0814
0815 /**
0816 * Returns a list of strings representing class names for annotation VRs that
0817 * are able to display/edit all types of annotations. The default VR will be
0818 * the first in the returned list.
0819 *
0820 * @return a list with all VRs that can display all annotation types
0821 */
0822 public List<String> getAnnotationVRs() {
0823 LinkedList<String> responseList = new LinkedList<String>();
0824 String defaultVR = null;
0825 Iterator<String> vrIterator = vrTypes.iterator();
0826 while(vrIterator.hasNext()) {
0827 String vrClassName = vrIterator.next();
0828 ResourceData vrResourceData = this.get(vrClassName);
0829 if(vrResourceData == null)
0830 throw new GateRuntimeException(
0831 "Couldn't get resource data for VR called " + vrClassName);
0832 Class<?> vrResourceClass = null;
0833 try {
0834 vrResourceClass = vrResourceData.getResourceClass();
0835 }
0836 catch(ClassNotFoundException ex) {
0837 throw new GateRuntimeException(
0838 "Couldn't create a class object for VR called " + vrClassName);
0839 }// End try
0840 // Test if VR can display all types of annotations
0841 if(vrResourceData.getGuiType() == ResourceData.NULL_GUI
0842 && vrResourceData.getAnnotationTypeDisplayed() == null
0843 && vrResourceData.getResourceDisplayed() == null
0844 && gate.creole.AnnotationVisualResource.class
0845 .isAssignableFrom(vrResourceClass)) {
0846
0847 responseList.add(vrClassName);
0848 if(vrResourceData.isMainView()) defaultVR = vrClassName;
0849 }// End if
0850 }// End while
0851 if(defaultVR != null) {
0852 responseList.remove(defaultVR);
0853 responseList.addFirst(defaultVR);
0854 }// End if
0855 return Collections.unmodifiableList(responseList);
0856 }// getAnnotationVRs()
0857
0858 /**
0859 * Returns a list of strings representing class names for annotation VRs that
0860 * are able to display/edit a given annotation type The default VR will be the
0861 * first in the returned list.
0862 */
0863 public List<String> getAnnotationVRs(String annotationType) {
0864 if(annotationType == null)
0865 return Collections.unmodifiableList(new ArrayList<String>());
0866 LinkedList<String> responseList = new LinkedList<String>();
0867 String defaultVR = null;
0868 Iterator<String> vrIterator = vrTypes.iterator();
0869 while(vrIterator.hasNext()) {
0870 String vrClassName = vrIterator.next();
0871 ResourceData vrResourceData = this.get(vrClassName);
0872 if(vrResourceData == null)
0873 throw new GateRuntimeException(
0874 "Couldn't get resource data for VR called " + vrClassName);
0875 Class<?> vrResourceClass = null;
0876 try {
0877 vrResourceClass = vrResourceData.getResourceClass();
0878 }
0879 catch(ClassNotFoundException ex) {
0880 throw new GateRuntimeException(
0881 "Couldn't create a class object for VR called " + vrClassName);
0882 }// End try
0883 // Test if VR can display all types of annotations
0884 if(vrResourceData.getGuiType() == ResourceData.NULL_GUI
0885 && vrResourceData.getAnnotationTypeDisplayed() != null
0886 && gate.creole.AnnotationVisualResource.class
0887 .isAssignableFrom(vrResourceClass)) {
0888
0889 String annotationTypeDisplayed =
0890 vrResourceData.getAnnotationTypeDisplayed();
0891 if(annotationTypeDisplayed.equals(annotationType)) {
0892 responseList.add(vrClassName);
0893 if(vrResourceData.isMainView()) defaultVR = vrClassName;
0894 }// End if
0895 }// End if
0896 }// End while
0897 if(defaultVR != null) {
0898 responseList.remove(defaultVR);
0899 responseList.addFirst(defaultVR);
0900 }// End if
0901 return Collections.unmodifiableList(responseList);
0902 }// getAnnotationVRs()
0903
0904 /**
0905 * Renames an existing resource.
0906 */
0907 public void setResourceName(Resource res, String newName) {
0908 String oldName = res.getName();
0909 res.setName(newName);
0910 fireResourceRenamed(res, oldName, newName);
0911 }
0912
0913 /**
0914 * Returns a list of strings representing annotations types for which there
0915 * are custom viewers/editor registered.
0916 */
0917 public List<String> getVREnabledAnnotationTypes() {
0918 LinkedList<String> responseList = new LinkedList<String>();
0919 Iterator<String> vrIterator = vrTypes.iterator();
0920 while(vrIterator.hasNext()) {
0921 String vrClassName = vrIterator.next();
0922 ResourceData vrResourceData = this.get(vrClassName);
0923 if(vrResourceData == null)
0924 throw new GateRuntimeException(
0925 "Couldn't get resource data for VR called " + vrClassName);
0926 // Test if VR can display all types of annotations
0927 if(vrResourceData.getGuiType() == ResourceData.NULL_GUI
0928 && vrResourceData.getAnnotationTypeDisplayed() != null) {
0929
0930 String annotationTypeDisplayed =
0931 vrResourceData.getAnnotationTypeDisplayed();
0932 responseList.add(annotationTypeDisplayed);
0933 }// End if
0934 }// End while
0935 return Collections.unmodifiableList(responseList);
0936 }// getVREnabledAnnotationTypes()
0937
0938 /** Get a list of all non-private instantiations. */
0939 protected <T> List<T> getPublics(List<T> instances) {
0940 Iterator<T> iter = instances.iterator();
0941 List<T> publics = new ArrayList<T>();
0942
0943 // for each instance, if resource data specifies it isn't private,
0944 // add to the publics list
0945 while(iter.hasNext()) {
0946 T res = iter.next();
0947 ResourceData rd = get(res.getClass().getName());
0948 if(!rd.isPrivate()) publics.add(res);
0949 }
0950
0951 return Collections.unmodifiableList(publics);
0952 } // getPublics
0953
0954 /** Gets a list of all non private types from alist of types */
0955 protected List<String> getPublicTypes(Collection<String> types) {
0956 Iterator<String> iter = types.iterator();
0957 List<String> publics = new ArrayList<String>();
0958 while(iter.hasNext()) {
0959 String oneType = iter.next();
0960 ResourceData rData = get(oneType);
0961 if(rData != null && !rData.isPrivate()) publics.add(oneType);
0962 }
0963 return Collections.unmodifiableList(publics);
0964 }// getPublicTypes
0965
0966 public synchronized void removeCreoleListener(CreoleListener l) {
0967 if(creoleListeners != null && creoleListeners.contains(l)) {
0968 Vector<CreoleListener> v = (Vector<CreoleListener>)creoleListeners.clone();
0969 v.removeElement(l);
0970 creoleListeners = v;
0971 }
0972 }
0973
0974 public synchronized void addCreoleListener(CreoleListener l) {
0975 Vector<CreoleListener> v =
0976 creoleListeners == null ? new Vector<CreoleListener>(2) : (Vector<CreoleListener>)creoleListeners.clone();
0977 if(!v.contains(l)) {
0978 v.addElement(l);
0979 creoleListeners = v;
0980 }
0981 } // getPublicTypes
0982
0983 /**
0984 * Removes a {@link gate.event.CreoleListener} previously registered with this
0985 * CreoleRegister. {@see #addCreoleListener()}
0986 */
0987
0988 /**
0989 * Registers a {@link gate.event.CreoleListener}with this CreoleRegister. The
0990 * register will fire events every time a resource is added to or removed from
0991 * the system.
0992 */
0993 // addCreoleListener
0994 /**
0995 * Notifies all listeners that a new {@link gate.Resource} has been loaded
0996 * into the system
0997 */
0998 // fireResourceLoaded
0999 /**
1000 * Notifies all listeners that a {@link gate.Resource} has been unloaded from
1001 * the system
1002 */
1003 // fireResourceUnloaded
1004 /** A list of the types of LR in the register. */
1005 protected Set<String> lrTypes;
1006
1007 /** A list of the types of PR in the register. */
1008 protected Set<String> prTypes;
1009
1010 /** A list of the types of VR in the register. */
1011 protected List<String> vrTypes;
1012
1013 /** A list of the types of Controller in the register. */
1014 protected Set<String> controllerTypes;
1015
1016 /** A list of the types of TOOL in the register. */
1017 protected Set<String> toolTypes;
1018
1019 private transient Vector<CreoleListener> creoleListeners;
1020
1021 protected void fireResourceLoaded(CreoleEvent e) {
1022 if(creoleListeners != null) {
1023 Vector<CreoleListener> listeners = creoleListeners;
1024 int count = listeners.size();
1025 for(int i = 0; i < count; i++) {
1026 listeners.elementAt(i).resourceLoaded(e);
1027 }
1028 }
1029 }
1030
1031 protected void fireResourceUnloaded(CreoleEvent e) {
1032 if(creoleListeners != null) {
1033 Vector<CreoleListener> listeners = creoleListeners;
1034 int count = listeners.size();
1035 for(int i = 0; i < count; i++) {
1036 listeners.elementAt(i).resourceUnloaded(e);
1037 }
1038 }
1039 }
1040
1041 protected void fireResourceRenamed(Resource res, String oldName,
1042 String newName) {
1043 if(creoleListeners != null) {
1044 Vector<CreoleListener> listeners = creoleListeners;
1045 int count = listeners.size();
1046 for(int i = 0; i < count; i++) {
1047 listeners.elementAt(i).resourceRenamed(res, oldName,
1048 newName);
1049 }
1050 }
1051 }
1052
1053 protected void fireDatastoreOpened(CreoleEvent e) {
1054 if(creoleListeners != null) {
1055 Vector<CreoleListener> listeners = creoleListeners;
1056 int count = listeners.size();
1057 for(int i = 0; i < count; i++) {
1058 listeners.elementAt(i).datastoreOpened(e);
1059 }
1060 }
1061 }
1062
1063 protected void fireDatastoreCreated(CreoleEvent e) {
1064 if(creoleListeners != null) {
1065 Vector<CreoleListener> listeners = creoleListeners;
1066 int count = listeners.size();
1067 for(int i = 0; i < count; i++) {
1068 listeners.elementAt(i).datastoreCreated(e);
1069 }
1070 }
1071 }
1072
1073 protected void fireDatastoreClosed(CreoleEvent e) {
1074 if(creoleListeners != null) {
1075 Vector<CreoleListener> listeners = creoleListeners;
1076 int count = listeners.size();
1077 for(int i = 0; i < count; i++) {
1078 listeners.elementAt(i).datastoreClosed(e);
1079 }
1080 }
1081 }
1082
1083 public void resourceLoaded(CreoleEvent e) {
1084 fireResourceLoaded(e);
1085 }
1086
1087 public void resourceUnloaded(CreoleEvent e) {
1088 fireResourceUnloaded(e);
1089 }
1090
1091 public void resourceRenamed(Resource resource, String oldName, String newName) {
1092 fireResourceRenamed(resource, oldName, newName);
1093 }
1094
1095 public void datastoreOpened(CreoleEvent e) {
1096 fireDatastoreOpened(e);
1097 }
1098
1099 public void datastoreCreated(CreoleEvent e) {
1100 fireDatastoreCreated(e);
1101 }
1102
1103 public void datastoreClosed(CreoleEvent e) {
1104 fireDatastoreClosed(e);
1105 }
1106
1107 /** The lists of listeners registered with this CreoleRegister */
1108
1109 /**
1110 * Type-safe read-only list used by getLrInstances, getPrInstances, etc.
1111 */
1112 private static class TypedResourceList<T extends Resource>
1113 extends
1114 AbstractList<T> {
1115 private List<Resource> backingList;
1116
1117 private Class<T> realType;
1118
1119 TypedResourceList(List<Resource> backingList, Class<T> realType) {
1120 this.backingList = backingList;
1121 this.realType = realType;
1122 }
1123
1124 public T get(int i) {
1125 return realType.cast(backingList.get(i));
1126 }
1127
1128 public int size() {
1129 return backingList.size();
1130 }
1131 }
1132
1133 } // class CreoleRegisterImpl
|