You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by re...@apache.org on 2013/01/11 00:12:37 UTC

svn commit: r1431721 [7/19] - in /uima/sandbox/uimafit/trunk: uimafit-examples/src/main/java/org/apache/uima/fit/examples/experiment/pos/ uimafit-examples/src/main/java/org/apache/uima/fit/examples/getstarted/ uimafit-examples/src/main/java/org/apache/...

Modified: uima/sandbox/uimafit/trunk/uimafit/src/main/java/org/apache/uima/fit/factory/ConfigurationParameterFactory.java
URL: http://svn.apache.org/viewvc/uima/sandbox/uimafit/trunk/uimafit/src/main/java/org/apache/uima/fit/factory/ConfigurationParameterFactory.java?rev=1431721&r1=1431720&r2=1431721&view=diff
==============================================================================
--- uima/sandbox/uimafit/trunk/uimafit/src/main/java/org/apache/uima/fit/factory/ConfigurationParameterFactory.java (original)
+++ uima/sandbox/uimafit/trunk/uimafit/src/main/java/org/apache/uima/fit/factory/ConfigurationParameterFactory.java Thu Jan 10 23:12:33 2013
@@ -49,540 +49,509 @@ import org.springframework.beans.TypeMis
  */
 
 public final class ConfigurationParameterFactory {
-	private ConfigurationParameterFactory() {
-		// This class is not meant to be instantiated
-	}
-
-	/**
-	 * A mapping from Java class names to UIMA configuration parameter type names. Used by
-	 * setConfigurationParameters().
-	 */
-	public static final Map<String, String> javaUimaTypeMap = new HashMap<String, String>();
-	static {
-		javaUimaTypeMap.put(Boolean.class.getName(), ConfigurationParameter.TYPE_BOOLEAN);
-		javaUimaTypeMap.put(Float.class.getName(), ConfigurationParameter.TYPE_FLOAT);
-		javaUimaTypeMap.put(Double.class.getName(), ConfigurationParameter.TYPE_FLOAT);
-		javaUimaTypeMap.put(Integer.class.getName(), ConfigurationParameter.TYPE_INTEGER);
-		javaUimaTypeMap.put(String.class.getName(), ConfigurationParameter.TYPE_STRING);
-		javaUimaTypeMap.put("boolean", ConfigurationParameter.TYPE_BOOLEAN);
-		javaUimaTypeMap.put("float", ConfigurationParameter.TYPE_FLOAT);
-		javaUimaTypeMap.put("double", ConfigurationParameter.TYPE_FLOAT);
-		javaUimaTypeMap.put("int", ConfigurationParameter.TYPE_INTEGER);
-
-	}
-
-	/**
-	 * This method determines if the field is annotated with
-	 * {@link org.apache.uima.fit.descriptor.ConfigurationParameter}.
-	 */
-	public static boolean isConfigurationParameterField(Field field) {
-		return field.isAnnotationPresent(org.apache.uima.fit.descriptor.ConfigurationParameter.class);
-	}
-
-	/**
-	 * Determines the default value of an annotated configuration parameter. The returned value is
-	 * not necessarily the value that the annotated member variable will be instantiated with in
-	 * ConfigurationParameterInitializer which does extra work to convert the UIMA configuration
-	 * parameter value to comply with the type of the member variable.
-	 */
-	public static Object getDefaultValue(Field field) {
-		if (isConfigurationParameterField(field)) {
-			org.apache.uima.fit.descriptor.ConfigurationParameter annotation = field
-					.getAnnotation(org.apache.uima.fit.descriptor.ConfigurationParameter.class);
-
-			String[] stringValue = annotation.defaultValue();
-			if (stringValue.length == 1
-					&& stringValue[0]
-							.equals(org.apache.uima.fit.descriptor.ConfigurationParameter.NO_DEFAULT_VALUE)) {
-				return null;
-			}
-
-			String valueType = getConfigurationParameterType(field);
-			boolean isMultiValued = isMultiValued(field);
-
-			if (!isMultiValued) {
-				if (ConfigurationParameter.TYPE_BOOLEAN.equals(valueType)) {
-					return Boolean.parseBoolean(stringValue[0]);
-				}
-				else if (ConfigurationParameter.TYPE_FLOAT.equals(valueType)) {
-					return Float.parseFloat(stringValue[0]);
-				}
-				else if (ConfigurationParameter.TYPE_INTEGER.equals(valueType)) {
-					return Integer.parseInt(stringValue[0]);
-				}
-				else if (ConfigurationParameter.TYPE_STRING.equals(valueType)) {
-					return stringValue[0];
-				}
-				throw new UIMA_IllegalArgumentException(
-						UIMA_IllegalArgumentException.METADATA_ATTRIBUTE_TYPE_MISMATCH,
-						new Object[] { valueType, "type" });
-			}
-			else {
-				if (ConfigurationParameter.TYPE_BOOLEAN.equals(valueType)) {
-					Boolean[] returnValues = new Boolean[stringValue.length];
-					for (int i = 0; i < stringValue.length; i++) {
-						returnValues[i] = Boolean.parseBoolean(stringValue[i]);
-					}
-					return returnValues;
-				}
-				else if (ConfigurationParameter.TYPE_FLOAT.equals(valueType)) {
-					Float[] returnValues = new Float[stringValue.length];
-					for (int i = 0; i < stringValue.length; i++) {
-						returnValues[i] = Float.parseFloat(stringValue[i]);
-					}
-					return returnValues;
-				}
-				else if (ConfigurationParameter.TYPE_INTEGER.equals(valueType)) {
-					Integer[] returnValues = new Integer[stringValue.length];
-					for (int i = 0; i < stringValue.length; i++) {
-						returnValues[i] = Integer.parseInt(stringValue[i]);
-					}
-					return returnValues;
-				}
-				else if (ConfigurationParameter.TYPE_STRING.equals(valueType)) {
-					return stringValue;
-				}
-				throw new UIMA_IllegalArgumentException(
-						UIMA_IllegalArgumentException.METADATA_ATTRIBUTE_TYPE_MISMATCH,
-						new Object[] { valueType, "type" });
-
-			}
-
-		}
-		else {
-			throw new IllegalArgumentException("field is not annotated with annotation of type "
-					+ org.apache.uima.fit.descriptor.ConfigurationParameter.class.getName());
-		}
-	}
-
-	private static String getConfigurationParameterType(Field field) {
-		Class<?> parameterClass = field.getType();
-		String parameterClassName;
-		if (parameterClass.isArray()) {
-			parameterClassName = parameterClass.getComponentType().getName();
-		}
-		else if (Collection.class.isAssignableFrom(parameterClass)) {
-			ParameterizedType collectionType = (ParameterizedType) field.getGenericType();
-			parameterClassName = ((Class<?>) (collectionType.getActualTypeArguments()[0]))
-					.getName();
-		}
-		else {
-			parameterClassName = parameterClass.getName();
-		}
-		String parameterType = javaUimaTypeMap.get(parameterClassName);
-		if (parameterType == null) {
-			return ConfigurationParameter.TYPE_STRING;
-		}
-		return parameterType;
-	}
-
-	private static boolean isMultiValued(Field field) {
-		Class<?> parameterClass = field.getType();
-		if (parameterClass.isArray()) {
-			return true;
-		}
-		else if (Collection.class.isAssignableFrom(parameterClass)) {
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * This method generates the default name of a configuration parameter that is defined by an
-	 * {@link org.apache.uima.fit.descriptor.ConfigurationParameter} annotation when no name is given
-	 */
-	public static String getConfigurationParameterName(Field field) {
-		if (isConfigurationParameterField(field)) {
-			org.apache.uima.fit.descriptor.ConfigurationParameter annotation = field
-					.getAnnotation(org.apache.uima.fit.descriptor.ConfigurationParameter.class);
-			String name = annotation.name();
-			if (name.equals(org.apache.uima.fit.descriptor.ConfigurationParameter.USE_FIELD_NAME)) {
-				name = field.getDeclaringClass().getName() + "." + field.getName();
-			}
-			return name;
-		}
-		return null;
-	}
-
-	/**
-	 * This method provides a convenient way to generate a configuration parameter name for a member
-	 * variable that is annotated with {@link org.apache.uima.fit.descriptor.ConfigurationParameter} and no
-	 * name is provided in the annotation.
-	 */
-	public static String createConfigurationParameterName(Class<?> clazz, String fieldName)
-			throws IllegalArgumentException {
-		try {
-			return ConfigurationParameterFactory.getConfigurationParameterName(clazz
-					.getDeclaredField(fieldName));
-		}
-		catch (NoSuchFieldException e) {
-			throw new IllegalArgumentException(e);
-		}
-	}
-
-	/**
-	 * A factory method for creating a ConfigurationParameter from a given field definition
-	 */
-	public static ConfigurationParameter createPrimitiveParameter(Field field) {
-		if (isConfigurationParameterField(field)) {
-			org.apache.uima.fit.descriptor.ConfigurationParameter annotation = field
-					.getAnnotation(org.apache.uima.fit.descriptor.ConfigurationParameter.class);
-			String name = getConfigurationParameterName(field);
-			boolean multiValued = isMultiValued(field);
-			String parameterType = getConfigurationParameterType(field);
-			return createPrimitiveParameter(name, parameterType, annotation.description(),
-					multiValued, annotation.mandatory());
-		}
-		else {
-			throw new IllegalArgumentException("field is not annotated with annotation of type "
-					+ org.apache.uima.fit.descriptor.ConfigurationParameter.class.getName());
-		}
-	}
-
-	/**
-	 * A factory method for creating a ConfigurationParameter object.
-	 */
-	public static ConfigurationParameter createPrimitiveParameter(String name,
-			Class<?> parameterClass, String parameterDescription, boolean isMandatory) {
-		String parameterClassName;
-		if (parameterClass.isArray()) {
-			parameterClassName = parameterClass.getComponentType().getName();
-		}
-		else {
-			parameterClassName = parameterClass.getName();
-		}
-
-		String parameterType = javaUimaTypeMap.get(parameterClassName);
-		if (parameterType == null) {
-			// If we cannot map the type, we'll try to convert it to a String
-			parameterType = ConfigurationParameter.TYPE_STRING;
-		}
-		return createPrimitiveParameter(name, parameterType, parameterDescription,
-				parameterClass.isArray(), isMandatory);
-	}
-	
-	/**
-	 * Convert a value so it can be injected into a UIMA component. UIMA only supports several
-	 * parameter types. If the value is not of these types, this method can be used to coerce the
-	 * value into a supported type (typically String). It is also used to convert primitive
-	 * arrays to object arrays when necessary.
-	 * 
-	 * @param param the configuration parameter.
-	 * @param aValue the parameter value.
-	 * @return the converted value.
-	 */
-	protected static Object convertParameterValue(ConfigurationParameter param, Object aValue)
-	{
-		Object value = aValue;
-		if (value.getClass().isArray()
-				&& value.getClass().getComponentType().getName().equals("boolean")) {
-			value = ArrayUtils.toObject((boolean[]) value);
-		}
-		else if (value.getClass().isArray()
-				&& value.getClass().getComponentType().getName().equals("int")) {
-			value = ArrayUtils.toObject((int[]) value);
-		}
-		else if (value.getClass().isArray()
-				&& value.getClass().getComponentType().getName().equals("float")) {
-			value = ArrayUtils.toObject((float[]) value);
-		}
-		else {
-			try {
-				if (param.getType().equals(ConfigurationParameter.TYPE_STRING)) {
-					SimpleTypeConverter converter = new SimpleTypeConverter();
-					PropertyEditorUtil.registerUimaFITEditors(converter);		
-					if (value.getClass().isArray() || value instanceof Collection) {
-						value = converter.convertIfNecessary(value, String[].class);
-					}
-					else {
-						value = converter.convertIfNecessary(value, String.class);
-					}
-				}
-			}
-			catch (TypeMismatchException e) {
-				throw new IllegalArgumentException(e.getMessage(), e);
-			}
-		}
-		
-		return value;
-	}
-
-	/**
-	 * A factory method for creating a ConfigurationParameter object.
-	 */
-	public static ConfigurationParameter createPrimitiveParameter(String name,
-			String parameterType, String parameterDescription, boolean isMultiValued,
-			boolean isMandatory) {
-		ConfigurationParameter param = new ConfigurationParameter_impl();
-		param.setName(name);
-		param.setType(parameterType);
-		param.setDescription(parameterDescription);
-		param.setMultiValued(isMultiValued);
-		param.setMandatory(isMandatory);
-		return param;
-	}
-
-	/**
-	 * This method converts configuration data provided as an array of objects and returns a
-	 * {@link ConfigurationData} object
-	 */
-	public static ConfigurationData createConfigurationData(Object... configurationData) {
-		if (configurationData == null) {
-			return new ConfigurationData(new ConfigurationParameter[0], new Object[0]);
-		}
-		
-		ensureParametersComeInPairs(configurationData);
-
-		int numberOfParameters = configurationData.length / 2;
-		List<ConfigurationParameter> configurationParameters = new ArrayList<ConfigurationParameter>();
-		List<Object> configurationValues = new ArrayList<Object>();
-
-		for (int i = 0; i < numberOfParameters; i++) {
-			String name = (String) configurationData[i * 2];
-			Object value = configurationData[i * 2 + 1];
-
-			if (value == null || value instanceof ExternalResourceDescription) {
-				continue;
-			}
-			
-			ConfigurationParameter param = ConfigurationParameterFactory.createPrimitiveParameter(
-					name, value.getClass(), null, false);
-			configurationParameters.add(param);
-			configurationValues.add(ConfigurationParameterFactory.convertParameterValue(param, value));
-		}
-		return new ConfigurationData(
-				configurationParameters.toArray(new ConfigurationParameter[configurationParameters
-						.size()]), configurationValues.toArray());
-	}
-
-	/**
-	 * This method creates configuration data for a given class definition using reflection and the
-	 * configuration parameter annotation
-	 */
-	public static ConfigurationData createConfigurationData(Class<?> componentClass) {
-		List<ConfigurationParameter> configurationParameters = new ArrayList<ConfigurationParameter>();
-		List<Object> configurationValues = new ArrayList<Object>();
-
-		for (Field field : ReflectionUtil.getFields(componentClass)) {
-			if (ConfigurationParameterFactory.isConfigurationParameterField(field)) {
-				configurationParameters.add(ConfigurationParameterFactory
-						.createPrimitiveParameter(field));
-				configurationValues.add(ConfigurationParameterFactory.getDefaultValue(field));
-			}
-		}
-
-		return new ConfigurationData(
-				configurationParameters.toArray(new ConfigurationParameter[configurationParameters
-						.size()]), configurationValues.toArray(new Object[configurationValues
-						.size()]));
-	}
-
-	/**
-	 * A simple class for storing an array of configuration parameters along with an array of the
-	 * values that will fill in those configuration parameters
-	 *
-	 */
-	public static class ConfigurationData {
-		public ConfigurationParameter[] configurationParameters;
-		public Object[] configurationValues;
-
-		public ConfigurationData(ConfigurationParameter[] configurationParameters,
-				Object[] configurationValues) {
-			this.configurationParameters = configurationParameters;
-			this.configurationValues = configurationValues;
-		}
-
-	}
-
-	/**
-	 * This method adds configuration parameter information to the specifier given the provided
-	 * configuration data
-	 *
-	 * @param configurationData
-	 *            should consist of name value pairs.
-	 */
-	public static void addConfigurationParameters(ResourceCreationSpecifier specifier,
-			Object... configurationData) {
-		ConfigurationData cdata = ConfigurationParameterFactory
-				.createConfigurationData(configurationData);
-		ResourceCreationSpecifierFactory.setConfigurationParameters(specifier,
-				cdata.configurationParameters, cdata.configurationValues);
-	}
-
-	/**
-	 * Provides a mechanism to add configuration parameter information to a specifier for the given
-	 * classes. this method may be useful in situations where a class definition has annotated
-	 * configuration parameters that you want to include in the given specifier
-	 */
-	public static void addConfigurationParameters(ResourceCreationSpecifier specifier,
-			List<Class<?>> dynamicallyLoadedClasses) {
-		for (Class<?> dynamicallyLoadedClass : dynamicallyLoadedClasses) {
-			ConfigurationData reflectedConfigurationData = ConfigurationParameterFactory
-					.createConfigurationData(dynamicallyLoadedClass);
-			ResourceCreationSpecifierFactory.setConfigurationParameters(specifier,
-					reflectedConfigurationData.configurationParameters,
-					reflectedConfigurationData.configurationValues);
-		}
-
-	}
-
-	/**
-	 * Provides a mechanism to add configuration parameter information to a specifier for the given
-	 * classes. this method may be useful in situations where a class definition has annotated
-	 * configuration parameters that you want to include in the given specifier
-	 */
-	public static void addConfigurationParameters(ResourceCreationSpecifier specifier,
-			Class<?>... dynamicallyLoadedClasses) {
-		for (Class<?> dynamicallyLoadedClass : dynamicallyLoadedClasses) {
-			ConfigurationData reflectedConfigurationData = ConfigurationParameterFactory
-					.createConfigurationData(dynamicallyLoadedClass);
-			ResourceCreationSpecifierFactory.setConfigurationParameters(specifier,
-					reflectedConfigurationData.configurationParameters,
-					reflectedConfigurationData.configurationValues);
-		}
-	}
-
-	/**
-	 * Adds a single configuration parameter name value pair to a specifier
-	 */
-	public static void addConfigurationParameter(ResourceCreationSpecifier specifier, String name,
-			Object value) {
-		ConfigurationData cdata = ConfigurationParameterFactory
-				.createConfigurationData(name, value);
-		ResourceCreationSpecifierFactory.setConfigurationParameters(specifier,
-				cdata.configurationParameters, cdata.configurationValues);
-
-	}
-
-	/**
-	 * Helper method to make sure configuration parameter lists have always pairs of name/values.
-	 * 
-	 * @param configurationData the configuration parameters.
-	 */
-	static void ensureParametersComeInPairs(Object[] configurationData) {
-		if (configurationData != null && configurationData.length % 2 != 0) {
-			throw new IllegalArgumentException("Parameter arguments have to "
-					+ "come in key/value pairs, but found odd number of " + "arguments ["
-					+ configurationData.length + "]");
-		}
-	}
-
-	/**
-	 * Fetches the parameter settings from the given resource specifier.
-	 * 
-	 * @param spec a resource specifier.
-	 * @return the parameter settings.
-	 */
-	public static Map<String, Object> getParameterSettings(ResourceSpecifier spec)
-	{
-		Map<String, Object> settings = new HashMap<String, Object>();
-		if (spec instanceof CustomResourceSpecifier) {
-			for (Parameter p : ((CustomResourceSpecifier) spec).getParameters()) {
-				settings.put(p.getName(), p.getValue());
-			}
-		}
-		else if (spec instanceof ResourceCreationSpecifier) {
-			for (NameValuePair p : ((ResourceCreationSpecifier) spec).getMetaData()
-					.getConfigurationParameterSettings().getParameterSettings())
-			{
-				settings.put(p.getName(), p.getValue());
-			}
-		}
-		else if (spec instanceof ConfigurableDataResourceSpecifier) {
-			for (NameValuePair p : ((ResourceCreationSpecifier) spec).getMetaData()
-					.getConfigurationParameterSettings().getParameterSettings())
-			{
-				settings.put(p.getName(), p.getValue());
-			}
-		}
-		else {
-			throw new IllegalClassException("Unsupported resource specifier class ["
-					+ spec.getClass() + "]");
-		}
-		return settings;
-	}
-
-	/**
-	 * Sets the specified parameter in the given resource specifier. If the specified is a
-	 * {@link CustomResourceSpecifier} an exception is thrown if the parameter value not a String.
-	 * 
-	 * @param aSpec a resource specifier.
-	 * @param name the parameter name.
-	 * @param value the parameter value.
-	 * @throws IllegalClassException if the value is not of a supported type for the given 
-	 * specifier.
-	 */
-	public static void setParameter(ResourceSpecifier aSpec, String name, Object value)
-	{
-		if (aSpec instanceof CustomResourceSpecifier) {
-			if (!(value instanceof String || value == null)) {
-				throw new IllegalClassException(String.class, value);
-			}
-			CustomResourceSpecifier spec = (CustomResourceSpecifier) aSpec;
-			
-			// If the parameter is already there, update it
-			boolean found = false;
-			for (Parameter p : spec.getParameters()) {
-				if (p.getName().equals(name)) {
-					p.setValue((String) value);
-					found = true;
-				}
-			}
-			
-			// If the parameter is not there, add it
-			if (!found) {
-				Parameter[] params = new Parameter[spec.getParameters().length + 1];
-				System.arraycopy(spec.getParameters(), 0, params, 0, spec.getParameters().length);
-				params[params.length-1] = new Parameter_impl();
-				params[params.length-1].setName(name);
-				params[params.length-1].setValue((String) value);
-				spec.setParameters(params);
-			}
-		}
-		else if (aSpec instanceof ResourceCreationSpecifier) {
-			ResourceMetaData md = ((ResourceCreationSpecifier) aSpec).getMetaData();
-			
-			if (md.getConfigurationParameterDeclarations().getConfigurationParameter(null, name) == null) {
-				throw new IllegalArgumentException("Cannot set undeclared parameter [" + name + "]");
-			}
-			
-			md.getConfigurationParameterSettings().setParameterValue(name, value);
-		}
-		else if (aSpec instanceof ConfigurableDataResourceSpecifier) {
-			ResourceMetaData md = ((ConfigurableDataResourceSpecifier) aSpec).getMetaData();
-			
-			if (md.getConfigurationParameterDeclarations().getConfigurationParameter(null, name) == null) {
-				throw new IllegalArgumentException("Cannot set undeclared parameter [" + name + "]");
-			}
-
-			md.getConfigurationParameterSettings().setParameterValue(name, value);
-		}
-		else {
-			throw new IllegalClassException("Unsupported resource specifier class ["
-					+ aSpec.getClass() + "]");
-		}
-	}
-	
-	/**
-	 * Check if the given parameter can be set on the provided specifier. Some specifier types 
-	 * require parameters to be declared before they can be set.
-	 */
-	public static boolean canParameterBeSet(ResourceSpecifier aSpec, String name)
-	{
-		if (aSpec instanceof CustomResourceSpecifier) {
-			return true;
-		}
-		else if (aSpec instanceof ResourceCreationSpecifier) {
-			ResourceMetaData md = ((ResourceCreationSpecifier) aSpec).getMetaData();
-			return md.getConfigurationParameterDeclarations().getConfigurationParameter(null, name) != null;
-		}
-		else if (aSpec instanceof ConfigurableDataResourceSpecifier) {
-			ResourceMetaData md = ((ConfigurableDataResourceSpecifier) aSpec).getMetaData();
-			return md.getConfigurationParameterDeclarations().getConfigurationParameter(null, name) != null;
-		}
-		else {
-			throw new IllegalClassException("Unsupported resource specifier class ["
-					+ aSpec.getClass() + "]");
-		}		
-	}
+  private ConfigurationParameterFactory() {
+    // This class is not meant to be instantiated
+  }
+
+  /**
+   * A mapping from Java class names to UIMA configuration parameter type names. Used by
+   * setConfigurationParameters().
+   */
+  public static final Map<String, String> javaUimaTypeMap = new HashMap<String, String>();
+  static {
+    javaUimaTypeMap.put(Boolean.class.getName(), ConfigurationParameter.TYPE_BOOLEAN);
+    javaUimaTypeMap.put(Float.class.getName(), ConfigurationParameter.TYPE_FLOAT);
+    javaUimaTypeMap.put(Double.class.getName(), ConfigurationParameter.TYPE_FLOAT);
+    javaUimaTypeMap.put(Integer.class.getName(), ConfigurationParameter.TYPE_INTEGER);
+    javaUimaTypeMap.put(String.class.getName(), ConfigurationParameter.TYPE_STRING);
+    javaUimaTypeMap.put("boolean", ConfigurationParameter.TYPE_BOOLEAN);
+    javaUimaTypeMap.put("float", ConfigurationParameter.TYPE_FLOAT);
+    javaUimaTypeMap.put("double", ConfigurationParameter.TYPE_FLOAT);
+    javaUimaTypeMap.put("int", ConfigurationParameter.TYPE_INTEGER);
+
+  }
+
+  /**
+   * This method determines if the field is annotated with
+   * {@link org.apache.uima.fit.descriptor.ConfigurationParameter}.
+   */
+  public static boolean isConfigurationParameterField(Field field) {
+    return field.isAnnotationPresent(org.apache.uima.fit.descriptor.ConfigurationParameter.class);
+  }
+
+  /**
+   * Determines the default value of an annotated configuration parameter. The returned value is not
+   * necessarily the value that the annotated member variable will be instantiated with in
+   * ConfigurationParameterInitializer which does extra work to convert the UIMA configuration
+   * parameter value to comply with the type of the member variable.
+   */
+  public static Object getDefaultValue(Field field) {
+    if (isConfigurationParameterField(field)) {
+      org.apache.uima.fit.descriptor.ConfigurationParameter annotation = field
+              .getAnnotation(org.apache.uima.fit.descriptor.ConfigurationParameter.class);
+
+      String[] stringValue = annotation.defaultValue();
+      if (stringValue.length == 1
+              && stringValue[0]
+                      .equals(org.apache.uima.fit.descriptor.ConfigurationParameter.NO_DEFAULT_VALUE)) {
+        return null;
+      }
+
+      String valueType = getConfigurationParameterType(field);
+      boolean isMultiValued = isMultiValued(field);
+
+      if (!isMultiValued) {
+        if (ConfigurationParameter.TYPE_BOOLEAN.equals(valueType)) {
+          return Boolean.parseBoolean(stringValue[0]);
+        } else if (ConfigurationParameter.TYPE_FLOAT.equals(valueType)) {
+          return Float.parseFloat(stringValue[0]);
+        } else if (ConfigurationParameter.TYPE_INTEGER.equals(valueType)) {
+          return Integer.parseInt(stringValue[0]);
+        } else if (ConfigurationParameter.TYPE_STRING.equals(valueType)) {
+          return stringValue[0];
+        }
+        throw new UIMA_IllegalArgumentException(
+                UIMA_IllegalArgumentException.METADATA_ATTRIBUTE_TYPE_MISMATCH, new Object[] {
+                    valueType, "type" });
+      } else {
+        if (ConfigurationParameter.TYPE_BOOLEAN.equals(valueType)) {
+          Boolean[] returnValues = new Boolean[stringValue.length];
+          for (int i = 0; i < stringValue.length; i++) {
+            returnValues[i] = Boolean.parseBoolean(stringValue[i]);
+          }
+          return returnValues;
+        } else if (ConfigurationParameter.TYPE_FLOAT.equals(valueType)) {
+          Float[] returnValues = new Float[stringValue.length];
+          for (int i = 0; i < stringValue.length; i++) {
+            returnValues[i] = Float.parseFloat(stringValue[i]);
+          }
+          return returnValues;
+        } else if (ConfigurationParameter.TYPE_INTEGER.equals(valueType)) {
+          Integer[] returnValues = new Integer[stringValue.length];
+          for (int i = 0; i < stringValue.length; i++) {
+            returnValues[i] = Integer.parseInt(stringValue[i]);
+          }
+          return returnValues;
+        } else if (ConfigurationParameter.TYPE_STRING.equals(valueType)) {
+          return stringValue;
+        }
+        throw new UIMA_IllegalArgumentException(
+                UIMA_IllegalArgumentException.METADATA_ATTRIBUTE_TYPE_MISMATCH, new Object[] {
+                    valueType, "type" });
+
+      }
+
+    } else {
+      throw new IllegalArgumentException("field is not annotated with annotation of type "
+              + org.apache.uima.fit.descriptor.ConfigurationParameter.class.getName());
+    }
+  }
+
+  private static String getConfigurationParameterType(Field field) {
+    Class<?> parameterClass = field.getType();
+    String parameterClassName;
+    if (parameterClass.isArray()) {
+      parameterClassName = parameterClass.getComponentType().getName();
+    } else if (Collection.class.isAssignableFrom(parameterClass)) {
+      ParameterizedType collectionType = (ParameterizedType) field.getGenericType();
+      parameterClassName = ((Class<?>) (collectionType.getActualTypeArguments()[0])).getName();
+    } else {
+      parameterClassName = parameterClass.getName();
+    }
+    String parameterType = javaUimaTypeMap.get(parameterClassName);
+    if (parameterType == null) {
+      return ConfigurationParameter.TYPE_STRING;
+    }
+    return parameterType;
+  }
+
+  private static boolean isMultiValued(Field field) {
+    Class<?> parameterClass = field.getType();
+    if (parameterClass.isArray()) {
+      return true;
+    } else if (Collection.class.isAssignableFrom(parameterClass)) {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * This method generates the default name of a configuration parameter that is defined by an
+   * {@link org.apache.uima.fit.descriptor.ConfigurationParameter} annotation when no name is given
+   */
+  public static String getConfigurationParameterName(Field field) {
+    if (isConfigurationParameterField(field)) {
+      org.apache.uima.fit.descriptor.ConfigurationParameter annotation = field
+              .getAnnotation(org.apache.uima.fit.descriptor.ConfigurationParameter.class);
+      String name = annotation.name();
+      if (name.equals(org.apache.uima.fit.descriptor.ConfigurationParameter.USE_FIELD_NAME)) {
+        name = field.getDeclaringClass().getName() + "." + field.getName();
+      }
+      return name;
+    }
+    return null;
+  }
+
+  /**
+   * This method provides a convenient way to generate a configuration parameter name for a member
+   * variable that is annotated with {@link org.apache.uima.fit.descriptor.ConfigurationParameter}
+   * and no name is provided in the annotation.
+   */
+  public static String createConfigurationParameterName(Class<?> clazz, String fieldName)
+          throws IllegalArgumentException {
+    try {
+      return ConfigurationParameterFactory.getConfigurationParameterName(clazz
+              .getDeclaredField(fieldName));
+    } catch (NoSuchFieldException e) {
+      throw new IllegalArgumentException(e);
+    }
+  }
+
+  /**
+   * A factory method for creating a ConfigurationParameter from a given field definition
+   */
+  public static ConfigurationParameter createPrimitiveParameter(Field field) {
+    if (isConfigurationParameterField(field)) {
+      org.apache.uima.fit.descriptor.ConfigurationParameter annotation = field
+              .getAnnotation(org.apache.uima.fit.descriptor.ConfigurationParameter.class);
+      String name = getConfigurationParameterName(field);
+      boolean multiValued = isMultiValued(field);
+      String parameterType = getConfigurationParameterType(field);
+      return createPrimitiveParameter(name, parameterType, annotation.description(), multiValued,
+              annotation.mandatory());
+    } else {
+      throw new IllegalArgumentException("field is not annotated with annotation of type "
+              + org.apache.uima.fit.descriptor.ConfigurationParameter.class.getName());
+    }
+  }
+
+  /**
+   * A factory method for creating a ConfigurationParameter object.
+   */
+  public static ConfigurationParameter createPrimitiveParameter(String name,
+          Class<?> parameterClass, String parameterDescription, boolean isMandatory) {
+    String parameterClassName;
+    if (parameterClass.isArray()) {
+      parameterClassName = parameterClass.getComponentType().getName();
+    } else {
+      parameterClassName = parameterClass.getName();
+    }
+
+    String parameterType = javaUimaTypeMap.get(parameterClassName);
+    if (parameterType == null) {
+      // If we cannot map the type, we'll try to convert it to a String
+      parameterType = ConfigurationParameter.TYPE_STRING;
+    }
+    return createPrimitiveParameter(name, parameterType, parameterDescription,
+            parameterClass.isArray(), isMandatory);
+  }
+
+  /**
+   * Convert a value so it can be injected into a UIMA component. UIMA only supports several
+   * parameter types. If the value is not of these types, this method can be used to coerce the
+   * value into a supported type (typically String). It is also used to convert primitive arrays to
+   * object arrays when necessary.
+   * 
+   * @param param
+   *          the configuration parameter.
+   * @param aValue
+   *          the parameter value.
+   * @return the converted value.
+   */
+  protected static Object convertParameterValue(ConfigurationParameter param, Object aValue) {
+    Object value = aValue;
+    if (value.getClass().isArray()
+            && value.getClass().getComponentType().getName().equals("boolean")) {
+      value = ArrayUtils.toObject((boolean[]) value);
+    } else if (value.getClass().isArray()
+            && value.getClass().getComponentType().getName().equals("int")) {
+      value = ArrayUtils.toObject((int[]) value);
+    } else if (value.getClass().isArray()
+            && value.getClass().getComponentType().getName().equals("float")) {
+      value = ArrayUtils.toObject((float[]) value);
+    } else {
+      try {
+        if (param.getType().equals(ConfigurationParameter.TYPE_STRING)) {
+          SimpleTypeConverter converter = new SimpleTypeConverter();
+          PropertyEditorUtil.registerUimaFITEditors(converter);
+          if (value.getClass().isArray() || value instanceof Collection) {
+            value = converter.convertIfNecessary(value, String[].class);
+          } else {
+            value = converter.convertIfNecessary(value, String.class);
+          }
+        }
+      } catch (TypeMismatchException e) {
+        throw new IllegalArgumentException(e.getMessage(), e);
+      }
+    }
+
+    return value;
+  }
+
+  /**
+   * A factory method for creating a ConfigurationParameter object.
+   */
+  public static ConfigurationParameter createPrimitiveParameter(String name, String parameterType,
+          String parameterDescription, boolean isMultiValued, boolean isMandatory) {
+    ConfigurationParameter param = new ConfigurationParameter_impl();
+    param.setName(name);
+    param.setType(parameterType);
+    param.setDescription(parameterDescription);
+    param.setMultiValued(isMultiValued);
+    param.setMandatory(isMandatory);
+    return param;
+  }
+
+  /**
+   * This method converts configuration data provided as an array of objects and returns a
+   * {@link ConfigurationData} object
+   */
+  public static ConfigurationData createConfigurationData(Object... configurationData) {
+    if (configurationData == null) {
+      return new ConfigurationData(new ConfigurationParameter[0], new Object[0]);
+    }
+
+    ensureParametersComeInPairs(configurationData);
+
+    int numberOfParameters = configurationData.length / 2;
+    List<ConfigurationParameter> configurationParameters = new ArrayList<ConfigurationParameter>();
+    List<Object> configurationValues = new ArrayList<Object>();
+
+    for (int i = 0; i < numberOfParameters; i++) {
+      String name = (String) configurationData[i * 2];
+      Object value = configurationData[i * 2 + 1];
+
+      if (value == null || value instanceof ExternalResourceDescription) {
+        continue;
+      }
+
+      ConfigurationParameter param = ConfigurationParameterFactory.createPrimitiveParameter(name,
+              value.getClass(), null, false);
+      configurationParameters.add(param);
+      configurationValues.add(ConfigurationParameterFactory.convertParameterValue(param, value));
+    }
+    return new ConfigurationData(
+            configurationParameters.toArray(new ConfigurationParameter[configurationParameters
+                    .size()]), configurationValues.toArray());
+  }
+
+  /**
+   * This method creates configuration data for a given class definition using reflection and the
+   * configuration parameter annotation
+   */
+  public static ConfigurationData createConfigurationData(Class<?> componentClass) {
+    List<ConfigurationParameter> configurationParameters = new ArrayList<ConfigurationParameter>();
+    List<Object> configurationValues = new ArrayList<Object>();
+
+    for (Field field : ReflectionUtil.getFields(componentClass)) {
+      if (ConfigurationParameterFactory.isConfigurationParameterField(field)) {
+        configurationParameters.add(ConfigurationParameterFactory.createPrimitiveParameter(field));
+        configurationValues.add(ConfigurationParameterFactory.getDefaultValue(field));
+      }
+    }
+
+    return new ConfigurationData(
+            configurationParameters.toArray(new ConfigurationParameter[configurationParameters
+                    .size()]), configurationValues.toArray(new Object[configurationValues.size()]));
+  }
+
+  /**
+   * A simple class for storing an array of configuration parameters along with an array of the
+   * values that will fill in those configuration parameters
+   * 
+   */
+  public static class ConfigurationData {
+    public ConfigurationParameter[] configurationParameters;
+
+    public Object[] configurationValues;
+
+    public ConfigurationData(ConfigurationParameter[] configurationParameters,
+            Object[] configurationValues) {
+      this.configurationParameters = configurationParameters;
+      this.configurationValues = configurationValues;
+    }
+
+  }
+
+  /**
+   * This method adds configuration parameter information to the specifier given the provided
+   * configuration data
+   * 
+   * @param configurationData
+   *          should consist of name value pairs.
+   */
+  public static void addConfigurationParameters(ResourceCreationSpecifier specifier,
+          Object... configurationData) {
+    ConfigurationData cdata = ConfigurationParameterFactory
+            .createConfigurationData(configurationData);
+    ResourceCreationSpecifierFactory.setConfigurationParameters(specifier,
+            cdata.configurationParameters, cdata.configurationValues);
+  }
+
+  /**
+   * Provides a mechanism to add configuration parameter information to a specifier for the given
+   * classes. this method may be useful in situations where a class definition has annotated
+   * configuration parameters that you want to include in the given specifier
+   */
+  public static void addConfigurationParameters(ResourceCreationSpecifier specifier,
+          List<Class<?>> dynamicallyLoadedClasses) {
+    for (Class<?> dynamicallyLoadedClass : dynamicallyLoadedClasses) {
+      ConfigurationData reflectedConfigurationData = ConfigurationParameterFactory
+              .createConfigurationData(dynamicallyLoadedClass);
+      ResourceCreationSpecifierFactory.setConfigurationParameters(specifier,
+              reflectedConfigurationData.configurationParameters,
+              reflectedConfigurationData.configurationValues);
+    }
+
+  }
+
+  /**
+   * Provides a mechanism to add configuration parameter information to a specifier for the given
+   * classes. this method may be useful in situations where a class definition has annotated
+   * configuration parameters that you want to include in the given specifier
+   */
+  public static void addConfigurationParameters(ResourceCreationSpecifier specifier,
+          Class<?>... dynamicallyLoadedClasses) {
+    for (Class<?> dynamicallyLoadedClass : dynamicallyLoadedClasses) {
+      ConfigurationData reflectedConfigurationData = ConfigurationParameterFactory
+              .createConfigurationData(dynamicallyLoadedClass);
+      ResourceCreationSpecifierFactory.setConfigurationParameters(specifier,
+              reflectedConfigurationData.configurationParameters,
+              reflectedConfigurationData.configurationValues);
+    }
+  }
+
+  /**
+   * Adds a single configuration parameter name value pair to a specifier
+   */
+  public static void addConfigurationParameter(ResourceCreationSpecifier specifier, String name,
+          Object value) {
+    ConfigurationData cdata = ConfigurationParameterFactory.createConfigurationData(name, value);
+    ResourceCreationSpecifierFactory.setConfigurationParameters(specifier,
+            cdata.configurationParameters, cdata.configurationValues);
+
+  }
+
+  /**
+   * Helper method to make sure configuration parameter lists have always pairs of name/values.
+   * 
+   * @param configurationData
+   *          the configuration parameters.
+   */
+  static void ensureParametersComeInPairs(Object[] configurationData) {
+    if (configurationData != null && configurationData.length % 2 != 0) {
+      throw new IllegalArgumentException("Parameter arguments have to "
+              + "come in key/value pairs, but found odd number of " + "arguments ["
+              + configurationData.length + "]");
+    }
+  }
+
+  /**
+   * Fetches the parameter settings from the given resource specifier.
+   * 
+   * @param spec
+   *          a resource specifier.
+   * @return the parameter settings.
+   */
+  public static Map<String, Object> getParameterSettings(ResourceSpecifier spec) {
+    Map<String, Object> settings = new HashMap<String, Object>();
+    if (spec instanceof CustomResourceSpecifier) {
+      for (Parameter p : ((CustomResourceSpecifier) spec).getParameters()) {
+        settings.put(p.getName(), p.getValue());
+      }
+    } else if (spec instanceof ResourceCreationSpecifier) {
+      for (NameValuePair p : ((ResourceCreationSpecifier) spec).getMetaData()
+              .getConfigurationParameterSettings().getParameterSettings()) {
+        settings.put(p.getName(), p.getValue());
+      }
+    } else if (spec instanceof ConfigurableDataResourceSpecifier) {
+      for (NameValuePair p : ((ResourceCreationSpecifier) spec).getMetaData()
+              .getConfigurationParameterSettings().getParameterSettings()) {
+        settings.put(p.getName(), p.getValue());
+      }
+    } else {
+      throw new IllegalClassException("Unsupported resource specifier class [" + spec.getClass()
+              + "]");
+    }
+    return settings;
+  }
+
+  /**
+   * Sets the specified parameter in the given resource specifier. If the specified is a
+   * {@link CustomResourceSpecifier} an exception is thrown if the parameter value not a String.
+   * 
+   * @param aSpec
+   *          a resource specifier.
+   * @param name
+   *          the parameter name.
+   * @param value
+   *          the parameter value.
+   * @throws IllegalClassException
+   *           if the value is not of a supported type for the given specifier.
+   */
+  public static void setParameter(ResourceSpecifier aSpec, String name, Object value) {
+    if (aSpec instanceof CustomResourceSpecifier) {
+      if (!(value instanceof String || value == null)) {
+        throw new IllegalClassException(String.class, value);
+      }
+      CustomResourceSpecifier spec = (CustomResourceSpecifier) aSpec;
+
+      // If the parameter is already there, update it
+      boolean found = false;
+      for (Parameter p : spec.getParameters()) {
+        if (p.getName().equals(name)) {
+          p.setValue((String) value);
+          found = true;
+        }
+      }
+
+      // If the parameter is not there, add it
+      if (!found) {
+        Parameter[] params = new Parameter[spec.getParameters().length + 1];
+        System.arraycopy(spec.getParameters(), 0, params, 0, spec.getParameters().length);
+        params[params.length - 1] = new Parameter_impl();
+        params[params.length - 1].setName(name);
+        params[params.length - 1].setValue((String) value);
+        spec.setParameters(params);
+      }
+    } else if (aSpec instanceof ResourceCreationSpecifier) {
+      ResourceMetaData md = ((ResourceCreationSpecifier) aSpec).getMetaData();
+
+      if (md.getConfigurationParameterDeclarations().getConfigurationParameter(null, name) == null) {
+        throw new IllegalArgumentException("Cannot set undeclared parameter [" + name + "]");
+      }
+
+      md.getConfigurationParameterSettings().setParameterValue(name, value);
+    } else if (aSpec instanceof ConfigurableDataResourceSpecifier) {
+      ResourceMetaData md = ((ConfigurableDataResourceSpecifier) aSpec).getMetaData();
+
+      if (md.getConfigurationParameterDeclarations().getConfigurationParameter(null, name) == null) {
+        throw new IllegalArgumentException("Cannot set undeclared parameter [" + name + "]");
+      }
+
+      md.getConfigurationParameterSettings().setParameterValue(name, value);
+    } else {
+      throw new IllegalClassException("Unsupported resource specifier class [" + aSpec.getClass()
+              + "]");
+    }
+  }
+
+  /**
+   * Check if the given parameter can be set on the provided specifier. Some specifier types require
+   * parameters to be declared before they can be set.
+   */
+  public static boolean canParameterBeSet(ResourceSpecifier aSpec, String name) {
+    if (aSpec instanceof CustomResourceSpecifier) {
+      return true;
+    } else if (aSpec instanceof ResourceCreationSpecifier) {
+      ResourceMetaData md = ((ResourceCreationSpecifier) aSpec).getMetaData();
+      return md.getConfigurationParameterDeclarations().getConfigurationParameter(null, name) != null;
+    } else if (aSpec instanceof ConfigurableDataResourceSpecifier) {
+      ResourceMetaData md = ((ConfigurableDataResourceSpecifier) aSpec).getMetaData();
+      return md.getConfigurationParameterDeclarations().getConfigurationParameter(null, name) != null;
+    } else {
+      throw new IllegalClassException("Unsupported resource specifier class [" + aSpec.getClass()
+              + "]");
+    }
+  }
 }

Modified: uima/sandbox/uimafit/trunk/uimafit/src/main/java/org/apache/uima/fit/factory/CpeBuilder.java
URL: http://svn.apache.org/viewvc/uima/sandbox/uimafit/trunk/uimafit/src/main/java/org/apache/uima/fit/factory/CpeBuilder.java?rev=1431721&r1=1431720&r2=1431721&view=diff
==============================================================================
--- uima/sandbox/uimafit/trunk/uimafit/src/main/java/org/apache/uima/fit/factory/CpeBuilder.java (original)
+++ uima/sandbox/uimafit/trunk/uimafit/src/main/java/org/apache/uima/fit/factory/CpeBuilder.java Thu Jan 10 23:12:33 2013
@@ -56,129 +56,118 @@ import org.xml.sax.SAXException;
  * {@link AnalysisEngineDescription}. If an aggregate analysis engine description is used, the
  * builder will add each child of the aggregate engine as one processor to the engine. This works
  * only for aggregate analysis engines using a {@link FixedFlow}.
- *
+ * 
  */
-public class CpeBuilder
-{
-//	private final Log log = LogFactory.getLog(getClass());
-
-	private static final String ACTION_ON_MAX_ERROR = "terminate";
-
-	/**
-	 * used for calculating the CAS pool size which needs to be adjusted to the number of parallel
-	 * pipelines
-	 */
-	private int maxProcessingUnitThreadCount = 1;
-
-	private final CpeDescription cpeDesc = produceDescriptor();
-
-	public void setMaxProcessingUnitThreadCount(int aMaxProcessingUnitThreadCount)
-	{
-		maxProcessingUnitThreadCount = aMaxProcessingUnitThreadCount;
-	}
-
-	public void setReader(CollectionReaderDescription aDesc)
-		throws IOException, SAXException, CpeDescriptorException
-	{
-		// Remove all collection readers
-		cpeDesc.setAllCollectionCollectionReaders(new CpeCollectionReader[0]);
-
-		URL descUrl = materializeDescriptor(aDesc).toURI().toURL();
-		CpeCollectionReader reader = produceCollectionReader(descUrl.toString());
-		cpeDesc.addCollectionReader(reader);
-	}
-
-	public void setAnalysisEngine(AnalysisEngineDescription aDesc)
-		throws IOException, SAXException, CpeDescriptorException, InvalidXMLException
-	{
-		// Remove all CAS processors
-		cpeDesc.setCpeCasProcessors(null);
-
-		if (aDesc.isPrimitive()) {
-			// For a primitive AE we just add it.
-			CpeIntegratedCasProcessor proc = createProcessor("", aDesc);
-			cpeDesc.addCasProcessor(proc);
-		}
-		else {
-			// For an aggregate AE we dive into the first aggregation level and add each of the
-			// contained AEs separately, thus allowing us to control their properties separately
-
-			Map<String, ResourceSpecifier> delegates = aDesc.getDelegateAnalysisEngineSpecifiers();
-			FixedFlow flow = (FixedFlow) aDesc.getAnalysisEngineMetaData().getFlowConstraints();
-			for (String key : flow.getFixedFlow()) {
-				AnalysisEngineDescription aeDesc = (AnalysisEngineDescription) delegates.get(key);
-//				boolean multi = aeDesc.getAnalysisEngineMetaData().getOperationalProperties()
-//						.isMultipleDeploymentAllowed();
-//				log.info("["+key+"] runs "+ (multi ? "multi-threaded" : "single-threaded"));
-				CpeIntegratedCasProcessor proc = createProcessor(key, aeDesc);
-				cpeDesc.addCasProcessor(proc);
-			}
-		}
-	}
-
-	public CpeDescription getCpeDescription()
-	{
-		return cpeDesc;
-	}
-	
-	public CollectionProcessingEngine createCpe(StatusCallbackListener aListener)
-		throws ResourceInitializationException, CpeDescriptorException
-	{
-		ResourceManager resMgr = UIMAFramework.newDefaultResourceManager();
-		if (maxProcessingUnitThreadCount == 0) {
-			cpeDesc.getCpeCasProcessors().setPoolSize(3);
-		}
-		else {
-			cpeDesc.getCpeCasProcessors().setPoolSize(maxProcessingUnitThreadCount + 2);
-			cpeDesc.setProcessingUnitThreadCount(maxProcessingUnitThreadCount);
-		}
-		CollectionProcessingEngine cpe = produceCollectionProcessingEngine(cpeDesc, resMgr, null);
-		cpe.addStatusCallbackListener(aListener);
-		return cpe;
-	}
-
-	/**
-	 * Writes a temporary file containing a XML descriptor of the given resource. Returns the file.
-	 *
-	 * @param resource
-	 *            A resource specifier that should we materialized.
-	 * @return The file containing the XML representation of the given resource.
-	 */
-	private static File materializeDescriptor(ResourceSpecifier resource)
-		throws IOException, SAXException
-	{
-		File tempDesc = File.createTempFile("desc", ".xml");
-		tempDesc.deleteOnExit();
-		
-		BufferedWriter out = null;
-		try {
-			out = new BufferedWriter(new FileWriter(tempDesc));
-			resource.toXML(out);
-		}
-		finally {
-			IOUtils.closeQuietly(out);
-		}
-
-		return tempDesc;
-	}
-
-	private static CpeIntegratedCasProcessor createProcessor(String key, AnalysisEngineDescription aDesc)
-		throws IOException, SAXException, CpeDescriptorException
-	{
-		URL descUrl = materializeDescriptor(aDesc).toURI().toURL();
-
-		CpeInclude cpeInclude = getResourceSpecifierFactory().createInclude();
-		cpeInclude.set(descUrl.toString());
-
-		CpeComponentDescriptor ccd = getResourceSpecifierFactory().createDescriptor();
-		ccd.setInclude(cpeInclude);
-
-		CpeIntegratedCasProcessor proc = produceCasProcessor(key);
-		proc.setCpeComponentDescriptor(ccd);
-		proc.setAttributeValue(CpeDefaultValues.PROCESSING_UNIT_THREAD_COUNT, 1);
-		proc.setActionOnMaxError(ACTION_ON_MAX_ERROR);
-		proc.setMaxErrorCount(0);
+public class CpeBuilder {
+  // private final Log log = LogFactory.getLog(getClass());
 
-		return proc;
-	}
+  private static final String ACTION_ON_MAX_ERROR = "terminate";
+
+  /**
+   * used for calculating the CAS pool size which needs to be adjusted to the number of parallel
+   * pipelines
+   */
+  private int maxProcessingUnitThreadCount = 1;
+
+  private final CpeDescription cpeDesc = produceDescriptor();
+
+  public void setMaxProcessingUnitThreadCount(int aMaxProcessingUnitThreadCount) {
+    maxProcessingUnitThreadCount = aMaxProcessingUnitThreadCount;
+  }
+
+  public void setReader(CollectionReaderDescription aDesc) throws IOException, SAXException,
+          CpeDescriptorException {
+    // Remove all collection readers
+    cpeDesc.setAllCollectionCollectionReaders(new CpeCollectionReader[0]);
+
+    URL descUrl = materializeDescriptor(aDesc).toURI().toURL();
+    CpeCollectionReader reader = produceCollectionReader(descUrl.toString());
+    cpeDesc.addCollectionReader(reader);
+  }
+
+  public void setAnalysisEngine(AnalysisEngineDescription aDesc) throws IOException, SAXException,
+          CpeDescriptorException, InvalidXMLException {
+    // Remove all CAS processors
+    cpeDesc.setCpeCasProcessors(null);
+
+    if (aDesc.isPrimitive()) {
+      // For a primitive AE we just add it.
+      CpeIntegratedCasProcessor proc = createProcessor("", aDesc);
+      cpeDesc.addCasProcessor(proc);
+    } else {
+      // For an aggregate AE we dive into the first aggregation level and add each of the
+      // contained AEs separately, thus allowing us to control their properties separately
+
+      Map<String, ResourceSpecifier> delegates = aDesc.getDelegateAnalysisEngineSpecifiers();
+      FixedFlow flow = (FixedFlow) aDesc.getAnalysisEngineMetaData().getFlowConstraints();
+      for (String key : flow.getFixedFlow()) {
+        AnalysisEngineDescription aeDesc = (AnalysisEngineDescription) delegates.get(key);
+        // boolean multi = aeDesc.getAnalysisEngineMetaData().getOperationalProperties()
+        // .isMultipleDeploymentAllowed();
+        // log.info("["+key+"] runs "+ (multi ? "multi-threaded" : "single-threaded"));
+        CpeIntegratedCasProcessor proc = createProcessor(key, aeDesc);
+        cpeDesc.addCasProcessor(proc);
+      }
+    }
+  }
+
+  public CpeDescription getCpeDescription() {
+    return cpeDesc;
+  }
+
+  public CollectionProcessingEngine createCpe(StatusCallbackListener aListener)
+          throws ResourceInitializationException, CpeDescriptorException {
+    ResourceManager resMgr = UIMAFramework.newDefaultResourceManager();
+    if (maxProcessingUnitThreadCount == 0) {
+      cpeDesc.getCpeCasProcessors().setPoolSize(3);
+    } else {
+      cpeDesc.getCpeCasProcessors().setPoolSize(maxProcessingUnitThreadCount + 2);
+      cpeDesc.setProcessingUnitThreadCount(maxProcessingUnitThreadCount);
+    }
+    CollectionProcessingEngine cpe = produceCollectionProcessingEngine(cpeDesc, resMgr, null);
+    cpe.addStatusCallbackListener(aListener);
+    return cpe;
+  }
+
+  /**
+   * Writes a temporary file containing a XML descriptor of the given resource. Returns the file.
+   * 
+   * @param resource
+   *          A resource specifier that should we materialized.
+   * @return The file containing the XML representation of the given resource.
+   */
+  private static File materializeDescriptor(ResourceSpecifier resource) throws IOException,
+          SAXException {
+    File tempDesc = File.createTempFile("desc", ".xml");
+    tempDesc.deleteOnExit();
+
+    BufferedWriter out = null;
+    try {
+      out = new BufferedWriter(new FileWriter(tempDesc));
+      resource.toXML(out);
+    } finally {
+      IOUtils.closeQuietly(out);
+    }
+
+    return tempDesc;
+  }
+
+  private static CpeIntegratedCasProcessor createProcessor(String key,
+          AnalysisEngineDescription aDesc) throws IOException, SAXException, CpeDescriptorException {
+    URL descUrl = materializeDescriptor(aDesc).toURI().toURL();
+
+    CpeInclude cpeInclude = getResourceSpecifierFactory().createInclude();
+    cpeInclude.set(descUrl.toString());
+
+    CpeComponentDescriptor ccd = getResourceSpecifierFactory().createDescriptor();
+    ccd.setInclude(cpeInclude);
+
+    CpeIntegratedCasProcessor proc = produceCasProcessor(key);
+    proc.setCpeComponentDescriptor(ccd);
+    proc.setAttributeValue(CpeDefaultValues.PROCESSING_UNIT_THREAD_COUNT, 1);
+    proc.setActionOnMaxError(ACTION_ON_MAX_ERROR);
+    proc.setMaxErrorCount(0);
+
+    return proc;
+  }
 }