/* Copyright 2003, Carnegie Mellon, All Rights Reserved */
package edu.cmu.minorthird.text;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.Properties;
import org.apache.log4j.Logger;
import edu.cmu.minorthird.text.mixup.Mixup;
import edu.cmu.minorthird.text.mixup.MixupProgram;
/**
* Analogous to a ClassLoader, this finds annotators by name, so they can be
* applied to a set of labels.
*/
public abstract class AnnotatorLoader{
private static Logger log=Logger.getLogger(AnnotatorLoader.class);
protected static Properties redirectionProps=new Properties();
static{
InputStream s=ClassLoader.getSystemResourceAsStream("annotators.config");
if(s==null){
try{
s=new FileInputStream("./config/annotators.config");
}catch(IOException e){
log.warn("Can't find annotators.config.");
log.warn("classpath: "+System.getProperty("java.class.path"));
log.warn(e);
}
}else{
try{
redirectionProps.load(s);
}catch(IOException e){
log.warn("error trying to load annotators.config: "+e);
}
}
}
/** Find the named resource file - usually a dictionary or trie for mixup. */
abstract public InputStream findFileResource(String fileName);
/** Find the named resource class - usually an annotator. */
abstract public Class<?> findClassResource(String className);
/**
* Find an annotator for the given annotationType, from the listed source. If
* the source is non-null, it attempted to be located via findFileResource and
* if it does not find it there it uses the findClassResource. If the source
* is null, the following rules are followed, in order, to find the source.
* <ol>
* <li>If the classpath contains a file "annotation.properties" that defines
* the annotator source for 'foo' to be 'bar', follow the rules above for
* source 'bar' (i.e., find a file resource 'bar' if 'bar' ends in .mixup, and
* a class resource otherwise.)
* <li>If one can find a file resource "foo.mixup", use that as the source.
* <li>Use 'foo' as a class name.
* </ol>
*/
final public Annotator findAnnotator(String annotationType,String source){
log.debug("Trying to load annotator with annotation type \""+annotationType+"\" from source \""+source+"\"");
if(source!=null){
// see if the source is a mixup file
if(source.endsWith(".mixup")){
log.debug("Trying to load annotator from mixup file: "+source);
// first use findFileResource method
InputStream is=findFileResource(source);
// if that fails, try to load the file directly
if(is==null){
try{
is=new FileInputStream(source);
}catch(Exception e){
e.printStackTrace();
}
}
if(is==null){
log.warn("Cannot load annotator from source: "+source);
return null;
}
else{
return findMixupAnnotatorFromStream(source,is);
}
}
// if source isn't mixup, then it's either part of an encapsulated annotator or is a class that needs to be loaded natively by java
else{
log.debug("Trying to load annotator from non-mixup source: "+source);
// first check to see if the saved annotator is being served as a object from a stream such as if the annotator is encapsulated inside another annotator
log.debug("Trying to load annotator from a file stream: "+source);
Annotator ann=findSavedAnnotatorFromStream(source,findFileResource(source));
if(ann==null){
// otherwise find the native annotator from class name
log.debug("Trying to load annotator from class name: "+source);
ann=findNativeAnnotatorFromString(source);
}
if(ann==null){
log.warn("Cannot load annotator from source: "+source);
return null;
}
else{
return ann;
}
}
}
// if the source does not lead us to the annotator check the annotation type
else{
log.debug("Source not provided, trying to load from annotation type");
// Check to see if the annotation type specifies a redirection
String redirect=redirectionProps.getProperty(annotationType);
if(redirect!=null){
log.debug("Redirected to "+redirect);
return findAnnotator(annotationType,redirect);
}
else{
log.debug("No redirection, assuming the annotation type is source and trying again");
return findAnnotator(null,annotationType);
}
}
}
// This method attempts to locate an annotator named as provided using the
// supplied input stream
final private Annotator findSavedAnnotatorFromStream(String annotatorName,
InputStream s){
log.debug("Trying to find saved Annotator "+annotatorName+" from stream "+s);
if(s!=null){
try{
byte[] buf=new byte[s.available()];
s.read(buf);
ByteArrayInputStream input=new ByteArrayInputStream(buf);
ObjectInputStream objInput=new ObjectInputStream(input);
return (Annotator)objInput.readObject();
}catch(IOException e){
e.printStackTrace();
return null;
}catch(ClassNotFoundException e){
e.printStackTrace();
return null;
}
}
else{
log.warn("Cannot find saved Annotator because InputStream is null");
return null;
}
}
final private Annotator findMixupAnnotatorFromStream(String fileName,
InputStream s){
log.debug("finding MixupProgram "+fileName+" in stream "+s);
if(s==null){
log.warn("couldn't find mixup program "+fileName+" using "+this);
return null;
}
try{
byte[] buf=new byte[s.available()];
s.read(buf);
MixupProgram p=new MixupProgram(new String(buf));
return new MixupAnnotator(p);
}catch(Mixup.ParseException e){
log.warn("error parsing "+fileName+": "+e);
return null;
}catch(IOException e){
log.warn("error loading "+fileName+": "+e);
return null;
}
}
final private Annotator findNativeAnnotatorFromString(String className){
log.debug("Looking for native annotator class "+className);
try{
Class<?> c=findClassResource(className);
Object o=c.newInstance();
if(o instanceof Annotator)
return (Annotator)o;
else
log.warn(c+", found from "+className+" via "+this+
", is not an instance of Annotator");
}catch(Exception e){
log.warn(this+" can't find class named "+className+": "+e);
}
return null;
}
}