You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2008/01/27 15:21:41 UTC
svn commit: r615608 [1/2] - in
/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima:
analysis_engine/ analysis_engine/impl/ analysis_engine/impl/compatibility/
flow/impl/ uimacpp/
Author: schor
Date: Sun Jan 27 06:21:40 2008
New Revision: 615608
URL: http://svn.apache.org/viewvc?rev=615608&view=rev
Log:
[UIMA-721] Still left to do, as an incremental improvement - replace use of CapabilityContainer with ResultSpecification, and do an appropriate union of input types needed by annotators in the Flow when computing the Capability Language Flow.
Modified:
incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngine.java
incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/ResultSpecification.java
incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineImplBase.java
incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/PrimitiveAnalysisEngine_impl.java
incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/ResultSpecification_impl.java
incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/compatibility/AnnotatorAdapter.java
incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/flow/impl/CapabilityLanguageFlowController.java
incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/flow/impl/CapabilityLanguageFlowObject.java
incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/uimacpp/CppUimajEngine.java
Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngine.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngine.java?rev=615608&r1=615607&r2=615608&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngine.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngine.java Sun Jan 27 06:21:40 2008
@@ -24,6 +24,7 @@
import org.apache.uima.analysis_engine.metadata.AnalysisEngineMetaData;
import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.TypeSystem;
import org.apache.uima.collection.base_cpm.CasObjectProcessor;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ConfigurableResource;
@@ -510,13 +511,26 @@
public void collectionProcessComplete() throws AnalysisEngineProcessException;
/**
- * A factory method used to create an instance of {@link ResultSpecification} for use with this
+ * <p>A factory method used to create an instance of {@link ResultSpecification} for use with this
* AnalysisEngine. Applications use this method to construct <code>ResultSpecification</code>s
* to pass to this AnalysisEngine's {@link #setResultSpecification(ResultSpecification)} method.
*
+ * <p>
+ * See also {@link #createResultSpecification(TypeSystem)} which should be used if the
+ * type system associated with this result specification is known at this point in time.
+ *
* @return a new instance of <code>ResultSpecification</code>
*/
public ResultSpecification createResultSpecification();
+
+ /**
+ * A factory method used to create an instance of {@link ResultSpecification} for use with this
+ * AnalysisEngine. Applications use this method to construct <code>ResultSpecification</code>s
+ * to pass to this AnalysisEngine's {@link #setResultSpecification(ResultSpecification)} method.
+ *
+ * @return a new instance of <code>ResultSpecification</code>
+ */
+ public ResultSpecification createResultSpecification(TypeSystem aTypeSystem);
/**
* Gets the {@link ResourceManager} used by this AnalysisEngine.
Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/ResultSpecification.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/ResultSpecification.java?rev=615608&r1=615607&r2=615608&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/ResultSpecification.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/ResultSpecification.java Sun Jan 27 06:21:40 2008
@@ -30,30 +30,82 @@
* A <code>ResultSpecification</code> is a set of desired outputs from a Analysis Engine or
* Annotator. Each output is a reference to either a {@link org.apache.uima.cas.Type} or a
* {@link org.apache.uima.cas.Feature}.
+ *
* <p>
* Annotator implementations may, but are not required to, check the <code>ResultSpecification</code>
* passed as a parameter to their {@link AnalysisComponent#setResultSpecification(ResultSpecification)}},
* and produce only those <code>Type</code>s and <code>Feature</code>s that are part of the
* ResultSpecification. Annotators can call the {@link #containsType(String)} and
* {@link #containsFeature(String)} to determine which types and features belong to this
- * ResultSpecification and should be produced.
+ * ResultSpecification and should be produced.
+ *
+ * <p>
+ * The containsType(...) method also returns true for subtypes of types specified in the result specification.
+ * The containsFeature(...) method also returns true for all features of a type if the type's
+ * allAnnotatorFeatures flag is set. As a corner case, the containsFeature may return
+ * true in this case even if the feature is not actually part of the type system.
+ *
* <p>
* ResultSpecifications are language enabled to allow different values to be set and returned, based
- * on a ISO language identifier. There are two styles of the get and add methods: one takes an
+ * on a ISO language identifier. There are two styles of the get and add methods that add these
+ * specifications to an instance of a ResultSpecification: one takes an
* additional parameter specifying the language(s), the other doesn't have this parameter. Using the
* one without the language parameter is equivalent to using the "x-unspecified" language. The
* functions that add ResultSpecifications can do this for multiple languages at once because the
* language parameter is an array of strings. The functions to retrieve a ResultSpecification
* specify one particular language.
+ *
+ * <p>The language x-unspecified is used like a wild-card, in that it matches any language.
+ * Result Specifications for particular types or features have an associated set of languages
+ * which they are set for. That associated set of languages can include the "x-unspecified"
+ * language; if it does, then a query for that feature for any language will match.
+ *
+ * <p>A result specification entry having a language set may contain languages with country codes, such as
+ * zh-cn for example. A query for zh-cn would match, but a query for zh would not match,
+ * if this entry only had the zh-cn language specified.
+ *
+ * <p>But, a result specification entry having a language set containing just zh will match
+ * queries that specify zh-cn as the language, because a result-specification of zh is implied to
+ * mean the language zh regardless of the country.
+ *
* <p>
- * If you query the ResultSpecification with a language with a country code (e.g. en-US), results
- * for the base language (en) will be returned as well.
+ * Sometimes the methods to change the result specification replace the language(s), other times, the
+ * language(s) are merged with any existing specification already present in the result specification
+ * for the particular type or feature.
+ * <ul><li>Methods to "set" result types and/or features (or both) replace the current settings, for all languages.</li>
+ * <li>Methods to "add" 1 type or feature, with no language(s) specified
+ * replace the current language setting for that type or feature with x-unspecified,
+ * except for the following 2 methods</li>
+ * <li>Methods addResultType and addFeatureType, with languages specified, augment any existing
+ * languages that might already be specified for that type or feature.</li>
+ * </ul>
+ *
+ * <p>Prior to any querying using the containsType or containsFeature methods,
+ * the type system in use for this result specification may be specified by
+ * calling setTypeSystem(typeSystem). If it is available, the results of the containsType and
+ * containsFeature methods will be true for subtypes of the original types.
+ * The language specification in the ResultSpecification for a derived sub type
+ * is computed as the union of all of the langauges specified for its supertypes.
+ * Likewise, the The allAnnotatorFeatures flag of a subtype is the logical union
+ * of this property for all of its supertypes.
+ *
+ * <p>The computation to enable this behavior for subtypes is called "compiling" the
+ * result specification, and is done automatically, but only when
+ * needed, and when there is an available type system
+ * specified for this result specification object, using
+ * the setTypeSystem or compile methods. The result of this computation is "cached". If the result specification
+ * is subsequently updated in such a way as to make this computation invalid, the cache is
+ * invalidated, and another compile operation will be transparently done, when and if needed.
*
*/
public interface ResultSpecification extends XMLizable, Serializable, Cloneable {
/**
* Retrieves the Types and Features that the AnalysisEngine or Annotator is requested to produce
- * for the default language x-unspecified.
+ * for the default language x-unspecified (that is, regardless any language specification).
+ * <p>
+ * The set of types and features returned are just the ones that have been
+ * explicitly set or added to the ResultSpecification, and doesn't include
+ * any derived subtypes, even if this ResultSpecification has been compiled.
*
* @return an array of {@link TypeOrFeature} objects that define the result types and features for
* the language x-unspecified.
@@ -62,8 +114,12 @@
/**
* Retrieves the Types and Features that the AnalysisEngine or Annotator is requested to produce
- * for the specified language.
- *
+ * for the specified language. See the class comment for how languages are compared.
+ * <p>
+ * The set of types and features returned are just the ones that have been
+ * explicitly set or added to the ResultSpecification, and doesn't include
+ * any derived subtypes, even if this ResultSpecification has been compiled.
+ *
* @return an array of {@link TypeOrFeature} objects that define the result types and features for
* the specified language.
*/
@@ -71,7 +127,8 @@
/**
* Sets the Types and Features that the AnalysisEngine or Annotator is requested to produce for
- * the language x-unspecified.
+ * the language x-unspecified, and removes all other type or feature information, that may be
+ * previously present (e.g., for other languages)
*
* @param aTypesAndFeatures
* an array of {@link TypeOrFeature} objects that define the result types and features
@@ -81,7 +138,8 @@
/**
* Sets the Types and Features that the AnalysisEngine or Annotator is requested to produce for
- * the specified languages.
+ * the specified languages, and removes all other type or feature information, that may be
+ * previously present (e.g., for other languages).
*
* @param aTypesAndFeatures
* an array of {@link TypeOrFeature} objects that define the result types and features
@@ -94,8 +152,9 @@
/**
* Adds a Result Type or Feature to this <code>ResultSpecification</code> for the language
- * x-unspecified. If the current ToF is already contained in the result spec, the language
- * specification for this ToF will be replaced with x-unspecified.
+ * x-unspecified. If there is already a same-named TypeOrFeature object contained in the
+ * result spec, its language specification for this ToF will be replaced with x-unspecified,
+ * and its allAnnotatorFeatures flag will be replaced with the parameter's.
*
* @param aTypeOrFeature
* the Type or Feature to add for the language x-unspecified
@@ -104,8 +163,11 @@
/**
* Adds a Result Type or Feature to this <code>ResultSpecification</code> for the specified
- * languages. If the current ToF is already contained in the result spec, the language
- * specification for this ToF will be replaced with the specified languages.
+ * languages. If there is already a same-named TypeOrFeature object contained in the
+ * result spec, the language
+ * specification for this ToF will be replaced with the specified languages,
+ * and its allAnnotatorFeatures flag will be replaced with the parameter's. If null is passed in for
+ * the aLanguageIDs, this is treated as if one language, x-unspecified, was given.
*
* @param aTypeOrFeature
* the Type or Feature to add for the specified languages
@@ -119,7 +181,8 @@
* Adds an Type to this <code>ResultSpecification</code> for the language x-unspecified.
*
* If the current Type is already contained in the result spec, the language specification for
- * this Type will be replaced with x-unspecified.
+ * this Type will be replaced with x-unspecified,
+ * and its allAnnotatorFeatures flag will be replaced with the parameter's.
*
* @param aTypeName
* the name of the Type to add for the language x-unspecified
@@ -131,8 +194,11 @@
/**
* Adds an Type to this <code>ResultSpecification</code> for the specified languages.
*
- * If the given Type is already contained in the result spec, the languages specificied will be
+ * If the given Type is already contained in the result spec, the languages specified will be
* added to those already associated with the Type in this ResultSpec.
+ * The given type's allAnnotatorFeatures is logically "or"ed with any existing value.
+ * If null is passed in for
+ * the aLanguageIDs, this is treated as if one language, x-unspecified, was given.
*
* @param aTypeName
* the name of the Type to add for the specified languages
@@ -146,8 +212,8 @@
/**
* Adds a Feature to this <code>ResultSpecification</code> for the language x-unspecified.
*
- * If the given Type is already contained in the result spec, the languages specificied will be
- * added to those already associated with the Type in this ResultSpec.
+ * If the given Type is already contained in the result spec, the languages associated with that type will be
+ * replaced by x-unspecified.
*
* @param aFullFeatureName
* the fully-qualified name of the Feature to add for the language x-unspecified
@@ -158,7 +224,9 @@
* Adds a Feature to this <code>ResultSpecification</code> for the specified languages.
*
* If the current Feature is already contained in the result spec, the language specification for
- * this Feature will be replaced with the specified languages.
+ * this Feature will be augmented (added to) with the specified languages.
+ * If null is passed in for
+ * the aLanguageIDs, this is treated as if one language, x-unspecified, was given.
*
* @param aFullFeatureName
* the fully-qualified name of the Feature to add for the specified languages
@@ -169,23 +237,27 @@
public void addResultFeature(String aFullFeatureName, String[] aLanguageIDs);
/**
- * Compiles this <code>ResultSpecification</code> using a specific {@link TypeSystem}. This
- * allows the {@link #containsType(String)} and {@link #containsFeature(String)} methods to
- * properly consider the inheritance of types and to expand features when this
- * <code>ResultSpecification</code> contains Types with <code>allAnnotatorFeatures</code> set
- * to true.
- * <p>
- * This method is called automatically by the Analysis Engine. Annotators and Applications do not
- * need to call it.
- *
+ * Compiles this <code>ResultSpecification</code> using a specific {@link TypeSystem}. The
+ * result is cached and used by the {@link #containsType(String)} and {@link #containsFeature(String)} methods to
+ * properly consider the inheritance of types and to restrict allAnnotatorFeatures
+ * to just those features defined in the type system when this
+ * <code>ResultSpecification</code> contains Types with <code>allAnnotatorFeatures</code> set
+ * to true.
+ * <p>
+ * This method is called automatically internally when needed. Framework code, Annotators and Applications do not
+ * need to call it.
+ *
* @param aTypeSystem
* the Type System used to determine which features belong to each Type
+ * @deprecated as of 2.3.0 Now called automatically internally when needed
*/
public void compile(TypeSystem aTypeSystem);
/**
* Determines whether this <code>ResultSpecification</code> contains the specified Type for the
- * language x-unspecified.
+ * language x-unspecified. If a type system is available to the result specification,
+ * a type will be considered to be contained in the result spec, also, if it
+ * is a subtype of the types originally specified to be in the result specification.
*
* @param aTypeName
* the name of the type
@@ -197,12 +269,15 @@
/**
* Determines whether this <code>ResultSpecification</code> contains the specified Type for the
- * specified language
+ * specified language. A type is considered to be contained in the result spec, also, if it
+ * is a subtype of the types originally specified to be in the result specification for this language.
*
* @param aTypeName
* the name of the type
* @param aLanguage
- * the language to search for
+ * the language to search for. A null value or the value x-unspecified for this argument disables
+ * the language test - any language will match. The language is matched after excluding any
+ * country code, if present.
*
* @return true if and only if this <code>ResultSpecification</code> contains the type with name
* <code>aTypeName</code> for the specified language.
@@ -211,7 +286,11 @@
/**
* Determines whether this <code>ResultSpecification</code> contains the specified Feature for
- * the language x-unspecified.
+ * the language x-unspecified. Feature names are fully qualified, consisting of the
+ * type name plus the feature-of-that-type name. A feature ttt:fff is contained in the result spec if
+ * that fff is specified for type ttt or any supertype of ttt in the result spec.
+ * A feature can be specified in the result spec explicitly or by specifying a type or supertype
+ * of the feature's type having the allAnnotatorFeatures flag set.
*
* @param aFullFeatureName
* the fully-qualified name of the feature, in the form MyTypeName:MyFeatureName.
@@ -223,12 +302,18 @@
/**
* Determines whether this <code>ResultSpecification</code> contains the specified Feature for
- * the specified language.
+ * the specified language. Feature names are fully qualified, consisting of the
+ * type name plus the feature-of-that-type name. A feature ttt:fff is contained in the result spec if
+ * that fff is specified for type ttt or any supertype of ttt in the result spec.
+ * A feature can be specified in the result spec explicitly or by specifying a type or supertype
+ * of the feature's type having the allAnnotatorFeatures flag set.
*
* @param aFullFeatureName
* the fully-qualified name of the feature, in the form MyTypeName:MyFeatureName.
* @param aLanguage
- * the language to search for
+ * the language to search for. A null value or the value x-unspecified for this argument disables
+ * the language test - any language will match. A value with a country code
+ * in addition to a language will match a result-spec without the country code.
*
* @return true if and only if this <code>ResultSpecification</code> contains the feature with
* name <code>aFullFeatureName</code> for the specified language.
@@ -237,7 +322,12 @@
/**
* Adds the output types and features from the specified capabilities to this
- * <code>ResultSpecification</code>.
+ * <code>ResultSpecification</code>.
+ * <p>
+ * If a Type being added is already contained in the ResultSpecification, the languages
+ * from the Capabilities entry for this type will be
+ * added to those already associated with the Type in this ResultSpec.
+ * The given capability instance's allAnnotatorFeatures is logically "or"ed with any existing value.
*
* @param aCapabilities
* capabilities to add
@@ -246,18 +336,23 @@
/**
* Adds either outputs or inputs from the specified capabilities to this
- * <code>ResultSpecification</code>.
- *
+ * <code>ResultSpecification</code>.
+ * <p>
+ * If a Type being added is already contained in the ResultSpecification, the languages
+ * from the Capabilities entry for this type will be
+ * added to those already associated with the Type in this ResultSpec.
+ * The given capability instance's allAnnotatorFeatures is logically "or"ed with any existing value.
+
* @param aCapabilities
* capabilities to add
* @param aOutputs
* true to add the output types/features to this ResultSpecification, false to add the
- * input types/features to this ResultSpecification.
+ * input types/features to this ResultSpecification.
*/
public void addCapabilities(Capability[] aCapabilities, boolean aOutputs);
/**
- * removes the specified TypeOrFeature from this <code>ResultSpecification</code>.
+ * removes the specified TypeOrFeature from this <code>ResultSpecification</code>.
*
* @param aTypeOrFeature
* the Type or Feature to remove
@@ -265,10 +360,22 @@
public void removeTypeOrFeature(TypeOrFeature aTypeOrFeature);
/**
- * create a copy of the current object
+ * create a copy of the current object.
*
* @return Object returns a copy of the current object
*/
public Object clone();
+
+ /**
+ * set the type system associated with this result specification. It is used
+ * to augment any types with their subtypes
+ * @param ts the CAS Type System
+ */
+ public void setTypeSystem(TypeSystem ts);
+
+ /**
+ * get the type system associated with this result specification.
+ */
+ public TypeSystem getTypeSystem();
}
Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineImplBase.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineImplBase.java?rev=615608&r1=615607&r2=615608&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineImplBase.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineImplBase.java Sun Jan 27 06:21:40 2008
@@ -26,6 +26,7 @@
import org.apache.uima.UIMAFramework;
import org.apache.uima.UimaContextAdmin;
+import org.apache.uima.analysis_engine.AnalysisEngine;
import org.apache.uima.analysis_engine.AnalysisEngineManagement;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.analysis_engine.CasIterator;
@@ -294,6 +295,13 @@
*/
public ResultSpecification createResultSpecification() {
return new ResultSpecification_impl();
+ }
+
+ /**
+ * @see AnalysisEngine#createResultSpecification(TypeSystem)
+ */
+ public ResultSpecification createResultSpecification(TypeSystem aTypeSystem) {
+ return new ResultSpecification_impl(aTypeSystem);
}
/**
Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/PrimitiveAnalysisEngine_impl.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/PrimitiveAnalysisEngine_impl.java?rev=615608&r1=615607&r2=615608&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/PrimitiveAnalysisEngine_impl.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/PrimitiveAnalysisEngine_impl.java Sun Jan 27 06:21:40 2008
@@ -19,7 +19,9 @@
package org.apache.uima.analysis_engine.impl;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import org.apache.uima.Constants;
@@ -62,6 +64,10 @@
* current class
*/
private static final Class CLASS_NAME = PrimitiveAnalysisEngine_impl.class;
+
+ private static final String [] X_UNSPECIFIED = new String [] {"x-unspecified"};
+
+ private static final String [] EMPTY_STRING_ARRAY = new String [0];
private ResultSpecification mCurrentResultSpecification;
@@ -349,18 +355,16 @@
AbstractCas casToPass = getCasManager().getCasInterface(view, requiredInterface);
// check if there was a change in the ResultSpecification or in
- // the TypeSystem. If so, recompile the ResultSpecification and
+ // the TypeSystem. If so, set the changed type system into the ResultSpecification and
// inform the component
if (mResultSpecChanged || mLastTypeSystem != view.getTypeSystem()) {
mLastTypeSystem = view.getTypeSystem();
- mCurrentResultSpecification.compile(mLastTypeSystem);
+ mCurrentResultSpecification.setTypeSystem(mLastTypeSystem);
// the actual ResultSpec we send to the component is formed by
// looking at this primitive AE's declared output types and eliminiating
// any that are not in mCurrentResultSpecification.
ResultSpecification analysisComponentResultSpec = computeAnalysisComponentResultSpec(
mCurrentResultSpecification, getAnalysisEngineMetaData().getCapabilities());
- // compile result spec - necessary to get type subsumption to work properly
- analysisComponentResultSpec.compile(mLastTypeSystem);
mAnalysisComponent.setResultSpecification(analysisComponentResultSpec);
mResultSpecChanged = false;
}
@@ -415,29 +419,60 @@
*/
protected ResultSpecification computeAnalysisComponentResultSpec(
ResultSpecification inputResultSpec, Capability[] capabilities) {
- ResultSpecification newResultSpec = new ResultSpecification_impl();
- for (int i = 0; i < capabilities.length; i++) {
- Capability cap = capabilities[i];
- TypeOrFeature[] outputs = cap.getOutputs();
- String[] languages = cap.getLanguagesSupported();
- if (languages.length == 0) {
- languages = new String[] { "x-unspecified" };
+ ResultSpecification newResultSpec = new ResultSpecification_impl(inputResultSpec.getTypeSystem());
+ List<String> languagesToAdd = new ArrayList<String>();
+
+ for (Capability capability : capabilities) {
+ TypeOrFeature[] outputs = capability.getOutputs();
+ String[] languages = capability.getLanguagesSupported();
+ if (null == languages || languages.length == 0) {
+ languages = X_UNSPECIFIED;
}
- for (int j = 0; j < outputs.length; j++) {
- for (int k = 0; k < languages.length; k++) {
- if (outputs[j].isType()
- && inputResultSpec.containsType(outputs[j].getName(), languages[k])) {
- newResultSpec.addResultType(outputs[j].getName(), outputs[j].isAllAnnotatorFeatures(),
- new String[] { languages[k] });
- } else if (!outputs[j].isType()
- && inputResultSpec.containsFeature(outputs[j].getName(), languages[k])) {
- newResultSpec.addResultFeature(outputs[j].getName(), new String[] { languages[k] });
+
+ for (TypeOrFeature tof : outputs) {
+ String tofName = tof.getName();
+ languagesToAdd.clear();
+ for (String language : languages) {
+ if ((tof.isType() && inputResultSpec.containsType(tofName, language)) ||
+ (!tof.isType() && inputResultSpec.containsFeature(tofName, language))) {
+ languagesToAdd.add(language);
}
}
+ if (0 < languagesToAdd.size()) {
+ if (tof.isType()) {
+ newResultSpec.addResultType(tofName, tof.isAllAnnotatorFeatures(),
+ languagesToAdd.toArray(EMPTY_STRING_ARRAY));
+ } else {
+ newResultSpec.addResultFeature(tofName, languagesToAdd.toArray(EMPTY_STRING_ARRAY));
+ }
+ }
}
}
- return newResultSpec;
+ return newResultSpec;
}
+
+// for (int i = 0; i < capabilities.length; i++) {
+// Capability cap = capabilities[i];
+// TypeOrFeature[] outputs = cap.getOutputs();
+// String[] languages = cap.getLanguagesSupported();
+// if (languages.length == 0) {
+// languages = X_UNSPECIFIED;
+// }
+// for (int j = 0; j < outputs.length; j++) {
+// for (int k = 0; k < languages.length; k++) {
+// if (outputs[j].isType()
+// && inputResultSpec.containsType(outputs[j].getName(), languages[k])) {
+// newResultSpec.addResultType(outputs[j].getName(), outputs[j].isAllAnnotatorFeatures(),
+// new String[] { languages[k] });
+// } else if (!outputs[j].isType()
+// && inputResultSpec.containsFeature(outputs[j].getName(), languages[k])) {
+// newResultSpec.addResultFeature(outputs[j].getName(), new String[] { languages[k] });
+// }
+// }
+// }
+// }
+// return newResultSpec;
+// }
/**
* Calls the Analysis Component's next() method.
Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/ResultSpecification_impl.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/ResultSpecification_impl.java?rev=615608&r1=615607&r2=615608&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/ResultSpecification_impl.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/ResultSpecification_impl.java Sun Jan 27 06:21:40 2008
@@ -19,19 +19,17 @@
package org.apache.uima.analysis_engine.impl;
+import java.util.ArrayList;
+import java.util.BitSet;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.Vector;
import org.apache.uima.analysis_engine.ResultSpecification;
import org.apache.uima.analysis_engine.TypeOrFeature;
-import org.apache.uima.cas.Feature;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
+import org.apache.uima.cas.text.Language;
import org.apache.uima.resource.metadata.Capability;
import org.apache.uima.resource.metadata.impl.MetaDataObject_impl;
import org.apache.uima.resource.metadata.impl.PropertyXmlInfo;
@@ -40,137 +38,427 @@
/**
* Reference implementaion of {@link ResultSpecification}.
*
+ * Notes on the implementation
*
+ * There are two ways this data is used: with and without "compiling"
+ * Compiling means: adding subtypes of types and adding all features of a type
+ * Uncompiled form is called ORIGINAL.
+ *
+ * Compiling is deferred - until the first reference to containsType or Feature.
+ *
+ * Many instances of this class are made, sometimes via cloning.
+ *
+ * Sometimes types and features are deleted - the intent is to do this operation on the
+ * uncompiled form, and then "recompile" it.
+ *
+ * Types and Features are kept on a per-language basis. Language can include a special value,
+ * x-unspecified, which "matches" any other language.
+ *
+ * Language specifications are simplified to eliminate the country part. All refs to
+ * test if a type or feature is in the result spec for a language uses the simplified language.
+ *
+ * Set operations are done to combine, for a particular type or feature, the languages for which it is valid.
+ * This is a Union operation
+ * Set operations are done to union the input types/features with the output types/features when computing the default
+ * result-spec for an aggregate.
+ * Set operations are done to intersect the result spec with the output capabilities of a component.
+ *
+ * Languages are represented as integers; there is a hash table from the string to the integer, and
+ * an array to go from integer to lang string.
+ *
+ * A result set of ORIGINALs consists of types/features with associated language sets.
*/
public final class ResultSpecification_impl extends MetaDataObject_impl implements
ResultSpecification {
+// private enum AddMode {ORIGINAL, COMPILED};
+// private AddMode addMode = AddMode.ORIGINAL;
+//
private static final long serialVersionUID = 8516517600467270594L;
- static final String UNSPECIFIED_LANGUAGE = "x-unspecified";
+ static final int UNSPECIFIED_LANGUAGE_INDEX = 0;
/**
* main language separator e.g 'en' and 'en-US'
*/
private static final char LANGUAGE_SEPARATOR = '-';
-
+
/**
- * Map from TypeOrFeature objects to HashSets that include the language codes (Strings) for which
- * that type or feature should be produced.
+ *
+ */
+ private boolean needsCompilation = true;
+
+ private final Map<String, Integer> lang2int;
+
+ private int getLanguageWithoutCountryIndex(String language) {
+ return getLanguageIndex(getLanguageWithoutCountry(language));
+ }
+
+ private int getLanguageIndex(String language) {
+ Integer r = lang2int.get(language);
+ if (null == r) {
+ int i = lang2int.size();
+ lang2int.put(language, Integer.valueOf(i));
+ return i;
+ }
+ return r.intValue();
+ }
+
+ private class ToF_Languages {
+ public TypeOrFeature tof;
+ public BitSet languages;
+
+ ToF_Languages(TypeOrFeature aTof, String[] aLanguages) {
+ tof = aTof;
+ languages = new BitSet();
+ for (String lang : aLanguages) {
+ languages.set(getLanguageIndex(lang));
+ }
+ }
+
+ ToF_Languages(TypeOrFeature aTof, BitSet aLanguages) {
+ tof = aTof;
+ languages = aLanguages;
+ }
+
+ public Object clone() {
+ return new ToF_Languages((TypeOrFeature) tof.clone(), (BitSet)languages.clone());
+ }
+ }
+
+ /**
+ * hash map used to map fully qualified type and feature names to associated
+ * ToF_Languages instances. This used for ORIGINAL types and features.
+ *
+ * Another hash map is used for compiled types and features - these include
+ * the subtypes of the ORIGINAL types. We keep the originals because the
+ * operations of adding and removing types and features are done with respect
+ * to the originals, only, and then the other map for compiled types is recomputed.
+ *
+ * A case in particular: we need to be able to distinguish which types were
+ * originally marked allAnnotatorFeatures, versus those types which were
+ * added because they were subtypes. The corner case happens when a type is both
+ * an original and is also an added-via-subtype, where the allAnnotatorFeatures
+ * flag of the original is not set but the subtype version is set.
+ *
*/
- private Map mTypesAndFeatures = new HashMap();
+ private final Map<String, ToF_Languages> name2tof_langs;
/**
- * Map from String type or feature names to HashSets that include the language codes (Strings) for
- * which that type or feature should be produced. This is populated by the compile() method, and
- * includes subtypes as well as the individual feature names for types that have
- * allAnnotatorFeatures=true.
+ * hash map used to map fully qualified type and feature names to associated
+ * ToF_Languages instances. This used for COMPILED types and features.
*/
- private Map mCompiledNameToLanguageMap = new HashMap();
+ private final Map<String, ToF_Languages> withSubtypesName2tof_langs;
+
+// /**
+// * Map from TypeOrFeature objects to HashSets that include the language codes (Strings) for which
+// * that type or feature should be produced.
+// */
+// private Map<TypeOrFeature, Set<String>> mTypesAndFeatures = new HashMap<TypeOrFeature, Set<String>>();
+//
+// /**
+// * Map from String type or feature names to HashSets that include the language codes (Strings) for
+// * which that type or feature should be produced. This is populated by the compile() method, and
+// * includes subtypes as well as the individual feature names for types that have
+// * allAnnotatorFeatures=true.
+// */
+// private final Map<String, Set<String>> mCompiledNameToLanguageMap =
+// new HashMap<String, Set<String>>();
+
/**
* Default language set to use if nothing else is specified
*/
- private HashSet mDefaultLanguage = new HashSet();
+ private static final String[] mDefaultLanguage = new String[] {Language.UNSPECIFIED_LANGUAGE};
/**
- * constructor init the default languge set with the language x-unspecified
+ * The type system used to compute the subtypes and allAnnotatorFeatures of types
+ */
+ private TypeSystem mTypeSystem;
+
+ /**
+ * constructor: init the default languge set with the language x-unspecified
*/
public ResultSpecification_impl() {
- mDefaultLanguage.add(UNSPECIFIED_LANGUAGE);
+ name2tof_langs = new HashMap<String, ToF_Languages>();
+ withSubtypesName2tof_langs = new HashMap<String, ToF_Languages>();
+ lang2int = new HashMap<String, Integer>();
+ lang2int.put(Language.UNSPECIFIED_LANGUAGE, 0);
}
/**
+ * Constructor specifying the type system
+ * this should always be used in preference to the 0 argument version
+ * if the type system is available. Otherwise, the type system *must*
+ * be set via a method call prior to querying the result spec, with the
+ * one exception of the method getResultTypesAndFeaturesWithoutCompiling
+ * @param aTypeSystem
+ */
+ public ResultSpecification_impl(TypeSystem aTypeSystem) {
+ this();
+ mTypeSystem = aTypeSystem;
+ }
+
+ private ResultSpecification_impl(ResultSpecification_impl original) {
+ name2tof_langs = new HashMap<String, ToF_Languages>(original.name2tof_langs.size());
+ withSubtypesName2tof_langs = new HashMap<String, ToF_Languages>(original.withSubtypesName2tof_langs.size());
+ lang2int = original.lang2int; // shared hash map - to save space.
+ for (Map.Entry<String, ToF_Languages> entry : original.name2tof_langs.entrySet()) {
+ ToF_Languages tof_langs = entry.getValue();
+
+ // note: TypeOrFeature instances are not cloned, but shared
+ // If they are modified, things may break
+ name2tof_langs.put(entry.getKey(),
+ new ToF_Languages(tof_langs.tof, (BitSet)(tof_langs.languages.clone())));
+ }
+ mTypeSystem = original.mTypeSystem;
+ }
+
+ private void compileIfNeeded() {
+ if (needsCompilation) {
+ compile();
+ }
+ }
+
+ private String getLanguageWithoutCountry(String language) {
+ String baseLanguage = language;
+ int index = language.indexOf(LANGUAGE_SEPARATOR);
+ if (index > -1) {
+ baseLanguage = language.substring(0, index);
+ }
+ return baseLanguage;
+ }
+
+ /**
* @see org.apache.uima.analysis_engine.ResultSpecification#getResultTypesAndFeatures()
*/
public TypeOrFeature[] getResultTypesAndFeatures() {
- TypeOrFeature[] arr = new TypeOrFeature[mTypesAndFeatures.size()];
- mTypesAndFeatures.keySet().toArray(arr);
+ TypeOrFeature[] arr = new TypeOrFeature[name2tof_langs.size()];
+ int i = 0;
+ for (ToF_Languages tof_langs : name2tof_langs.values()) {
+ arr[i++] = tof_langs.tof;
+ }
return arr;
}
+
+ private Map<String, ToF_Languages> availName2tof_langs() {
+ if (needsCompilation) {
+ return name2tof_langs;
+ }
+ return withSubtypesName2tof_langs;
+ }
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#getResultTypesAndFeatures(java.lang.String)
*/
public TypeOrFeature[] getResultTypesAndFeatures(String language) {
- // get language without country if applicable
- String baseLanguage = null;
- int index = language.indexOf(LANGUAGE_SEPARATOR);
- if (index > -1) {
- baseLanguage = language.substring(0, index);
- }
+
+ int languageIndex = getLanguageIndex(language);
+ int baseLanguageIndex = getLanguageWithoutCountryIndex(language);
// holds the found ToFs for the specified language
- Vector vec = new Vector();
+ List<TypeOrFeature> foundToF = new ArrayList<TypeOrFeature>();
- Iterator it = mTypesAndFeatures.keySet().iterator();
- while (it.hasNext()) {
- // get current key
- TypeOrFeature tof = (TypeOrFeature) it.next();
- // get value for the current key
- Set values = (HashSet) mTypesAndFeatures.get(tof);
- if (values.contains(language) || values.contains(UNSPECIFIED_LANGUAGE)
- || values.contains(baseLanguage)) {
- // add tof to the TypeOfFeature array
- vec.add(tof);
+ for (Map.Entry<String, ToF_Languages> entry : name2tof_langs.entrySet()) {
+ if (languageMatches(entry.getValue(), languageIndex, baseLanguageIndex)) {
+ foundToF.add(entry.getValue().tof);
+ }
+ }
+ return foundToF.toArray(new TypeOrFeature[foundToF.size()]);
+ }
+
+ // private helper functions
+
+// private boolean sameLanguages(String [] s, BitSet b) {
+// if (s.length != b.cardinality()) {
+// return false;
+// }
+// for (String lang : s) {
+// if ( ! b.get(getLanguageIndex(lang))) {
+// return false;
+// }
+// }
+// return true;
+// }
+
+ /**
+ * change null languages to the unspecified language
+ * change a set of languages that includes the unspecified language to
+ * just the unspecified language.
+ * This is OK when storing things into a result spec, since
+ * the unspecified language will match any query.
+ * This doesn't apply for querying because the queries only
+ * specify one language, not a set
+ */
+ private String [] normalizeLanguages(String [] languages) {
+ if (null == languages) {
+ return mDefaultLanguage;
+ } else {
+ for (String lang : languages) {
+ if (lang.equals(Language.UNSPECIFIED_LANGUAGE)) {
+ return mDefaultLanguage;
+ }
+ }
+ }
+ // normalization is expensive - so do this once as part of parsing capabilities
+// int i = 0;
+// for (String language : languages) {
+// languages[i++] = normalizeLanguage(language);
+// }
+ return languages;
+ }
+
+// private String normalizeLanguage(String language) {
+// String result = language.toLowerCase(Locale.ENGLISH); // language specs are in English locale
+// return result.replace('_', '-');
+// }
+
+ private void setNeedsCompilation() {
+ needsCompilation = true;
+ if (0 != withSubtypesName2tof_langs.size()) {
+ withSubtypesName2tof_langs.clear();
+ }
+ }
+
+ private void addTypeOrFeatureInternal(TypeOrFeature tof, String[] languages) {
+ languages = normalizeLanguages(languages);
+
+ ToF_Languages tof_langs = name2tof_langs.get(tof.getName());
+ if (null == tof_langs) {
+ name2tof_langs.put(tof.getName(), new ToF_Languages(tof, languages));
+ setNeedsCompilation();
+ return;
+ }
+ tof_langs.tof.setAllAnnotatorFeatures(tof.isAllAnnotatorFeatures());
+ BitSet langBitSet = tof_langs.languages;
+ langBitSet.clear();
+ for (String lang : languages) {
+ langBitSet.set(getLanguageIndex(lang));
+ }
+ setNeedsCompilation();
+ }
+
+ private TypeOrFeature createTypeOrFeature(String name, boolean isType, boolean aAllAnnotatorFeatures) {
+ TypeOrFeature r = new TypeOrFeature_impl();
+ r.setType(isType);
+ r.setName(name);
+ if (isType) {
+ r.setAllAnnotatorFeatures(aAllAnnotatorFeatures);
+ }
+ return r;
+ }
+
+ private void addResultTypeOrFeatureAddLanguage(String name, boolean isType, boolean allAnnotatorFeatures, String[] languages) {
+
+ ToF_Languages tof_langs = name2tof_langs.get(name);
+
+ if (null == tof_langs) {
+ addTypeOrFeatureInternal(createTypeOrFeature(name, isType, allAnnotatorFeatures), languages);
+ setNeedsCompilation();
+ return;
+ }
+
+ // tof_langs entry for this name exists, so update it
+ addResultTypeOrFeatureAddLanguageCommon(tof_langs, allAnnotatorFeatures, languages);
+ }
+
+ private void addResultTypeOrFeatureAddLanguage(TypeOrFeature tof, String[] languages) {
+
+ ToF_Languages tof_langs = name2tof_langs.get(tof.getName());
+
+ if (null == tof_langs) {
+ addTypeOrFeatureInternal(tof, languages);
+ setNeedsCompilation();
+ return;
+ }
+
+ addResultTypeOrFeatureAddLanguageCommon(tof_langs, tof.isAllAnnotatorFeatures(), languages);
+ }
+
+ private void addResultTypeOrFeatureAddLanguageCommon(
+ ToF_Languages tof_langs, boolean allAnnotatorFeatures, String [] languages) {
+
+ // tof_langs entry for this name exists, so update it
+ if (allAnnotatorFeatures) {
+ if (!tof_langs.tof.isAllAnnotatorFeatures()) {
+ tof_langs.tof.setAllAnnotatorFeatures(true);
+ setNeedsCompilation();
+ }
+ }
+
+ // update the languages by adding the new languages passed in
+ languages = normalizeLanguages(languages);
+ BitSet langBitSet = tof_langs.languages;
+
+ // "==" ok here due to normalizeLanguages call above
+ if (languages == mDefaultLanguage) {
+ if ( ! langBitSet.get(UNSPECIFIED_LANGUAGE_INDEX)) {
+ langBitSet.clear();
+ langBitSet.set(UNSPECIFIED_LANGUAGE_INDEX);
+ setNeedsCompilation();
+ }
+ return;
+ }
+
+ // languages set already exists; add new ones to existing set
+ for (String lang : languages) {
+ langBitSet.set(getLanguageIndex(lang));
+ }
+ setNeedsCompilation();
+ }
+
+ /**
+ * version used by compile to add subtypes
+ * @param aTypeName
+ * @param aAllAnnotatorFeatures
+ * @param languages
+ */
+ private void addResultType(String name, boolean allAnnotatorFeatures, BitSet languages) {
+ ToF_Languages tof_langs = withSubtypesName2tof_langs.get(name);
+
+ if (null == tof_langs) {
+ withSubtypesName2tof_langs.put(
+ name,
+ new ToF_Languages(createTypeOrFeature(name, true, allAnnotatorFeatures), (BitSet)languages.clone()));
+ return;
+ }
+
+ // tof_langs entry for this name exists, so update it
+ if (allAnnotatorFeatures) {
+ if (!tof_langs.tof.isAllAnnotatorFeatures()) {
+ tof_langs.tof.setAllAnnotatorFeatures(true);
}
}
- // create array for return
- TypeOrFeature[] arr = new TypeOrFeature[vec.size()];
-
- // convert vector to TypeOrFeature[]
- vec.toArray(arr);
-
- return arr;
+ // update the languages by adding the new languages passed in
+ tof_langs.languages.or(languages);
}
+
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#setResultTypesAndFeatures(org.apache.uima.analysis_engine.TypeOrFeature[])
*/
public void setResultTypesAndFeatures(TypeOrFeature[] aTypesAndFeatures) {
- mTypesAndFeatures.clear();
- for (int i = 0; i < aTypesAndFeatures.length; i++) {
- mTypesAndFeatures.put(aTypesAndFeatures[i], mDefaultLanguage);
- }
- // revert to uncompiled state
- mCompiledNameToLanguageMap.clear();
+ setResultTypesAndFeatures(aTypesAndFeatures, mDefaultLanguage);
}
-
+
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#setResultTypesAndFeatures(org.apache.uima.analysis_engine.TypeOrFeature[],
* java.lang.String[])
*/
public void setResultTypesAndFeatures(TypeOrFeature[] aTypesAndFeatures, String[] aLanguageIDs) {
- if (aLanguageIDs != null) {
- // create HashSet for the aLanguageIDs with the initial capacity of the aLanguageIDs size
- HashSet languagesSupported = new HashSet(aLanguageIDs.length);
- // add all supported languages to at HashSet
- for (int x = 0; x < aLanguageIDs.length; x++) {
- // add current language to the HashSet
- languagesSupported.add(aLanguageIDs[x]);
- }
-
- mTypesAndFeatures.clear();
- for (int i = 0; i < aTypesAndFeatures.length; i++) {
- mTypesAndFeatures.put(aTypesAndFeatures[i], languagesSupported);
- }
- // revert to uncompiled state
- mCompiledNameToLanguageMap.clear();
- } else {
- // if aLangugeIDs is null set ToFs for the default language
- setResultTypesAndFeatures(aTypesAndFeatures);
- }
-
+ name2tof_langs.clear();
+ for (TypeOrFeature tof : aTypesAndFeatures) {
+ name2tof_langs.put(tof.getName(), new ToF_Languages(tof, normalizeLanguages(aLanguageIDs)));
+ }
+ setNeedsCompilation();
}
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#addResultTypeOrFeature(org.apache.uima.analysis_engine.TypeOrFeature)
*/
public void addResultTypeOrFeature(TypeOrFeature aTypeOrFeature) {
- mTypesAndFeatures.put(aTypeOrFeature, mDefaultLanguage);
- // revert to uncompiled state
- mCompiledNameToLanguageMap.clear();
+ addTypeOrFeatureInternal(aTypeOrFeature, mDefaultLanguage);
}
/**
@@ -178,80 +466,30 @@
* java.lang.String[])
*/
public void addResultTypeOrFeature(TypeOrFeature aTypeOrFeature, String[] aLanguageIDs) {
- if (aLanguageIDs != null) {
- // create HashSet for the aLanguageIDs with the initial capacity of the aLanguageIDs size
- HashSet languagesSupported = new HashSet(aLanguageIDs.length);
- // add all supported languages to at HashSet
- for (int x = 0; x < aLanguageIDs.length; x++) {
- // add current language to the HashSet
- languagesSupported.add(aLanguageIDs[x]);
- }
-
- mTypesAndFeatures.put(aTypeOrFeature, languagesSupported);
- // revert to uncompiled state
- mCompiledNameToLanguageMap.clear();
- } else {
- // if aLangugeIDs is null add ToF with the default language
- addResultTypeOrFeature(aTypeOrFeature);
- }
+ addTypeOrFeatureInternal(aTypeOrFeature, aLanguageIDs);
}
-
+
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#addResultType(java.lang.String,
* boolean)
*/
public void addResultType(String aTypeName, boolean aAllAnnotatorFeatures) {
- TypeOrFeature t = new TypeOrFeature_impl();
- t.setType(true);
- t.setName(aTypeName);
- t.setAllAnnotatorFeatures(aAllAnnotatorFeatures);
- mTypesAndFeatures.put(t, mDefaultLanguage);
- // revert to uncompiled state
- mCompiledNameToLanguageMap.clear();
+ addTypeOrFeatureInternal(createTypeOrFeature(aTypeName, true, aAllAnnotatorFeatures), mDefaultLanguage);
}
-
+
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#addResultType(java.lang.String,
* boolean, java.lang.String[])
*/
public void addResultType(String aTypeName, boolean aAllAnnotatorFeatures, String[] aLanguageIDs) {
- if (aLanguageIDs != null) {
- // create HashSet for the aLanguageIDs with the initial capacity of the aLanguageIDs size
- HashSet languagesSupported = new HashSet(aLanguageIDs.length);
- // add all supported languages to at HashSet
- for (int x = 0; x < aLanguageIDs.length; x++) {
- // add current language to the HashSet
- languagesSupported.add(aLanguageIDs[x]);
- }
-
- TypeOrFeature t = new TypeOrFeature_impl();
- t.setType(true);
- t.setName(aTypeName);
- t.setAllAnnotatorFeatures(aAllAnnotatorFeatures);
- HashSet existingLanguages = (HashSet) mTypesAndFeatures.get(t);
- if (existingLanguages != null) {
- existingLanguages.addAll(languagesSupported);
- } else {
- mTypesAndFeatures.put(t, languagesSupported);
- }
- // revert to uncompiled state
- mCompiledNameToLanguageMap.clear();
- } else {
- // if aLangugeIDs is null add type with the default language
- addResultType(aTypeName, aAllAnnotatorFeatures);
- }
+ addResultTypeOrFeatureAddLanguage(aTypeName, true, aAllAnnotatorFeatures, aLanguageIDs);
}
-
+
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#addResultFeature(java.lang.String)
*/
public void addResultFeature(String aFullFeatureName) {
- TypeOrFeature f = new TypeOrFeature_impl();
- f.setType(false);
- f.setName(aFullFeatureName);
- mTypesAndFeatures.put(f, mDefaultLanguage);
- // revert to uncompiled state
- mCompiledNameToLanguageMap.clear();
+ addTypeOrFeatureInternal(createTypeOrFeature(aFullFeatureName, false, false), mDefaultLanguage);
}
/**
@@ -259,76 +497,110 @@
* java.lang.String[])
*/
public void addResultFeature(String aFullFeatureName, String[] aLanguageIDs) {
- if (aLanguageIDs != null) {
- // create HashSet for the aLanguageIDs with the initial capacity of the aLanguageIDs size
- HashSet languagesSupported = new HashSet(aLanguageIDs.length);
- // add all supported languages to at HashSet
- for (int x = 0; x < aLanguageIDs.length; x++) {
- // add current language to the HashSet
- languagesSupported.add(aLanguageIDs[x]);
- }
-
- TypeOrFeature f = new TypeOrFeature_impl();
- f.setType(false);
- f.setName(aFullFeatureName);
- HashSet existingLanguages = (HashSet) mTypesAndFeatures.get(f);
- if (existingLanguages != null) {
- existingLanguages.addAll(languagesSupported);
- } else {
- mTypesAndFeatures.put(f, languagesSupported);
- }
- // revert to uncompiled state
- mCompiledNameToLanguageMap.clear();
- } else {
- // if aLangugeIDs is null add type with the default language
- addResultFeature(aFullFeatureName);
- }
+ addResultTypeOrFeatureAddLanguage(aFullFeatureName, false, false, aLanguageIDs);
}
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#compile(org.apache.uima.cas.TypeSystem)
*/
public void compile(TypeSystem aTypeSystem) {
- mCompiledNameToLanguageMap.clear();
- Iterator it = mTypesAndFeatures.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry elem = (Map.Entry) it.next();
- TypeOrFeature tof = (TypeOrFeature) elem.getKey();
- if (tof.isType()) {
- Type t = aTypeSystem.getType(tof.getName());
- if (t != null) {
- addTypeRecursive(t, aTypeSystem, (HashSet) elem.getValue(), tof.isAllAnnotatorFeatures());
+ setTypeSystem(aTypeSystem);
+ compileIfNeeded();
+ }
+
+// private static class TypeToCompile {
+// String name;
+// boolean allFeatures;
+// String[] languages;
+// TypeToCompile(String aName, boolean aAllFeatures, String[] aLanguages) {
+// name = aName;
+// allFeatures = aAllFeatures;
+// languages = aLanguages;
+// }
+// }
+
+ private void compile() {
+ if (null == mTypeSystem) {
+ return;
+ }
+
+ needsCompilation = false;
+ // get set of current type names
+ // for each name, get set of implied additional names (allAnnotatorFeatures and subtypes), recursively
+ // add with languages
+
+ // issue: can a result spec hold for language 1 types a b c, for language 2 types a b? yes
+ // can it hold for lang 1 type a(allfeats) and for lang 2 type a(not all feat)? no
+
+// Map<String, TypeToCompile> typesToCompile = new HashMap<String, TypeToCompile>(mNameToTofLang.size());
+// for (ToF_Languages tof_langs : mNameToTofLang.values()) {
+// TypeOrFeature tof = tof_langs.tof;
+// if (tof.isType()) {
+// String typeName = tof.getName();
+// typesToCompile.put(typeName, new TypeToCompile(typeName, tof.isAllAnnotatorFeatures(), tof_langs.languages));
+// }
+// }
+
+ for (ToF_Languages tof_langs : name2tof_langs.values()) {
+ TypeOrFeature tof = tof_langs.tof;
+ // copy type or feature to other map
+ withSubtypesName2tof_langs.put(tof.getName(), (ToF_Languages) tof_langs.clone());
+ if (tof.isType()) {
+ compileTypeRecursively(mTypeSystem.getType(tof.getName()), tof.isAllAnnotatorFeatures(), tof_langs.languages);
}
- } else // feature
- {
- mCompiledNameToLanguageMap.put(tof.getName(), elem.getValue());
- }
}
- // TODO: process the set of intersections
}
-
- /**
- * @param t
- */
- private void addTypeRecursive(Type type, TypeSystem typeSystem, HashSet languages,
- boolean allFeatures) {
- mCompiledNameToLanguageMap.put(type.getName(), languages);
- if (allFeatures) {
- List features = type.getFeatures();
- Iterator featIt = features.iterator();
- while (featIt.hasNext()) {
- Feature f = (Feature) featIt.next();
- mCompiledNameToLanguageMap.put(f.getName(), languages);
+
+// mCompiledNameToLanguageMap.clear();
+// for (Map.Entry<TypeOrFeature, Set<String>> elem : mTypesAndFeatures.entrySet()) {
+// TypeOrFeature tof = elem.getKey();
+// if (tof.isType()) {
+// Type t = aTypeSystem.getType(tof.getName());
+// if (t != null) {
+// addTypeRecursive(t, aTypeSystem, elem.getValue(), tof.isAllAnnotatorFeatures());
+// }
+// } else { // feature
+// mCompiledNameToLanguageMap.put(tof.getName(), elem.getValue());
+// }
+// }
+// // TODO: process the set of intersections
+// }
+
+ private void compileTypeRecursively(Type type, boolean allFeatures, BitSet languages) {
+
+ if (null != type) {
+// if (allFeatures) {
+// for (Feature f : (List<Feature>) type.getFeatures()) {
+// addResultFeature(f.getName(), languages); // this add "merges"
+// // langauges with existing
+// // ones
+// }
+// }
+
+ for (Type subType : (List<Type>) mTypeSystem.getDirectSubtypes(type)) {
+ String subTypeName = subType.getName();
+ addResultType(subTypeName, allFeatures, languages);
+ compileTypeRecursively(subType, allFeatures, languages);
}
}
- // recurse on subtypes
- List subtypes = typeSystem.getDirectSubtypes(type);
- Iterator typeIt = subtypes.iterator();
- while (typeIt.hasNext()) {
- Type subtype = (Type) typeIt.next();
- addTypeRecursive(subtype, typeSystem, languages, allFeatures);
- }
}
+
+// /**
+// * @param t
+// */
+// private void addTypeRecursive(Type type, TypeSystem typeSystem, Set<String> languages,
+// boolean allFeatures) {
+// mCompiledNameToLanguageMap.put(type.getName(), languages);
+// if (allFeatures) {
+// for (Feature f : (List<Feature>)type.getFeatures()) {
+// mCompiledNameToLanguageMap.put(f.getName(), languages);
+// }
+// }
+// // recurse on subtypes
+// for (Type subtype : (List<Type>)typeSystem.getDirectSubtypes(type)) {
+// addTypeRecursive(subtype, typeSystem, languages, allFeatures);
+// }
+// }
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#containsType(java.lang.String)
@@ -336,171 +608,123 @@
public boolean containsType(String aTypeName) {
if (aTypeName.indexOf(TypeSystem.FEATURE_SEPARATOR) != -1)
return false; // check against someone passing a feature name here
- // if compile() has been called can be done by a hash lookup
- if (!mCompiledNameToLanguageMap.isEmpty()) {
- return mCompiledNameToLanguageMap.containsKey(aTypeName);
- } else {
- // brute force search
- Iterator it = mTypesAndFeatures.keySet().iterator();
- while (it.hasNext()) {
- TypeOrFeature elem = (TypeOrFeature) it.next();
- if (elem.isType() && aTypeName.equals(elem.getName())) {
- return true;
- }
- }
- return false;
- }
+ compileIfNeeded();
+ return availName2tof_langs().containsKey(aTypeName);
}
+
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#containsType(java.lang.String,java.lang.String)
*/
public boolean containsType(String aTypeName, String language) {
- if (language == null) {
+ if (language == null || language.equals(Language.UNSPECIFIED_LANGUAGE)) {
return containsType(aTypeName);
}
if (aTypeName.indexOf(TypeSystem.FEATURE_SEPARATOR) != -1)
return false; // check against someone passing a feature name here
-
- // get language without country if applicable
- String baseLanguage = null;
- int index = language.indexOf(LANGUAGE_SEPARATOR);
- if (index > -1) {
- baseLanguage = language.substring(0, index);
- }
-
- boolean found = false;
-
- if (!mCompiledNameToLanguageMap.isEmpty()) {
- // if compile() has been called can be done by a hash lookup
- HashSet languages = (HashSet) mCompiledNameToLanguageMap.get(aTypeName);
- if (languages != null) {
- // check if tof is supported for the current language
- if (UNSPECIFIED_LANGUAGE.equals(language) || languages.contains(language)
- || languages.contains(UNSPECIFIED_LANGUAGE) || languages.contains(baseLanguage)) {
- // mark item found
- found = true;
- }
- }
- } else {
- // brute force search
- Iterator it = mTypesAndFeatures.keySet().iterator();
- while (it.hasNext()) {
- TypeOrFeature elem = (TypeOrFeature) it.next();
- if (elem.isType() && aTypeName.equals(elem.getName())) {
- HashSet languages = (HashSet) mTypesAndFeatures.get(elem);
- if (languages != null) {
- // check if tof is supported for the current language
- if (UNSPECIFIED_LANGUAGE.equals(language) || languages.contains(language)
- || languages.contains(UNSPECIFIED_LANGUAGE) || languages.contains(baseLanguage)) {
- // mark item found
- return true;
- }
- }
- }
- }
- }
-
- return found;
+
+ compileIfNeeded();
+ return languageMatches(availName2tof_langs().get(aTypeName), language);
}
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#containsFeature(java.lang.String)
*/
public boolean containsFeature(String aFullFeatureName) {
- if (aFullFeatureName.indexOf(TypeSystem.FEATURE_SEPARATOR) == -1)
+ int typeEndPosition = aFullFeatureName.indexOf(TypeSystem.FEATURE_SEPARATOR);
+ if (typeEndPosition == -1)
return false; // check against someone passing a type name here
- // if compile() has been called can be done by a hash lookup
- if (!mCompiledNameToLanguageMap.isEmpty()) {
- return mCompiledNameToLanguageMap.containsKey(aFullFeatureName);
- } else {
- // brute force search
- // (also need to consider Types with allAnnotatorFeatures = true)
- String typeName = "";
- int typeSeparatorIndex = aFullFeatureName.indexOf(':');
- if (typeSeparatorIndex > 0) {
- typeName = aFullFeatureName.substring(0, typeSeparatorIndex);
- }
-
- Iterator it = mTypesAndFeatures.keySet().iterator();
- while (it.hasNext()) {
- TypeOrFeature elem = (TypeOrFeature) it.next();
- if ((!elem.isType() && aFullFeatureName.equals(elem.getName()))
- || (elem.isType() && elem.isAllAnnotatorFeatures() && typeName.equals(elem
- .getName()))) {
- return true;
- }
+ compileIfNeeded();
+ if (availName2tof_langs().containsKey(aFullFeatureName)) {
+ return true;
+ }
+
+ // special code here to return true if the allAnnotatorFeatures flag is set for the type
+ String typeName = aFullFeatureName.substring(0, typeEndPosition);
+ ToF_Languages tof_langs = availName2tof_langs().get(typeName);
+ if (null != tof_langs && tof_langs.tof.isAllAnnotatorFeatures()) {
+ if (null != mTypeSystem) {
+ return null != mTypeSystem.getFeatureByFullName(aFullFeatureName); // verify feature is there
}
-
- return false;
+ return true;
}
+ return false;
}
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#containsFeature(java.lang.String,java.lang.String)
*/
public boolean containsFeature(String aFullFeatureName, String language) {
- if (language == null) {
+ if (language == null || language.equals(Language.UNSPECIFIED_LANGUAGE)) {
return containsFeature(aFullFeatureName);
}
- if (aFullFeatureName.indexOf(TypeSystem.FEATURE_SEPARATOR) == -1)
+ int typeEndPosition = aFullFeatureName.indexOf(TypeSystem.FEATURE_SEPARATOR);
+ if (typeEndPosition == -1)
return false; // check against someone passing a type name here
- // get language without country if applicable
- String baseLanguage = null;
- int index = language.indexOf(LANGUAGE_SEPARATOR);
- if (index > -1) {
- baseLanguage = language.substring(0, index);
- }
+ compileIfNeeded();
+ ToF_Languages tof_langs = name2tof_langs.get(aFullFeatureName);
+ if (languageMatches(tof_langs, language)) {
+ return true;
+ }
+
+ // special code for allAnnotatorFeatures: return true if type name is found and
+ // has all annotator features set
+ tof_langs = availName2tof_langs().get(aFullFeatureName.substring(0, typeEndPosition));
+ if (null != tof_langs && tof_langs.tof.isAllAnnotatorFeatures() && languageMatches(tof_langs, language)) {
+ if (null != mTypeSystem) {
+ return null != mTypeSystem.getFeatureByFullName(aFullFeatureName); // verify feature is there
+ }
+ return true;
+ }
+ return false;
+ }
- boolean found = false;
+ /**
+ * Languages matches if the query language is xxx-yyy and
+ * result spec languages contains:
+ * x-unspecified
+ * xxx-yyy
+ * xxx
+ * or if query language is x-unspecified
+ *
+ * @param tof_langs
+ * @param language
+ * @return
+ */
+ private boolean languageMatches(ToF_Languages tof_langs, String language) {
+ if (null == tof_langs) {
+ return false;
+ }
+ BitSet languages = tof_langs.languages;
+ if (languages.get(UNSPECIFIED_LANGUAGE_INDEX) ||
+ languages.get(getLanguageIndex(language))) {
+ return true;
+ }
+ String baseLanguage = getLanguageWithoutCountry(language);
+ return baseLanguage != language &&
+ languages.get(getLanguageIndex(baseLanguage));
+ }
- // if compile() has been called can be done by a hash lookup
- if (!mCompiledNameToLanguageMap.isEmpty()) {
- HashSet languages = (HashSet) mCompiledNameToLanguageMap.get(aFullFeatureName);
- if (languages != null) {
- // check if tof is supported for the current language
- if (UNSPECIFIED_LANGUAGE.equals(language) || languages.contains(language)
- || languages.contains(UNSPECIFIED_LANGUAGE) || languages.contains(baseLanguage)) {
- // mark item found
- found = true;
- }
- }
- } else {
- // brute force search
- // (also need to consider Types with allAnnotatorFeatures = true)
- String typeName = "";
- int typeSeparatorIndex = aFullFeatureName.indexOf(':');
- if (typeSeparatorIndex > 0) {
- typeName = aFullFeatureName.substring(0, typeSeparatorIndex);
- }
-
- Iterator it = mTypesAndFeatures.keySet().iterator();
- while (it.hasNext()) {
- TypeOrFeature elem = (TypeOrFeature) it.next();
- if ((!elem.isType() && aFullFeatureName.equals(elem.getName()))
- || (elem.isType() && elem.isAllAnnotatorFeatures() && typeName.equals(elem
- .getName()))) {
- HashSet languages = (HashSet) mTypesAndFeatures.get(elem);
- if (languages != null) {
- // check if tof is supported for the current language
- if (UNSPECIFIED_LANGUAGE.equals(language) || languages.contains(language)
- || languages.contains(UNSPECIFIED_LANGUAGE) || languages.contains(baseLanguage)) {
- // mark item found
- return true;
- }
- }
- }
- }
+ private boolean languageMatches(ToF_Languages tof_langs, int languageIndex, int baseLanguageIndex) {
+ if (null == tof_langs) {
+ return false;
+ }
+ BitSet languages = tof_langs.languages;
+ if (languages.get(UNSPECIFIED_LANGUAGE_INDEX) ||
+ languages.get(languageIndex)) {
+ return true;
}
-
- return found;
+ return baseLanguageIndex != languageIndex &&
+ languages.get(baseLanguageIndex);
}
+
/**
* @see org.apache.uima.resource.impl.MetaDataObject_impl#getXmlizationInfo()
*/
+ @Override
protected XmlizationInfo getXmlizationInfo() {
return new XmlizationInfo("resultSpecification", null,
new PropertyXmlInfo[] { new PropertyXmlInfo("resultTypesAndFeatures", null) });
@@ -518,45 +742,29 @@
* boolean)
*/
public void addCapabilities(Capability[] capabilities, boolean outputs) {
- if (capabilities != null) {
- for (int i = 0; i < capabilities.length; i++) {
- TypeOrFeature[] tofs = outputs ? capabilities[i].getOutputs() : capabilities[i].getInputs();
-
- // get supported languages
- String[] supportedLanguagesArr = capabilities[i].getLanguagesSupported();
-
- HashSet supportedLanguages = null;
- if (supportedLanguagesArr != null && supportedLanguagesArr.length > 0) {
- // create new HashSet with the initial capacity of the supportedLanguageArr
- supportedLanguages = new HashSet(supportedLanguagesArr.length);
- // add all supported languages to at HashSet
- for (int x = 0; x < supportedLanguagesArr.length; x++) {
- // add current language to the HashSet
- supportedLanguages.add(supportedLanguagesArr[x]);
- }
- } else {
- // if no languages are set, set default language
- supportedLanguages = mDefaultLanguage;
- }
-
- for (int y = 0; y < tofs.length; y++) {
- mTypesAndFeatures.put(tofs[y], supportedLanguages);
- }
-
+ if (null == capabilities) {
+ return;
+ }
+ for (Capability capability : capabilities) {
+ TypeOrFeature[] tofs = outputs ? capability.getOutputs() : capability.getInputs();
+ String[] supportedLanguages = capability.getLanguagesSupported();
+ if (null == supportedLanguages) {
+ supportedLanguages = mDefaultLanguage;
+ }
+ for (TypeOrFeature tof : tofs) {
+ addResultTypeOrFeatureAddLanguage(tof, supportedLanguages);
}
}
- // revert to uncompiled state
- mCompiledNameToLanguageMap.clear();
+ setNeedsCompilation();
}
/**
* @see org.apache.uima.analysis_engine.ResultSpecification#removeTypeOrFeature(org.apache.uima.analysis_engine.TypeOrFeature)
*/
public void removeTypeOrFeature(TypeOrFeature aTypeOrFeature) {
- // reomve Type or Feature from the
- mTypesAndFeatures.remove(aTypeOrFeature);
- // revert to uncompiled state
- mCompiledNameToLanguageMap.clear();
+ // remove Type or Feature from the
+ name2tof_langs.remove(aTypeOrFeature.getName());
+ setNeedsCompilation(); // may have removed something which had subtypes
}
/**
@@ -564,18 +772,26 @@
*
* @return Object copy of the current object
*/
+ @Override
public Object clone() {
// create new result specification
// NOTE: we don't use super.clone here, since for performance reasons
// we want to do a faster clone that what the general-purpose logic in
// MetaDataObject_impl does. This class is marked final so that
// this can't cause a problem if ResultSpecification_impl is subclassed.
- ResultSpecification_impl newResultSpec = new ResultSpecification_impl();
-
- // clone HashMaps
- newResultSpec.mTypesAndFeatures = new HashMap(this.mTypesAndFeatures);
- newResultSpec.mDefaultLanguage = new HashSet(this.mDefaultLanguage);
+ return new ResultSpecification_impl(this);
+ }
- return newResultSpec;
+ public void setTypeSystem(TypeSystem ts) {
+ if (mTypeSystem == ts) {
+ return;
+ }
+ mTypeSystem = ts;
+ setNeedsCompilation();
+ }
+
+ public TypeSystem getTypeSystem() {
+ return mTypeSystem;
}
+
}
Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/compatibility/AnnotatorAdapter.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/compatibility/AnnotatorAdapter.java?rev=615608&r1=615607&r2=615608&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/compatibility/AnnotatorAdapter.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/compatibility/AnnotatorAdapter.java Sun Jan 27 06:21:40 2008
@@ -139,12 +139,15 @@
if (mAnnotator instanceof TextAnnotator) {
CAS cas = (CAS) aCAS;
ResultSpecification rs = getResultSpecForLanguage(cas.getDocumentLanguage());
+ rs.setTypeSystem(cas.getTypeSystem());
((TextAnnotator) mAnnotator).process(cas, rs);
} else if (mAnnotator instanceof JTextAnnotator) {
JCas jcas = (JCas) aCAS;
ResultSpecification rs = getResultSpecForLanguage(jcas.getDocumentLanguage());
+ rs.setTypeSystem(jcas.getTypeSystem());
((JTextAnnotator) mAnnotator).process(jcas, rs);
} else if (mAnnotator instanceof GenericAnnotator) {
+ mDefaultResultSpecification.setTypeSystem(((CAS) aCAS).getTypeSystem());
((GenericAnnotator) mAnnotator).process((CAS) aCAS, mDefaultResultSpecification);
}
} catch (AnnotatorProcessException e) {
Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/flow/impl/CapabilityLanguageFlowController.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/flow/impl/CapabilityLanguageFlowController.java?rev=615608&r1=615607&r2=615608&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/flow/impl/CapabilityLanguageFlowController.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/flow/impl/CapabilityLanguageFlowController.java Sun Jan 27 06:21:40 2008
@@ -24,9 +24,9 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.apache.uima.UIMAFramework;
import org.apache.uima.UIMARuntimeException;
@@ -52,11 +52,14 @@
* have already been produced by a previous AE in the flow.
*/
public class CapabilityLanguageFlowController extends CasFlowController_ImplBase {
- private ArrayList mStaticSequence;
+ private List<AnalysisSequenceCapabilityNode> mStaticSequence;
- private Map mComponentMetaDataMap;
+ private Map<String, AnalysisEngineMetaData> mComponentMetaDataMap;
- private Map mFlowTable;
+ private Map<String, List<AnalysisSequenceCapabilityNode>> mFlowTable;
+
+ private final Map<String, ResultSpecification> lastResultSpecForComponent =
+ new HashMap<String, ResultSpecification>();
/**
* main language separator e.g 'en' and 'en-US'
@@ -70,16 +73,18 @@
*/
public void initialize(FlowControllerContext aContext) throws ResourceInitializationException {
super.initialize(aContext);
- mComponentMetaDataMap = aContext.getAnalysisEngineMetaDataMap();
+ mComponentMetaDataMap = (Map<String, AnalysisEngineMetaData>)aContext.getAnalysisEngineMetaDataMap();
// build a list of AnalysisSequenceNodes from the capabilityLanguageFlow
- mStaticSequence = new ArrayList();
+ mStaticSequence = new ArrayList<AnalysisSequenceCapabilityNode>();
CapabilityLanguageFlow flowConstraints = (CapabilityLanguageFlow) aContext
.getAggregateMetadata().getFlowConstraints();
- String[] flow = flowConstraints.getCapabilityLanguageFlow();
- for (int i = 0; i < flow.length; i++) {
- AnalysisEngineMetaData md = (AnalysisEngineMetaData) mComponentMetaDataMap.get(flow[i]);
- mStaticSequence.add(new AnalysisSequenceCapabilityNode(flow[i], md.getCapabilities(), null));
+ for (String aeKey : flowConstraints.getCapabilityLanguageFlow()) {
+ mStaticSequence.add(
+ new AnalysisSequenceCapabilityNode(
+ aeKey,
+ mComponentMetaDataMap.get(aeKey).getCapabilities(),
+ null));
}
// compute flow table with the specified capabilities
@@ -92,43 +97,37 @@
* @see org.apache.uima.flow.CasFlowController_ImplBase#computeFlow(org.apache.uima.cas.CAS)
*/
public Flow computeFlow(CAS aCAS) throws AnalysisEngineProcessException {
- CapabilityLanguageFlowObject flow = new CapabilityLanguageFlowObject(mFlowTable);
+ CapabilityLanguageFlowObject flow = new CapabilityLanguageFlowObject(mFlowTable, this);
flow.setCas(aCAS);
return flow;
}
/**
- * method computeFlowTable create the flow table for faster processing. The flow table inlcudes
- * for all languages in the capabilities the coresponding flow sequence
+ * method computeFlowTable create the flow table for faster processing. The flow table includes
+ * the coresponding flow sequence for all languages in the capabilities
*
* @param aCapabilities
* aggregate engine capabilities
* @return Map - flow table includes all sequences for all languages
*/
- protected Map computeFlowTable(Capability[] aCapabilities) {
+ protected Map<String, List<AnalysisSequenceCapabilityNode>> computeFlowTable(Capability[] aCapabilities) {
// create flowTable
- Map flowTable = new HashMap();
+ Map<String, List<AnalysisSequenceCapabilityNode>> flowTable =
+ new HashMap<String, List<AnalysisSequenceCapabilityNode>>();
// get all languages from the capabilities
- HashSet languages = new HashSet();
- for (int i = 0; i < aCapabilities.length; i++) {
- // get languages from current capability
- aCapabilities[i].getLanguagesSupported();
- String language;
- for (int y = 0; y < aCapabilities[i].getLanguagesSupported().length; y++) {
- language = aCapabilities[i].getLanguagesSupported()[y];
- languages.add(language);
+ Set<String> languages = new HashSet<String>();
+ for (Capability capability : aCapabilities) {
+ for (String capabilityLanguage : capability.getLanguagesSupported()) {
+ languages.add(capabilityLanguage);
}
}
// create flow table with sequences for all languages
- Iterator it = languages.iterator();
- while (it.hasNext()) {
- // add sequence for the current language
- String language = (String) it.next();
- flowTable.put(language, computeSequence(language, aCapabilities));
+ for (String capabilityLanguage : languages) {
+ flowTable.put(capabilityLanguage, computeSequence(capabilityLanguage, aCapabilities));
}
-
+
return flowTable;
}
@@ -142,8 +141,8 @@
*
* @return List - capabilityLanguageAnalysisSequence for the current language
*/
- protected List computeSequence(String language, Capability[] aCapabilities) {
- language = Language.normalize(language);
+ protected List<AnalysisSequenceCapabilityNode> computeSequence(String language, Capability[] aCapabilities) {
+ language = Language.normalize(language); // lower-cases, replaces _ with -, changes null to x-unspecified
// create resultSpec from the current aggregate capabilities
ResultSpecification resultSpec = UIMAFramework.getResourceSpecifierFactory()
@@ -156,43 +155,48 @@
}
// create array list for the current sequence
- List newSequence = new ArrayList();
+ List<AnalysisSequenceCapabilityNode> newSequence = new ArrayList<AnalysisSequenceCapabilityNode>();
- // loop pver all annotators that should be called
+ // loop over all annotators that should be called
+ // In this loop we will gradually reduce the set of output capabilities
for (int sequenceIndex = 0; sequenceIndex < mStaticSequence.size(); sequenceIndex++) {
- // get array of ouput capabilities for the current languge from the current result spec
- TypeOrFeature[] ouputCapabilities = resultSpec.getResultTypesAndFeatures(language);
+ // get array of output capabilities for the current language from the current result spec
+ TypeOrFeature[] outputCapabilities = resultSpec.getResultTypesAndFeatures(language);
+ // Augment these outputCapabilities if the language-spec is for a country, to
+ // include the outputCapabilities for the language without the country-spec.
+
// strip language extension if available
int index = language.indexOf(LANGUAGE_SEPARATOR);
// if country extension is available
if (index >= 0) {
- // create HashSet for outputSpec
- HashSet outputSpec = new HashSet();
+ // create Set for outputSpecs, so we can eliminate duplicates
+ Set<TypeOrFeature> outputSpec = new HashSet<TypeOrFeature>();
- // add language with country extension output capabilities to the outputSpec
- if (ouputCapabilities.length > 0) {
- for (int i = 0; i < ouputCapabilities.length; i++) {
- outputSpec.add(ouputCapabilities[i]);
+ // add language with country extension removed,
+ // to the existing output capabilities (or if non exist, just use
+ // the capabilities for the language without the country extension)
+ if (outputCapabilities.length > 0) {
+ // copy all existing capabilities to the Set
+ for (TypeOrFeature outputCapability : outputCapabilities) {
+ outputSpec.add(outputCapability);
}
// get array of output capabilities only for the language without country extension
- ouputCapabilities = resultSpec.getResultTypesAndFeatures(language.substring(0, index));
+ outputCapabilities = resultSpec.getResultTypesAndFeatures(language.substring(0, index));
- // add language output capabilities to the outputSpec
- for (int i = 0; i < ouputCapabilities.length; i++) {
- outputSpec.add(ouputCapabilities[i]);
+ // add language output capabilities to the Set
+ for (TypeOrFeature outputCapability : outputCapabilities) {
+ outputSpec.add(outputCapability);
}
// convert all output capabilities to a outputCapabilities array
- ouputCapabilities = new TypeOrFeature[outputSpec.size()];
- outputSpec.toArray(ouputCapabilities);
- } else
- // for language with country extension was noting found
- {
+ outputCapabilities = new TypeOrFeature[outputSpec.size()];
+ outputSpec.toArray(outputCapabilities);
+ } else { // for language with country extension was noting found
// get array of output capabilities with the new main language without country extension
- ouputCapabilities = resultSpec.getResultTypesAndFeatures(language.substring(0, index));
+ outputCapabilities = resultSpec.getResultTypesAndFeatures(language.substring(0, index));
}
}
@@ -208,7 +212,7 @@
// check output capabilites from the current result spec
// get next analysis engine from the sequence node
- node = (AnalysisSequenceCapabilityNode) mStaticSequence.get(sequenceIndex);
+ node = mStaticSequence.get(sequenceIndex);
// get capability container from the current analysis engine
CapabilityContainer capabilityContainer = node.getCapabilityContainer();
@@ -217,33 +221,39 @@
currentAnalysisResultSpec = UIMAFramework.getResourceSpecifierFactory()
.createResultSpecification();
- // check if engine should be called - loop over all ouput capabilities of the result spec
- for (int i = 0; i < ouputCapabilities.length; i++) {
- // check if current ToF can be produced by the current analysis engine
- if (capabilityContainer.hasOutputTypeOrFeature(ouputCapabilities[i], language, true)) {
- currentAnalysisResultSpec.addResultTypeOrFeature(ouputCapabilities[i]);
+ // check if engine should be called -
+ // loop over all remaining ouput capabilities of the aggregate's result spec
+ // to see if this component of the aggregate produces that type or feature,
+ // for this language
+ for (TypeOrFeature tof : outputCapabilities) {
+ if (capabilityContainer.hasOutputTypeOrFeature(tof, language, true)) {
+ currentAnalysisResultSpec.addResultTypeOrFeature(tof);
shouldEngineBeCalled = true;
-
// remove current ToF from the result spec
- resultSpec.removeTypeOrFeature(ouputCapabilities[i]);
+ resultSpec.removeTypeOrFeature(tof);
}
}
+
// skip engine if not output capability match
- // check if current engine should be called
+ // should be called is false if this engine produces none of the
+ // needed outputs of the aggregate
if (shouldEngineBeCalled == true) {
- // set result spec for current analysis engine
+ // tell this component which output types/features need to be produced
+ // note: As an exception to the way normal result-specifications are produced,
+ // here we *don't* add the types/features which are input to
+ // other delegates need to be produced.
+ // This is for backward compatibility.
node.setResultSpec(currentAnalysisResultSpec);
// add note to the current sequence
- newSequence.add(node.clone());
- } else
+ newSequence.add((AnalysisSequenceCapabilityNode)node.clone());
+ } else {
// engine should not be called, but add null to the sequence to track that
// engine should not be called
- {
newSequence.add(null);
}
- }
+ } // loop over all delegates in the flow sequence
return newSequence;
}
@@ -261,5 +271,9 @@
throw new UIMARuntimeException(e);
}
return desc;
+ }
+
+ public Map<String, ResultSpecification> getLastResultSpecForComponent() {
+ return lastResultSpecForComponent;
}
}