/*
* Copyright (c) 2005, The University of Sheffield.
*
* This file is part of the GATE/UIMA integration layer, and is free
* software, released under the terms of the GNU Lesser General Public
* Licence, version 2.1 (or any later version). A copy of this licence
* is provided in the file LICENCE in the distribution.
*
* UIMA is a product of IBM, details are available from
* http://alphaworks.ibm.com/tech/uima
*/
package gate.uima;
import gate.uima.mapping.*;
import gate.*;
import gate.util.*;
import gate.creole.*;
import java.net.URL;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
// UIMA imports
import org.apache.uima.UIMAFramework;
import org.apache.uima.util.XMLParser;
import org.apache.uima.util.XMLInputSource;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.ProcessTrace;
import org.apache.uima.util.CasCreationUtils;
import org.apache.uima.analysis_engine.AnalysisEngine;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.ResourceSpecifier;
import org.apache.uima.resource.metadata.ResourceMetaData;
import org.apache.uima.cas.CASRuntimeException;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.Feature;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.cas.FSIndexRepository;
import org.apache.uima.cas.FSIndex;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.ConstraintFactory;
import org.apache.uima.cas.FSMatchConstraint;
import org.apache.uima.cas.FSStringConstraint;
import org.apache.uima.cas.FeaturePath;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.cas.impl.XCASSerializer;
// JDOM imports
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.JDOMException;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
import org.xml.sax.SAXException;
/**
* A processing resource that encapsulates a Text Analysis Engine from UIMA.
*/
public class AnalysisEnginePR extends AbstractLanguageAnalyser {
/** Version string for CVS. */
private static final String __CVSID = "$Id: AnalysisEnginePR.java 11705 2009-10-21 13:27:41Z ian_roberts $";
private static final boolean DEBUG = false;
///// init parameters /////
/**
* URL to the UIMA XML descriptor for the contained analysis engine.
*/
private URL analysisEngineDescriptor;
/**
* @return the location of the UIMA descriptor for the analysis engine.
*/
public URL getAnalysisEngineDescriptor() {
return analysisEngineDescriptor;
}
/**
* Set the URL to the UIMA analysis engine descriptor.
*/
public void setAnalysisEngineDescriptor(URL newDescriptor) {
analysisEngineDescriptor = newDescriptor;
}
/**
* URL to the XML file defining the mapping from GATE annotations to UIMA
* feature structures, and the mapping from modifications to the UIMA feature
* structures back into GATE.
*/
private URL mappingDescriptor;
/**
* @return the location of the mapping descriptor.
*/
public URL getMappingDescriptor() {
return mappingDescriptor;
}
/**
* Set the URL to the UIMA/GATE mapping descriptor.
*/
public void setMappingDescriptor(URL newDescriptor) {
mappingDescriptor = newDescriptor;
}
///// runtime parameters /////
/**
* The annotation set to use for annotations that are to be mapped to and
* from UIMA.
*/
private String annotationSetName = null;
/**
* Get the name of the annotation set to use for annotations that are to be
* mapped to and from UIMA.
*/
public String getAnnotationSetName() {
return annotationSetName;
}
public void setAnnotationSetName(String newName) {
annotationSetName = newName;
}
///// private variables /////
/**
* The UIMA analysis engine that actually does the work.
*/
private AnalysisEngine analysisEngine;
/**
* The CAS used to pass annotations into and out of the TAE.
*/
private CAS cas;
/**
* A List of ObjectBuilders defining the input mappings of GATE annotations
* to UIMA annotations.
*/
private List inputMappings;
/**
* A list of ObjectBuilders defining the new annotations created by UIMA that
* should be mapped back into GATE.
*/
private List outputsAdded;
/**
* A list of ObjectBuilders defining the annotations whose features have been
* updated by UIMA, and for which changes should be propagated back into
* GATE.
*/
private List outputsUpdated;
/**
* A list of ObjectBuilders giving the annotations that have been removed by
* UIMA and for which the corresponding annotations should be removed in
* GATE.
*/
private List outputsRemoved;
////// variables for the GATE/UIMA index //////
/**
* Feature Structure Type for the AnnotationSource FS type used for the
* GATE/UIMA index.
*/
private Type annotationSourceType;
private static final String ANNOTATIONSOURCE_TYPE_NAME =
"gate.uima.mapping.AnnotationSource";
private Feature annotationSource_UIMAAnnotationFeature;
private static final String ANNOTATIONSOURCE_UIMAANNOTATION_FEATURE_NAME =
ANNOTATIONSOURCE_TYPE_NAME + ":UIMAAnnotation";
private Feature annotationSource_GATEAnnotationIDFeature;
private static final String ANNOTATIONSOURCE_GATEANNOTATIONID_FEATURE_NAME =
ANNOTATIONSOURCE_TYPE_NAME + ":GATEAnnotationID";
private Feature annotationSource_GATEAnnotationTypeFeature;
private static final String ANNOTATIONSOURCE_GATEANNOTATIONTYPE_FEATURE_NAME =
ANNOTATIONSOURCE_TYPE_NAME + ":GATEAnnotationType";
private FSIndex gateFSIndex;
private static final String GATE_INDEX_LABEL = "GATEIndex";
private FeaturePath gateAnnotationTypePath;
/**
* Initialise this resource. This method creates the underlying UIMA objects
* from their XML descriptor and parses the mapping definition.
*/
public gate.Resource init() throws ResourceInstantiationException {
// Sanity check on parameters - AE descriptor must be a non-null file: URL
if(analysisEngineDescriptor == null) {
throw new ResourceInstantiationException(
"Analysis engine descriptor location must be specified");
}
if(!analysisEngineDescriptor.getProtocol().equals("file")) {
throw new ResourceInstantiationException(
"Analysis engine descriptor location must be a file: URL");
}
// mapping descriptor must be non-null
if(mappingDescriptor == null) {
throw new ResourceInstantiationException(
"Annotation mapping descriptor must be specified");
}
// parse the uima descriptor and create the AE
try {
URI aeDescriptorURI =
URI.create(analysisEngineDescriptor.toExternalForm());
File aeDescriptorDir = new File(aeDescriptorURI).getParentFile();
XMLInputSource aeDescriptorSource =
new XMLInputSource(analysisEngineDescriptor.openStream(),
aeDescriptorDir);
XMLParser uimaXMLParser = UIMAFramework.getXMLParser();
// use more general type to allow for remote services
//TaeDescription taeDescription =
// uimaXMLParser.parseTaeDescription(aeDescriptorSource);
ResourceSpecifier taeDescription =
uimaXMLParser.parseResourceSpecifier(aeDescriptorSource);
analysisEngine = UIMAFramework.produceAnalysisEngine(taeDescription);
// load our GATE-specific type system and index information
XMLInputSource gateIndexSource = new XMLInputSource(
this.getClass().getResourceAsStream("gateIndexTypeDefinition.xml"),
new File(""));
ResourceMetaData gateIndexDescription =
uimaXMLParser.parseResourceMetaData(gateIndexSource);
// create a CAS to use for the analysis engine and the GATE/UIMA index.
// CAS instances are expensive to create, so we reuse the same tcas for
// all documents.
List casSpecs = Arrays.asList(new Object[] {
analysisEngine.getAnalysisEngineMetaData(),
gateIndexDescription});
//tcas = analysisEngine.newTCAS();
cas = CasCreationUtils.createCas(casSpecs);
}
catch(IOException ioe) {
throw new ResourceInstantiationException(ioe);
}
catch(InvalidXMLException ixe) {
// error in the TAE descriptor
throw new ResourceInstantiationException(ixe);
}
catch(ResourceInitializationException rie) {
// error creating TAE
throw new ResourceInstantiationException(rie);
}
// parse the mapping file somehow
SAXBuilder builder = new SAXBuilder();
builder.setErrorHandler(new ErrorHandler() {
public void warning(SAXParseException ex) {
// do nothing on warnings
}
// treat all errors as fatal
public void error(SAXParseException ex) throws SAXException {
throw ex;
}
public void fatalError(SAXParseException ex) throws SAXException {
throw ex;
}
});
org.jdom.Document configDoc = null;
try {
configDoc = builder.build(mappingDescriptor);
}
catch(JDOMException jde) {
throw (ResourceInstantiationException)
new ResourceInstantiationException("Error parsing mapping file")
.initCause(jde);
}
catch(IOException ioe) {
throw (ResourceInstantiationException)
new ResourceInstantiationException("Error reading mapping file")
.initCause(ioe);
}
processMappingDescriptor(configDoc, cas.getTypeSystem());
initUimaGateIndex(cas.getTypeSystem());
return this;
}
/**
* Executes the contained UIMA analysis engine, mapping the annotations to
* and from the GATE document as defined by the mapping descriptor.
*/
public void execute() throws ExecutionException {
// trick to make sure the finally block doesn't hide exceptions that
// happened further up
boolean exceptionThrown = true;
try {
// populate the CAS with the text and input annotations according to
// mapping
cas.setDocumentText(document.getContent().toString());
mapInputAnnotations();
if(DEBUG) {
File logfile = new File("casBefore.xml");
try {
FileOutputStream fos = new FileOutputStream(logfile);
XCASSerializer.serialize(cas, fos);
fos.close();
}
catch(Exception ex) {
ex.printStackTrace();
}
}
// run the AE
ProcessTrace trace = analysisEngine.process(cas);
if(DEBUG) {
/* FSIndex annIndex = tcas.getAnnotationIndex();
FSIterator it = annIndex.iterator();
System.out.println("Dumping all annotations from CAS:");
while(it.hasNext()) {
Object obj = it.next();
Class clz = obj.getClass();
while(clz != null) {
System.out.print(clz.toString() + Arrays.asList(clz.getInterfaces()) + "<-");
clz = clz.getSuperclass();
}
System.out.println(obj);
}*/
File logfile = new File("casAfter.xml");
try {
FileOutputStream fos = new FileOutputStream(logfile);
XCASSerializer.serialize(cas, fos);
fos.close();
}
catch(Exception ex) {
ex.printStackTrace();
}
}
// compute the differences and map outputs back into document
mapOutputs();
exceptionThrown = false;
}
catch(AnalysisEngineProcessException aepe) {
throw new ExecutionException(aepe);
}
catch(CASRuntimeException tre) {
throw new ExecutionException(tre);
}
finally {
try {
// clear out the CAS ready for the next document
cas.reset();
clearIndexes();
}
catch(CASRuntimeException cre) {
// oh well, we tried - only rethrow this exception if there isn't a
// higher level one that we would mask
if(!exceptionThrown) {
throw new ExecutionException(cre);
}
}
}
}
/**
* Use the defined input mappings to populate the initial CAS.
*/
private void mapInputAnnotations() throws ExecutionException {
// nothing to do if there are no input mappings
if(inputMappings == null || inputMappings.isEmpty()) {
return;
}
// get the UIMA index repository, to which generated feature structures
// will be added
FSIndexRepository uimaIndexes = cas.getIndexRepository();
if(uimaIndexes == null) {
throw new ExecutionException("No index repository found for CAS - "
+ "there should be at least the AnnotationIndex");
}
// get the GATE annotation set that will be the source for GATE annotations
// to map into UIMA
AnnotationSet sourceSet = null;
if(annotationSetName == null) {
sourceSet = document.getAnnotations();
}
else {
sourceSet = document.getAnnotations(annotationSetName);
}
Iterator inputsIt = inputMappings.iterator();
while(inputsIt.hasNext()) {
UIMAFeatureStructureBuilder fsBuilder =
(UIMAFeatureStructureBuilder)inputsIt.next();
if(fsBuilder instanceof UIMAAnnotationBuilder) {
UIMAAnnotationBuilder annotBuilder = (UIMAAnnotationBuilder)fsBuilder;
// if it's an annotation builder then call it once for each annotation
// of the appropriate type
// get all annotations of the appropriate type
AnnotationSet annotsToMap =
sourceSet.get(annotBuilder.getGateAnnotationType());
if(annotsToMap != null) {
Iterator annotsToMapIt = annotsToMap.iterator();
while(annotsToMapIt.hasNext()) {
gate.Annotation gateAnnot = (gate.Annotation)annotsToMapIt.next();
try {
AnnotationFS uimaAnnot =
(AnnotationFS)annotBuilder.buildObject(cas, document,
sourceSet, gateAnnot,
null);
// add to UIMA index repository - this is important
uimaIndexes.addFS(uimaAnnot);
if(annotBuilder.isIndexed()) {
addToUimaGateIndex(uimaAnnot, gateAnnot);
}
}
catch(MappingException mx) {
throw (ExecutionException)
new ExecutionException("Error mapping input annotations")
.initCause(mx);
}
}
}
}
else {
// if it's not an annotation builder, just call it once and add the
// result to the CAS
try {
FeatureStructure fs =
(FeatureStructure)fsBuilder.buildObject(cas, document, sourceSet,
null, null);
uimaIndexes.addFS(fs);
}
catch(MappingException mx) {
throw (ExecutionException)
new ExecutionException("Error mapping input annotations")
.initCause(mx);
}
}
}
}
/**
* Use the output mappings to map changes in the UIMA annotations back into
* GATE.
*/
private void mapOutputs() throws ExecutionException {
FSIndexRepository uimaIndexes = cas.getIndexRepository();
if(uimaIndexes == null) {
throw new ExecutionException("No index repository found for CAS - "
+ "there should be at least the AnnotationIndex");
}
// get the GATE annotation set that this PR operates on
AnnotationSet annSet = null;
if(annotationSetName == null) {
annSet = document.getAnnotations();
}
else {
annSet = document.getAnnotations(annotationSetName);
}
// added annotations
if(!outputsAdded.isEmpty()) {
Iterator outputsAddedIt = outputsAdded.iterator();
while(outputsAddedIt.hasNext()) {
GateAnnotationBuilder outputBuilder =
(GateAnnotationBuilder)outputsAddedIt.next();
// iterate over all the UIMA annotations of the appropriate type and
// create GATE annotations to correspond
Type uimaAnnotationType = outputBuilder.getUimaType();
FSIndex uimaIndex = cas.getAnnotationIndex(uimaAnnotationType);
Iterator uimaIndexIt = uimaIndex.iterator();
while(uimaIndexIt.hasNext()) {
FeatureStructure uimaAnn = (FeatureStructure)uimaIndexIt.next();
try {
outputBuilder.buildObject(cas, document, annSet, null, uimaAnn);
}
catch(MappingException mx) {
throw (ExecutionException)
new ExecutionException("Error mapping output annotations")
.initCause(mx);
}
}
}
}
// updated annotations
if(!outputsUpdated.isEmpty()) {
Iterator outputsUpdatedIt = outputsUpdated.iterator();
while(outputsUpdatedIt.hasNext()) {
GateAnnotationBuilder outputBuilder =
(GateAnnotationBuilder)outputsUpdatedIt.next();
String gateAnnotType = outputBuilder.getGateType();
// iterate over all the GATE annotations of the appropriate type, find
// their corresponding UIMA annotations and update the GATE
// annotation's features
FSIterator indexIt = getIndexIterator(gateAnnotType);
while(indexIt.hasNext()) {
FeatureStructure indexEntry = (FeatureStructure)indexIt.next();
if(DEBUG) {
System.err.println("Updating outputs - index entry: " + indexEntry);
}
FeatureStructure uimaAnnot = getUIMAAnnotationFromIndex(indexEntry);
Annotation gateAnnot = getGATEAnnotationFromIndex(indexEntry, annSet);
try {
outputBuilder.updateFeatures(cas, document, annSet, gateAnnot,
uimaAnnot);
}
catch(MappingException mx) {
throw (ExecutionException)
new ExecutionException("Error mapping output annotations")
.initCause(mx);
}
}
}
}
// removed annotations
if(!outputsRemoved.isEmpty()) {
FSIndex allAnnotationsIndex = cas.getAnnotationIndex();
Iterator outputsRemovedIt = outputsRemoved.iterator();
while(outputsRemovedIt.hasNext()) {
GateAnnotationBuilder outputBuilder =
(GateAnnotationBuilder)outputsRemovedIt.next();
String gateAnnotType = outputBuilder.getGateType();
// iterate over all the GATE annotations of the appropriate type, find
// their corresponding UIMA annotations and update the GATE
// annotation's features
FSIterator indexIt = getIndexIterator(gateAnnotType);
INDEX_ENTRY: while(indexIt.hasNext()) {
FeatureStructure indexEntry = (FeatureStructure)indexIt.next();
if(DEBUG) {
System.err.println("\"removed\" output - index entry: " + indexEntry);
}
FeatureStructure uimaAnnot = getUIMAAnnotationFromIndex(indexEntry);
Annotation gateAnnot = getGATEAnnotationFromIndex(indexEntry, annSet);
// try and find uimaAnnot in the annotation index. If it is not
// there, it was removed by the TAE so remove the corresponding GATE
// annotation.
// We get an iterator that starts with the first feature structure
// that is >= uimaAnnot under the AnnotationIndex ordering, i.e. the
// first annotation that starts at the same place or to the right of
// uimaAnnot
FSIterator annotIndexIt = allAnnotationsIndex.iterator(uimaAnnot);
// now iterate starting from this location until either (a) we run
// out of annotations in the AnnotationIndex, or (b) we come to an
// annotation that is not equal to uimaAnnot under the index
// ordering.
while(annotIndexIt.isValid()
&& allAnnotationsIndex.compare(annotIndexIt.get(),
uimaAnnot) == 0) {
// check whether the current annotation from the AnnotationIndex is
// actually equal to uimaAnnot. If so, we have found uimaAnnot
// still in the index, so we don't want to remove gateAnnot from
// the GATE document.
if(annotIndexIt.get().equals(uimaAnnot)) {
continue INDEX_ENTRY;
}
annotIndexIt.moveToNext();
}
// if we get to here, we know that uimaAnnot is no longer in the
// index, so remove its corresponding gateAnnot from the GATE
// annotation set.
annSet.remove(gateAnnot);
// Whew! That was hard work.
}
}
}
}
///// GATE/UIMA annotation indexes /////
/**
* Initialise the necessary variables for the GATE/UIMA index.
*/
private void initUimaGateIndex(TypeSystem typeSystem)
throws ResourceInstantiationException {
annotationSourceType = typeSystem.getType(ANNOTATIONSOURCE_TYPE_NAME);
if(annotationSourceType == null) {
throw new ResourceInstantiationException("Could not find "
+ ANNOTATIONSOURCE_TYPE_NAME + " in type system");
}
annotationSource_UIMAAnnotationFeature = typeSystem.getFeatureByFullName(
ANNOTATIONSOURCE_UIMAANNOTATION_FEATURE_NAME);
if(annotationSource_UIMAAnnotationFeature == null) {
throw new ResourceInstantiationException("Could not find feature "
+ ANNOTATIONSOURCE_UIMAANNOTATION_FEATURE_NAME + " in type system");
}
annotationSource_GATEAnnotationIDFeature = typeSystem.getFeatureByFullName(
ANNOTATIONSOURCE_GATEANNOTATIONID_FEATURE_NAME);
if(annotationSource_GATEAnnotationIDFeature == null) {
throw new ResourceInstantiationException("Could not find feature "
+ ANNOTATIONSOURCE_GATEANNOTATIONID_FEATURE_NAME + " in type system");
}
annotationSource_GATEAnnotationTypeFeature =
typeSystem.getFeatureByFullName(
ANNOTATIONSOURCE_GATEANNOTATIONTYPE_FEATURE_NAME);
if(annotationSource_GATEAnnotationTypeFeature == null) {
throw new ResourceInstantiationException("Could not find feature "
+ ANNOTATIONSOURCE_GATEANNOTATIONTYPE_FEATURE_NAME
+ " in type system");
}
FSIndexRepository uimaIndexes = cas.getIndexRepository();
gateFSIndex = uimaIndexes.getIndex(GATE_INDEX_LABEL);
if(gateFSIndex == null) {
throw new ResourceInstantiationException("Couldn't find GATE index "
+ "in UIMA index repository");
}
gateAnnotationTypePath = cas.createFeaturePath();
gateAnnotationTypePath.addFeature(
annotationSource_GATEAnnotationTypeFeature);
}
/**
* Clear the indexes mapping GATE annotations to UIMA ones.
*/
private void clearIndexes() {
// nothing to do - the index is stored in the CAS, so will clear when the
// CAS is reset
}
/**
* Store a GATE/UIMA annotation pair in the index.
*/
private void addToUimaGateIndex(AnnotationFS uimaAnnot,
gate.Annotation gateAnnot) {
//uimaGateIndex.put(uimaAnnot, gateAnnot.getId());
FeatureStructure indexEntry = cas.createFS(annotationSourceType);
indexEntry.setFeatureValue(annotationSource_UIMAAnnotationFeature,
uimaAnnot);
indexEntry.setIntValue(annotationSource_GATEAnnotationIDFeature,
gateAnnot.getId().intValue());
indexEntry.setStringValue(annotationSource_GATEAnnotationTypeFeature,
gateAnnot.getType());
cas.getIndexRepository().addFS(indexEntry);
if(DEBUG) {
System.out.println("Put annotation " + gateAnnot + " into index.");
}
}
/**
* Returns an FSIterator over the GATE/UIMA index for the index entries that
* refer to the specified type of GATE annotation.
*/
private FSIterator getIndexIterator(String gateAnnotType) {
ConstraintFactory cf = cas.getConstraintFactory();
// construct a matching constraint to allow us to iterate over only
// those index entries that refer to the right kind of GATE annotation
FSStringConstraint annotTypeConstraint = cf.createStringConstraint();
annotTypeConstraint.equals(gateAnnotType);
FSMatchConstraint matchConstraint =
cf.embedConstraint(gateAnnotationTypePath, annotTypeConstraint);
FSIterator allIndexEntriesIt = gateFSIndex.iterator();
FSIterator indexIt = cas.createFilteredIterator(
allIndexEntriesIt, matchConstraint);
return indexIt;
}
/**
* Extract the UIMA annotation from an index entry.
*/
private FeatureStructure getUIMAAnnotationFromIndex(
FeatureStructure indexEntry) {
return indexEntry.getFeatureValue(annotationSource_UIMAAnnotationFeature);
}
/**
* Returns the GATE annotation from the given set referenced by the given
* index entry.
*/
private gate.Annotation getGATEAnnotationFromIndex(
FeatureStructure indexEntry, AnnotationSet as) {
int gateID =
indexEntry.getIntValue(annotationSource_GATEAnnotationIDFeature);
return as.get(new Integer(gateID));
}
//////// processing the mapping descriptor ////////
private void processMappingDescriptor(org.jdom.Document doc,
TypeSystem typeSystem)
throws ResourceInstantiationException {
Element topElement = doc.getRootElement();
// process input section
Element inputsElement = topElement.getChild("inputs");
inputMappings = new ArrayList();
if(inputsElement != null) {
List inputElements = inputsElement.getChildren();
Iterator inputMappingsIt = inputElements.iterator();
while(inputMappingsIt.hasNext()) {
Element mapping = (Element)inputMappingsIt.next();
try {
ObjectBuilder inputBuilder =
ObjectManager.createBuilder(mapping, typeSystem);
if(!(inputBuilder instanceof UIMAFeatureStructureBuilder)) {
throw new ResourceInstantiationException(
"input mapping must be a feature structure builder");
}
inputMappings.add(inputBuilder);
}
catch(MappingException mx) {
throw (ResourceInstantiationException)
new ResourceInstantiationException("Error creating input mapping")
.initCause(mx);
}
}
}
// process outputs
outputsAdded = new ArrayList();
outputsUpdated = new ArrayList();
outputsRemoved = new ArrayList();
Element outputsElement = topElement.getChild("outputs");
if(outputsElement != null) {
String[] elements = new String[] {"added", "updated", "removed"};
List[] lists = new List[] {outputsAdded, outputsUpdated, outputsRemoved};
for(int i = 0; i < elements.length; i++) {
Element elt = outputsElement.getChild(elements[i]);
if(elt != null) {
List outputElements = elt.getChildren();
Iterator outputMappingsIt = outputElements.iterator();
while(outputMappingsIt.hasNext()) {
Element mapping = (Element)outputMappingsIt.next();
try {
ObjectBuilder outputBuilder =
ObjectManager.createBuilder(mapping, typeSystem);
if(!(outputBuilder instanceof GateAnnotationBuilder)) {
throw new ResourceInstantiationException(
"output mapping must be a GATE annotation builder");
}
lists[i].add(outputBuilder);
}
catch(MappingException mx) {
throw (ResourceInstantiationException)
new ResourceInstantiationException(
"Error creating output mapping").initCause(mx);
}
}
}
}
}
}
}