/* * 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.mapping; import org.apache.uima.cas.TypeSystem; import org.apache.uima.cas.Type; import org.apache.uima.cas.Feature; import org.apache.uima.cas.CAS; import gate.Document; import gate.Annotation; import gate.AnnotationSet; import org.apache.uima.cas.FeatureStructure; import org.apache.uima.cas.CASRuntimeException; import org.jdom.Element; import java.util.List; import java.util.ArrayList; import java.util.Iterator; /** * An ObjectBuilder that creates a UIMA FeatureStructure. */ public class UIMAFeatureStructureBuilder implements ObjectBuilder { /** * The UIMA Type of the feature structure to generate. */ protected Type fsType; /** * Feature definitions for this feature structure. */ protected List featureDefs; /** * Configure this ObjectBuilder by extracting the FeatureStructure type and * feature definitions from the XML element. */ public void configure(Element elt, TypeSystem typeSystem) throws MappingException { String fsTypeName = elt.getAttributeValue("type"); if(fsTypeName == null) { throw new MappingException("No \"type\" attribute specified for " + "featureStructure"); } fsType = typeSystem.getType(fsTypeName); if(fsType == null) { throw new MappingException("Type " + fsTypeName + " not found in UIMA type system"); } // build the list of feature definitions for this FS List featureElements = elt.getChildren("feature"); featureDefs = new ArrayList(featureElements.size()); Iterator featureElementsIt = featureElements.iterator(); while(featureElementsIt.hasNext()) { Element featureElt = (Element)featureElementsIt.next(); String featureName = featureElt.getAttributeValue("name"); if(featureName == null) { throw new MappingException("feature element must have \"name\" " + "attribute specified"); } Feature featureObject = fsType.getFeatureByBaseName(featureName); if(featureObject == null) { throw new MappingException("feature named \"" + featureName + "\" in " + "type \"" + fsTypeName + "\" does not exist in type system"); } String featureKind = featureElt.getAttributeValue("kind"); if(featureKind == null) { throw new MappingException("feature element must have \"kind\" " + "attribute specified"); } List children = featureElt.getChildren(); if(children.isEmpty()) { throw new MappingException("feature element must have a child element " + "specifying its value"); } Element valueElement = (Element)children.get(0); // create the object builder that gives this feature's value ObjectBuilder valueBuilder = ObjectManager.createBuilder(valueElement, typeSystem); featureDefs.add(new FeatureDefinition(featureName, featureKind, valueBuilder, featureObject)); } } /** * Constructs and returns the FeatureStructure. */ public Object buildObject(CAS cas, Document doc, AnnotationSet annSet, Annotation currentAnn, FeatureStructure currentFS) throws MappingException { FeatureStructure newFS = createFS(cas, doc, currentAnn, fsType); populateFeatures(newFS, cas, doc, annSet, currentAnn, currentFS); return newFS; } /** * Create the feature structure object. This method may be overridden by * subclasses that create more specific types of FS (e.g. annotations). */ protected FeatureStructure createFS(CAS cas, Document doc, Annotation currentAnn, Type fsType) { return cas.createFS(fsType); } /** * Uses the set of feature definitions to populate the features of the given * feature structure. */ public void populateFeatures(FeatureStructure newFS, CAS cas, Document doc, AnnotationSet annSet, Annotation currentAnn, FeatureStructure currentFS) throws MappingException { Iterator featuresIt = featureDefs.iterator(); while(featuresIt.hasNext()) { FeatureDefinition def = (FeatureDefinition)featuresIt.next(); // build the feature value ObjectBuilder valueBuilder = def.getValueBuilder(); Object featureValue = valueBuilder.buildObject(cas, doc, annSet, currentAnn, currentFS); // based on the feature kind, add it to the FS appropriately switch(def.getFeatureKind()) { // String kind - call toString on the value object and use that case FeatureDefinition.STRING_KIND: newFS.setStringValue(def.getCASFeatureObject(), String.valueOf(featureValue)); break; // integer kind - if the value object is a Number, call intValue, // otherwise try and parse the toString as an integer. If this fails, // give up. case FeatureDefinition.INT_KIND: if(featureValue instanceof Number) { newFS.setIntValue(def.getCASFeatureObject(), ((Number)featureValue).intValue()); } else { try { newFS.setIntValue(def.getCASFeatureObject(), Integer.parseInt(String.valueOf(featureValue))); } catch(NumberFormatException nfe) { throw new MappingException("Couldn't convert feature value \"" + featureValue + "\" to integer", nfe); } } break; // float kind - if the value object is a Number, call floatValue, // otherwise try and parse the toString as a float. If this fails, // give up. case FeatureDefinition.FLOAT_KIND: if(featureValue instanceof Number) { newFS.setFloatValue(def.getCASFeatureObject(), ((Number)featureValue).floatValue()); } else { try { newFS.setFloatValue(def.getCASFeatureObject(), Float.parseFloat(String.valueOf(featureValue))); } catch(NumberFormatException nfe) { throw new MappingException("Couldn't convert feature value \"" + featureValue + "\" to float", nfe); } } break; // feature structure kind - cast the value to a feature structure and // hope... case FeatureDefinition.FS_KIND: if(featureValue instanceof FeatureStructure) { newFS.setFeatureValue(def.getCASFeatureObject(), (FeatureStructure)featureValue); } else { throw new MappingException("Value for feature \"" + def.getCASFeatureObject().getName() + "\" should be " + "a FeatureStructure"); } break; default: throw new MappingException( "Unrecognised kind for feature definition"); } } } }