/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.uima.fit.factory;

import static java.util.Arrays.asList;
import static org.apache.uima.fit.descriptor.OperationalProperties.MODIFIES_CAS_DEFAULT;
import static org.apache.uima.fit.descriptor.OperationalProperties.MULTIPLE_DEPLOYMENT_ALLOWED_DEFAULT;
import static org.apache.uima.fit.descriptor.OperationalProperties.OUTPUTS_NEW_CASES_DEFAULT;
import static org.apache.uima.fit.factory.ConfigurationParameterFactory.createConfigurationData;
import static org.apache.uima.fit.factory.ConfigurationParameterFactory.ensureParametersComeInPairs;
import static org.apache.uima.fit.factory.ConfigurationParameterFactory.setParameters;
import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResource;
import static org.apache.uima.fit.factory.ExternalResourceFactory.createResourceDependencies;
import static org.apache.uima.fit.factory.FsIndexFactory.createFsIndexCollection;
import static org.apache.uima.fit.factory.TypePrioritiesFactory.createTypePriorities;
import static org.apache.uima.fit.factory.TypeSystemDescriptionFactory.createTypeSystemDescription;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.uima.Constants;
import org.apache.uima.UIMAFramework;
import org.apache.uima.analysis_component.AnalysisComponent;
import org.apache.uima.analysis_engine.AnalysisEngine;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.analysis_engine.impl.AggregateAnalysisEngine_impl;
import org.apache.uima.analysis_engine.impl.AnalysisEngineDescription_impl;
import org.apache.uima.analysis_engine.metadata.AnalysisEngineMetaData;
import org.apache.uima.analysis_engine.metadata.FixedFlow;
import org.apache.uima.analysis_engine.metadata.FlowControllerDeclaration;
import org.apache.uima.analysis_engine.metadata.SofaMapping;
import org.apache.uima.analysis_engine.metadata.impl.FixedFlow_impl;
import org.apache.uima.analysis_engine.metadata.impl.FlowControllerDeclaration_impl;
import org.apache.uima.cas.CAS;
import org.apache.uima.fit.descriptor.SofaCapability;
import org.apache.uima.fit.descriptor.TypeCapability;
import org.apache.uima.fit.factory.ConfigurationParameterFactory.ConfigurationData;
import org.apache.uima.fit.internal.ReflectionUtil;
import org.apache.uima.fit.internal.ResourceManagerFactory;
import org.apache.uima.flow.FlowControllerDescription;
import org.apache.uima.resource.ExternalResourceDescription;
import org.apache.uima.resource.PearSpecifier;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.ResourceSpecifier;
import org.apache.uima.resource.metadata.Capability;
import org.apache.uima.resource.metadata.ConfigurationParameter;
import org.apache.uima.resource.metadata.FsIndexCollection;
import org.apache.uima.resource.metadata.OperationalProperties;
import org.apache.uima.resource.metadata.TypePriorities;
import org.apache.uima.resource.metadata.TypeSystemDescription;
import org.apache.uima.resource.metadata.impl.Import_impl;
import org.apache.uima.util.CasCreationUtils;
import org.apache.uima.util.InvalidXMLException;

/**
 * A collection of static methods for creating UIMA {@link AnalysisEngineDescription
 * AnalysisEngineDescriptions} and {@link AnalysisEngine AnalysisEngines}.
 * 
 * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
 *      component instances?</a>
 */
public final class AnalysisEngineFactory {
  private AnalysisEngineFactory() {
    // This class is not meant to be instantiated
  }

  /**
   * Get an AnalysisEngine from the name (Java-style, dotted) of an XML descriptor file, and a set
   * of configuration parameters.
   * 
   * @param descriptorName
   *          The fully qualified, Java-style, dotted name of the XML descriptor file.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return the {@link AnalysisEngine} created from the XML descriptor and the configuration
   *         parameters.
   * @throws IOException
   *           if an I/O error occurs
   * @throws InvalidXMLException
   *           if the input XML is not valid or does not specify a valid {@link ResourceSpecifier}
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngine(String descriptorName, Object... configurationData)
          throws InvalidXMLException, IOException, ResourceInitializationException {
    AnalysisEngineDescription aed = createEngineDescription(descriptorName, configurationData);
    return UIMAFramework.produceAnalysisEngine(aed, ResourceManagerFactory.newResourceManager(), null);
  }

  /**
   * Get an AnalysisEngine from the name (Java-style, dotted) of an XML descriptor file, and a set
   * of configuration parameters.
   * 
   * @param descriptorName
   *          The fully qualified, Java-style, dotted name of the XML descriptor file.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return the {@link AnalysisEngine} created from the XML descriptor and the configuration
   *         parameters.
   * @throws IOException
   *           if an I/O error occurs
   * @throws InvalidXMLException
   *           if the input XML is not valid or does not specify a valid {@link ResourceSpecifier}
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use {@link #createEngine(String, Object...)}
   */
  @Deprecated
  public static AnalysisEngine createAnalysisEngine(String descriptorName,
          Object... configurationData) throws InvalidXMLException, IOException,
          ResourceInitializationException {
    return createEngine(descriptorName, configurationData);
  }

  /**
   * This method provides a convenient way to instantiate an AnalysisEngine where the default view
   * is mapped to the view name passed into the method.
   * 
   * @param analysisEngineDescription
   *          the analysis engine description from which the engine is instantiated
   * @param viewName
   *          the view name to map the default view to
   * @return an aggregate analysis engine consisting of a single component whose default view is
   *         mapped to the the view named by viewName.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @see AggregateBuilder
   */
  public static AnalysisEngine createEngine(AnalysisEngineDescription analysisEngineDescription,
          String viewName) throws ResourceInitializationException {
    AggregateBuilder builder = new AggregateBuilder();
    builder.add(analysisEngineDescription, CAS.NAME_DEFAULT_SOFA, viewName);
    return builder.createAggregate();
  }

  /**
   * This method provides a convenient way to instantiate an AnalysisEngine where the default view
   * is mapped to the view name passed into the method.
   * 
   * @param analysisEngineDescription
   *          the analysis engine description from which the engine is instantiated
   * @param viewName
   *          the view name to map the default view to
   * @return an aggregate analysis engine consisting of a single component whose default view is
   *         mapped to the the view named by viewName.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @see AggregateBuilder
   * @deprecated use {@link #createEngine(AnalysisEngineDescription, String)}
   */
  @Deprecated
  public static AnalysisEngine createAnalysisEngine(
          AnalysisEngineDescription analysisEngineDescription, String viewName)
          throws ResourceInitializationException {
    return createEngine(analysisEngineDescription, viewName);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param desc
   *          the descriptor to create the analysis engine from.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngine(AnalysisEngineDescription desc,
          Object... configurationData) throws ResourceInitializationException {
    if (configurationData == null || configurationData.length == 0) {
      return UIMAFramework.produceAnalysisEngine(desc, ResourceManagerFactory.newResourceManager(),
              null);
    } else {
      AnalysisEngineDescription descClone = (AnalysisEngineDescription) desc.clone();
      ResourceCreationSpecifierFactory.setConfigurationParameters(descClone, configurationData);
      return UIMAFramework.produceAnalysisEngine(descClone,
              ResourceManagerFactory.newResourceManager(), null);
    }
  }

  /**
   * Create an aggregate {@link AnalysisEngine}.
   * 
   * @param desc
   *          the descriptor to create the analysis engine from.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use {@link #createEngine(AnalysisEngineDescription, Object...)}
   */
  @Deprecated
  public static AnalysisEngine createAggregate(AnalysisEngineDescription desc)
          throws ResourceInitializationException {
    return createEngine(desc);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param desc
   *          the descriptor to create the analysis engine from.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use {@link #createEngine(AnalysisEngineDescription, Object...)}
   */
  @Deprecated
  public static AnalysisEngine createPrimitive(AnalysisEngineDescription desc,
          Object... configurationData) throws ResourceInitializationException {
    return createEngine(desc, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}. The type system is detected
   * automatically using {@link TypeSystemDescriptionFactory#createTypeSystemDescription()}. Type
   * priorities are detected automatically using
   * {@link TypePrioritiesFactory#createTypePriorities()}. Indexes are detected automatically using
   * {@link FsIndexFactory#createFsIndexCollection()}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngine(Class<? extends AnalysisComponent> componentClass,
          Object... configurationData) throws ResourceInitializationException {
    AnalysisEngineDescription desc = createEngineDescription(componentClass, configurationData);

    // create the AnalysisEngine, initialize it and return it
    return createEngine(desc);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}. The type system is detected
   * automatically using {@link TypeSystemDescriptionFactory#createTypeSystemDescription()}. Type
   * priorities are detected automatically using
   * {@link TypePrioritiesFactory#createTypePriorities()}. Indexes are detected automatically using
   * {@link FsIndexFactory#createFsIndexCollection()}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use {@link #createEngine(Class, Object...)}
   */
  @Deprecated
  public static AnalysisEngine createPrimitive(Class<? extends AnalysisComponent> componentClass,
          Object... configurationData) throws ResourceInitializationException {
    return createEngine(componentClass, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngine(Class<? extends AnalysisComponent> componentClass,
          TypeSystemDescription typeSystem, Object... configurationData)
          throws ResourceInitializationException {
    return createEngine(componentClass, typeSystem, (TypePriorities) null, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use {@link #createEngine(Class, TypeSystemDescription, Object...)}
   */
  @Deprecated
  public static AnalysisEngine createPrimitive(Class<? extends AnalysisComponent> componentClass,
          TypeSystemDescription typeSystem, Object... configurationData)
          throws ResourceInitializationException {
    return createEngine(componentClass, typeSystem, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities as an array of type names (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngine(Class<? extends AnalysisComponent> componentClass,
          TypeSystemDescription typeSystem, String[] typePriorities, Object... configurationData)
          throws ResourceInitializationException {
    TypePriorities tp = null;
    if (typePriorities != null) {
      tp = TypePrioritiesFactory.createTypePriorities(typePriorities);
    }
    return createEngine(componentClass, typeSystem, tp, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities as an array of type names (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use {@link #createEngine(Class, TypeSystemDescription, String[], Object...)}
   */
  @Deprecated
  public static AnalysisEngine createPrimitive(Class<? extends AnalysisComponent> componentClass,
          TypeSystemDescription typeSystem, String[] typePriorities, Object... configurationData)
          throws ResourceInitializationException {
    return createEngine(componentClass, typeSystem, typePriorities, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngine(Class<? extends AnalysisComponent> componentClass,
          TypeSystemDescription typeSystem, TypePriorities typePriorities,
          Object... configurationData) throws ResourceInitializationException {

    AnalysisEngineDescription desc = createEngineDescription(componentClass, typeSystem,
            typePriorities, configurationData);

    // create the AnalysisEngine, initialize it and return it
    return createEngine(desc);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use {@link #createEngine(Class, TypeSystemDescription, TypePriorities, Object...)}
   */
  @Deprecated
  public static AnalysisEngine createPrimitive(Class<? extends AnalysisComponent> componentClass,
          TypeSystemDescription typeSystem, TypePriorities typePriorities,
          Object... configurationData) throws ResourceInitializationException {
    return createEngine(componentClass, typeSystem, typePriorities, configurationData);
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component classes.
   * 
   * @param componentClasses
   *          a list of class that extend {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngine(
          List<Class<? extends AnalysisComponent>> componentClasses,
          TypeSystemDescription typeSystem, TypePriorities typePriorities,
          SofaMapping[] sofaMappings, Object... configurationData)
          throws ResourceInitializationException {
    AnalysisEngineDescription desc = createEngineDescription(componentClasses, typeSystem,
            typePriorities, sofaMappings, configurationData);
    // create the AnalysisEngine, initialize it and return it
    AnalysisEngine engine = new AggregateAnalysisEngine_impl();
    engine.initialize(desc, null);
    return engine;
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component classes.
   * 
   * @param componentClasses
   *          a list of class that extend {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use
   *             {@link #createEngine(List, TypeSystemDescription, TypePriorities, SofaMapping[], Object...)}
   */
  @Deprecated
  public static AnalysisEngine createAggregate(
          List<Class<? extends AnalysisComponent>> componentClasses,
          TypeSystemDescription typeSystem, TypePriorities typePriorities,
          SofaMapping[] sofaMappings, Object... configurationData)
          throws ResourceInitializationException {
    return createEngine(componentClasses, typeSystem, typePriorities, sofaMappings,
            configurationData);
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component classes.
   * 
   * @param componentClasses
   *          a list of class that extend {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param flowControllerDescription
   *          the flow controller description to be used by this aggregate (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngine(
          List<Class<? extends AnalysisComponent>> componentClasses,
          TypeSystemDescription typeSystem, TypePriorities typePriorities,
          SofaMapping[] sofaMappings, FlowControllerDescription flowControllerDescription,
          Object... configurationData) throws ResourceInitializationException {
    AnalysisEngineDescription desc = createEngineDescription(componentClasses, typeSystem,
            typePriorities, sofaMappings, configurationData, flowControllerDescription);
    // create the AnalysisEngine, initialize it and return it
    AnalysisEngine engine = new AggregateAnalysisEngine_impl();
    engine.initialize(desc, null);
    return engine;
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component classes.
   * 
   * @param componentClasses
   *          a list of class that extend {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param flowControllerDescription
   *          the flow controller description to be used by this aggregate (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use
   *             {@link #createEngine(List, TypeSystemDescription, TypePriorities, SofaMapping[], FlowControllerDescription, Object...)}
   */
  @Deprecated
  public static AnalysisEngine createAggregate(
          List<Class<? extends AnalysisComponent>> componentClasses,
          TypeSystemDescription typeSystem, TypePriorities typePriorities,
          SofaMapping[] sofaMappings, FlowControllerDescription flowControllerDescription,
          Object... configurationData) throws ResourceInitializationException {
    return createEngine(componentClasses, typeSystem, typePriorities, sofaMappings,
            flowControllerDescription, configurationData);
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component descriptions.
   * 
   * @param analysisEngineDescriptions
   *          a list of analysis engine descriptions from which the aggregate engine is instantiated
   * @param componentNames
   *          a list of names for the analysis engines in the aggregate. There must be exactly one
   *          name for each analysis engine, given in the same order as the descriptions.
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngine(
          List<AnalysisEngineDescription> analysisEngineDescriptions, List<String> componentNames,
          TypePriorities typePriorities, SofaMapping[] sofaMappings)
          throws ResourceInitializationException {

    AnalysisEngineDescription desc = createEngineDescription(analysisEngineDescriptions,
            componentNames, typePriorities, sofaMappings, null);
    // create the AnalysisEngine, initialize it and return it
    AnalysisEngine engine = new AggregateAnalysisEngine_impl();
    engine.initialize(desc, null);
    return engine;
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component descriptions.
   * 
   * @param analysisEngineDescriptions
   *          a list of analysis engine descriptions from which the aggregate engine is instantiated
   * @param componentNames
   *          a list of names for the analysis engines in the aggregate. There must be exactly one
   *          name for each analysis engine, given in the same order as the descriptions.
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use {@link #createEngine(List, List, TypePriorities, SofaMapping[])}
   */
  @Deprecated
  public static AnalysisEngine createAggregate(
          List<AnalysisEngineDescription> analysisEngineDescriptions, List<String> componentNames,
          TypePriorities typePriorities, SofaMapping[] sofaMappings)
          throws ResourceInitializationException {
    return createEngine(analysisEngineDescriptions, componentNames, typePriorities, sofaMappings);
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component descriptions.
   * 
   * @param analysisEngineDescriptions
   *          a list of analysis engine descriptions from which the aggregate engine is instantiated
   * @param componentNames
   *          a list of names for the analysis engines in the aggregate. There must be exactly one
   *          name for each analysis engine, given in the same order as the descriptions.
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param flowControllerDescription
   *          the flow controller description to be used by this aggregate (may be null).
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngine(
          List<AnalysisEngineDescription> analysisEngineDescriptions, List<String> componentNames,
          TypePriorities typePriorities, SofaMapping[] sofaMappings,
          FlowControllerDescription flowControllerDescription)
          throws ResourceInitializationException {

    AnalysisEngineDescription desc = createEngineDescription(analysisEngineDescriptions,
            componentNames, typePriorities, sofaMappings, flowControllerDescription);
    // create the AnalysisEngine, initialize it and return it
    AnalysisEngine engine = new AggregateAnalysisEngine_impl();
    engine.initialize(desc, null);
    return engine;
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component descriptions.
   * 
   * @param analysisEngineDescriptions
   *          a list of analysis engine descriptions from which the aggregate engine is instantiated
   * @param componentNames
   *          a list of names for the analysis engines in the aggregate. There must be exactly one
   *          name for each analysis engine, given in the same order as the descriptions.
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param flowControllerDescription
   *          the flow controller description to be used by this aggregate (may be null).
   * @return an {@link AnalysisEngine} created from the specified component class and initialized
   *         with the configuration parameters.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use
   *             {@link #createEngine(List, List, TypePriorities, SofaMapping[], FlowControllerDescription)}
   */
  @Deprecated
  public static AnalysisEngine createAggregate(
          List<AnalysisEngineDescription> analysisEngineDescriptions, List<String> componentNames,
          TypePriorities typePriorities, SofaMapping[] sofaMappings,
          FlowControllerDescription flowControllerDescription)
          throws ResourceInitializationException {
    return createEngine(analysisEngineDescriptions, componentNames, typePriorities, sofaMappings,
            flowControllerDescription);
  }

  /**
   * Get an {@link AnalysisEngine} from an XML descriptor file and a set of configuration
   * parameters.
   * 
   * @param descriptorPath
   *          The path to the XML descriptor file.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return The {@link AnalysisEngine} created from the XML descriptor and the configuration
   *         parameters.
   * @throws IOException
   *           if an I/O error occurs
   * @throws InvalidXMLException
   *           if the input XML is not valid or does not specify a valid {@link ResourceSpecifier}
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   */
  public static AnalysisEngine createEngineFromPath(String descriptorPath,
          Object... configurationData) throws InvalidXMLException, IOException,
          ResourceInitializationException {
    AnalysisEngineDescription desc = createEngineDescriptionFromPath(descriptorPath,
            configurationData);
    return UIMAFramework.produceAnalysisEngine(desc, ResourceManagerFactory.newResourceManager(),
            null);
  }

  /**
   * Get an {@link AnalysisEngine} from an XML descriptor file and a set of configuration
   * parameters.
   * 
   * @param descriptorPath
   *          The path to the XML descriptor file.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return The {@link AnalysisEngine} created from the XML descriptor and the configuration
   *         parameters.
   * @throws IOException
   *           if an I/O error occurs
   * @throws InvalidXMLException
   *           if the input XML is not valid or does not specify a valid {@link ResourceSpecifier}
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @see <a href="package-summary.html#InstancesVsDescriptors">Why are descriptors better than
   *      component instances?</a>
   * @deprecated use {@link #createEngineFromPath(String, Object...)}
   */
  @Deprecated
  public static AnalysisEngine createAnalysisEngineFromPath(String descriptorPath,
          Object... configurationData) throws InvalidXMLException, IOException,
          ResourceInitializationException {
    return createEngineFromPath(descriptorPath, configurationData);
  }

  /**
   * Get an {@link AnalysisEngineDescription} from an XML descriptor file and a set of configuration
   * parameters.
   * 
   * @param descriptorPath
   *          The path to the XML descriptor file.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return The {@link AnalysisEngineDescription} created from the XML descriptor and the
   *         configuration parameters.
   * @throws IOException
   *           if an I/O error occurs
   * @throws InvalidXMLException
   *           if the input XML is not valid or does not specify a valid {@link ResourceSpecifier}
   */
  public static AnalysisEngineDescription createEngineDescriptionFromPath(String descriptorPath,
          Object... configurationData) throws InvalidXMLException, IOException {
    ResourceSpecifier specifier;
    specifier = ResourceCreationSpecifierFactory.createResourceCreationSpecifier(descriptorPath,
            configurationData);
    return (AnalysisEngineDescription) specifier;
  }

  /**
   * Get an {@link AnalysisEngineDescription} from a PEAR and a set of configuration parameters.
   * 
   * @param pearSpecifier
   *          The PEAR specifier.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return The {@link AnalysisEngineDescription} created from the XML descriptor and the
   *         configuration parameters.
   * @throws IOException
   *           if an I/O error occurs
   * @throws InvalidXMLException
   *           if the input XML is not valid or does not specify a valid {@link ResourceSpecifier}
   */
  public static AnalysisEngineDescription createEngineDescription(PearSpecifier pearSpecifier,
          Object... configurationData) throws InvalidXMLException, IOException {
    ConfigurationParameterFactory.ensureParametersComeInPairs(configurationData);
    
    if (configurationData != null) {
      for (int i = 0; i < configurationData.length / 2; i++) {
        String name = (String) configurationData[i * 2];
        String value = (String) configurationData[i * 2 + 1];
        ConfigurationParameterFactory.setParameter(pearSpecifier, name, value);
      }
    }
    
    AnalysisEngineDescription desc = new AnalysisEngineDescription_impl();
    desc.setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
    desc.setPrimitive(false);
    desc.getDelegateAnalysisEngineSpecifiersWithImports().put(pearSpecifier.getPearPath(),
            pearSpecifier);
    
    FixedFlow fixedFlow = new FixedFlow_impl();
    fixedFlow.setFixedFlow(new String[] { pearSpecifier.getPearPath() });
    desc.getAnalysisEngineMetaData().setFlowConstraints(fixedFlow);
    
    return desc;
  }
  /**
   * Get an {@link AnalysisEngineDescription} from an XML descriptor file and a set of configuration
   * parameters.
   * 
   * @param descriptorPath
   *          The path to the XML descriptor file.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return The {@link AnalysisEngineDescription} created from the XML descriptor and the
   *         configuration parameters.
   * @throws IOException
   *           if an I/O error occurs
   * @throws InvalidXMLException
   *           if the input XML is not valid or does not specify a valid {@link ResourceSpecifier}
   * @deprecated use {@link #createEngineDescriptionFromPath(String, Object...)}
   */
  @Deprecated
  public static AnalysisEngineDescription createAnalysisEngineDescriptionFromPath(
          String descriptorPath, Object... configurationData) throws InvalidXMLException,
          IOException {
    return createEngineDescriptionFromPath(descriptorPath, configurationData);
  }

  /**
   * Provides a way to create an AnalysisEngineDescription using a descriptor file referenced by
   * name
   * 
   * @param descriptorName
   *          The fully qualified, Java-style, dotted name of the XML descriptor file.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters. Will override
   *          configuration parameter settings in the descriptor file
   * @return a description for this analysis engine.
   * @throws IOException
   *           if an I/O error occurs
   * @throws InvalidXMLException
   *           if the input XML is not valid or does not specify a valid {@link ResourceSpecifier}
   */
  public static AnalysisEngineDescription createEngineDescription(String descriptorName,
          Object... configurationData) throws InvalidXMLException, IOException {
    Import_impl imprt = new Import_impl();
    imprt.setName(descriptorName);
    URL url;
    try {
      url = imprt.findAbsoluteUrl(ResourceManagerFactory.newResourceManager());
    }
    catch (ResourceInitializationException e) {
      if (e.getCause() instanceof IOException) {
        throw (IOException) e.getCause();
      }
      else {
        throw new IOException(e);
      }
    }
    ResourceSpecifier specifier = ResourceCreationSpecifierFactory.createResourceCreationSpecifier(
            url, configurationData);
    return (AnalysisEngineDescription) specifier;
  }

  /**
   * Provides a way to create an AnalysisEngineDescription using a descriptor file referenced by
   * name
   * 
   * @param descriptorName
   *          The fully qualified, Java-style, dotted name of the XML descriptor file.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters. Will override
   *          configuration parameter settings in the descriptor file
   * @return a description for this analysis engine.
   * @throws IOException
   *           if an I/O error occurs
   * @throws InvalidXMLException
   *           if the input XML is not valid or does not specify a valid {@link ResourceSpecifier}
   * @deprecated use {@link #createEngineDescription(String, Object...)}
   */
  @Deprecated
  public static AnalysisEngineDescription createAnalysisEngineDescription(String descriptorName,
          Object... configurationData) throws InvalidXMLException, IOException {
    return createEngineDescription(descriptorName, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          Class<? extends AnalysisComponent> componentClass, TypeSystemDescription typeSystem,
          Object... configurationData) throws ResourceInitializationException {
    return createEngineDescription(componentClass, typeSystem, (TypePriorities) null,
            configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use {@link #createEngineDescription(Class, TypeSystemDescription, Object...)}
   */
  @Deprecated
  public static AnalysisEngineDescription createPrimitiveDescription(
          Class<? extends AnalysisComponent> componentClass, TypeSystemDescription typeSystem,
          Object... configurationData) throws ResourceInitializationException {
    return createEngineDescription(componentClass, typeSystem, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}. The type system is detected
   * automatically using {@link TypeSystemDescriptionFactory#createTypeSystemDescription()}. Type
   * priorities are detected automatically using
   * {@link TypePrioritiesFactory#createTypePriorities()}. Indexes are detected automatically using
   * {@link FsIndexFactory#createFsIndexCollection()}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          Class<? extends AnalysisComponent> componentClass, Object... configurationData)
          throws ResourceInitializationException {
    TypeSystemDescription typeSystem = createTypeSystemDescription();
    TypePriorities typePriorities = createTypePriorities();
    FsIndexCollection fsIndexCollection = createFsIndexCollection();

    return createEngineDescription(componentClass, typeSystem, typePriorities, fsIndexCollection,
            (Capability[]) null, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}. The type system is detected
   * automatically using {@link TypeSystemDescriptionFactory#createTypeSystemDescription()}. Type
   * priorities are detected automatically using
   * {@link TypePrioritiesFactory#createTypePriorities()}. Indexes are detected automatically using
   * {@link FsIndexFactory#createFsIndexCollection()}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use {@link #createEngineDescription(Class, Object...)}
   */
  @Deprecated
  public static AnalysisEngineDescription createPrimitiveDescription(
          Class<? extends AnalysisComponent> componentClass, Object... configurationData)
          throws ResourceInitializationException {
    return createEngineDescription(componentClass, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          Class<? extends AnalysisComponent> componentClass, TypeSystemDescription typeSystem,
          TypePriorities typePriorities, Object... configurationData)
          throws ResourceInitializationException {
    return createEngineDescription(componentClass, typeSystem, typePriorities,
            (FsIndexCollection) null, (Capability[]) null, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use
   *             {@link #createEngineDescription(Class, TypeSystemDescription, TypePriorities, Object...)}
   */
  @Deprecated
  public static AnalysisEngineDescription createPrimitiveDescription(
          Class<? extends AnalysisComponent> componentClass, TypeSystemDescription typeSystem,
          TypePriorities typePriorities, Object... configurationData)
          throws ResourceInitializationException {
    return createEngineDescription(componentClass, typeSystem, typePriorities, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param indexes
   *          the Feature Structure Index collection used by this analysis engine to iterate over
   *          annotations in the {@link org.apache.uima.cas.CAS}. If this is not null explicitly,
   *          any indexes declared via {@link org.apache.uima.fit.descriptor.FsIndexCollection} in
   *          the class are ignored.
   * @param capabilities
   *          the operations the component can perform in terms of consumed and produced types, sofa
   *          names, and languages. If this is set explicitly here, any capabilities declared via
   *          {@link SofaCapability} or {@link TypeCapability} in the class are ignored.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters. In addition to
   *          parameter names, external resource keys can also be specified. The value has to be an
   *          {@link ExternalResourceDescription} in that case.
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          Class<? extends AnalysisComponent> componentClass, TypeSystemDescription typeSystem,
          TypePriorities typePriorities, FsIndexCollection indexes, Capability[] capabilities,
          Object... configurationData) throws ResourceInitializationException {

    ensureParametersComeInPairs(configurationData);

    // Extract ExternalResourceDescriptions from configurationData
    // <ParamterName, ExternalResourceDescription> will be stored in this map
    Map<String, ExternalResourceDescription> externalResources = ExternalResourceFactory
            .extractResourceParameters(configurationData);

    // Create primitive description normally
    ConfigurationData cdata = createConfigurationData(configurationData);
    return createEngineDescription(componentClass, typeSystem, typePriorities, indexes,
            capabilities, cdata.configurationParameters, cdata.configurationValues,
            externalResources);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param indexes
   *          the Feature Structure Index collection used by this analysis engine to iterate over
   *          annotations in the {@link org.apache.uima.cas.CAS}. If this is not null explicitly,
   *          any indexes declared via {@link org.apache.uima.fit.descriptor.FsIndexCollection} in
   *          the class are ignored.
   * @param capabilities
   *          the operations the component can perform in terms of consumed and produced types, sofa
   *          names, and languages. If this is set explicitly here, any capabilities declared via
   *          {@link SofaCapability} or {@link TypeCapability} in the class are ignored.
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters. In addition to
   *          parameter names, external resource keys can also be specified. The value has to be an
   *          {@link ExternalResourceDescription} in that case.
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use
   *             {@link #createEngineDescription(Class, TypeSystemDescription, TypePriorities, FsIndexCollection, Capability[], Object...)}
   */
  @Deprecated
  public static AnalysisEngineDescription createPrimitiveDescription(
          Class<? extends AnalysisComponent> componentClass, TypeSystemDescription typeSystem,
          TypePriorities typePriorities, FsIndexCollection indexes, Capability[] capabilities,
          Object... configurationData) throws ResourceInitializationException {
    return createEngineDescription(componentClass, typeSystem, typePriorities, indexes,
            capabilities, configurationData);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param indexes
   *          the Feature Structure Index collection used by this analysis engine to iterate over
   *          annotations in the {@link org.apache.uima.cas.CAS}. If this is not null explicitly,
   *          any indexes declared via {@link org.apache.uima.fit.descriptor.FsIndexCollection} in
   *          the class are ignored.
   * @param capabilities
   *          the operations the component can perform in terms of consumed and produced types, sofa
   *          names, and languages. If this is set explicitly here, any capabilities declared via
   *          {@link SofaCapability} or {@link TypeCapability} in the class are ignored.
   * @param configurationParameters
   *          the configuration parameter declarations.
   * @param configurationValues
   *          the configuration parameter values.
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          Class<? extends AnalysisComponent> componentClass, TypeSystemDescription typeSystem,
          TypePriorities typePriorities, FsIndexCollection indexes, Capability[] capabilities,
          ConfigurationParameter[] configurationParameters, Object[] configurationValues)
          throws ResourceInitializationException {
    return createEngineDescription(componentClass, typeSystem, typePriorities, indexes,
            capabilities, configurationParameters, configurationValues, null);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param indexes
   *          the Feature Structure Index collection used by this analysis engine to iterate over
   *          annotations in the {@link org.apache.uima.cas.CAS}. If this is not null explicitly,
   *          any indexes declared via {@link org.apache.uima.fit.descriptor.FsIndexCollection} in
   *          the class are ignored.
   * @param capabilities
   *          the operations the component can perform in terms of consumed and produced types, sofa
   *          names, and languages. If this is set explicitly here, any capabilities declared via
   *          {@link SofaCapability} or {@link TypeCapability} in the class are ignored.
   * @param configurationParameters
   *          the configuration parameter declarations.
   * @param configurationValues
   *          the configuration parameter values.
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use
   *             {@link #createEngineDescription(Class, TypeSystemDescription, TypePriorities, FsIndexCollection, Capability[], ConfigurationParameter[], Object[])}
   */
  @Deprecated
  public static AnalysisEngineDescription createPrimitiveDescription(
          Class<? extends AnalysisComponent> componentClass, TypeSystemDescription typeSystem,
          TypePriorities typePriorities, FsIndexCollection indexes, Capability[] capabilities,
          ConfigurationParameter[] configurationParameters, Object[] configurationValues)
          throws ResourceInitializationException {
    return createEngineDescription(componentClass, typeSystem, typePriorities, indexes,
            capabilities, configurationParameters, configurationValues);
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param indexes
   *          the Feature Structure Index collection used by this analysis engine to iterate over
   *          annotations in the {@link org.apache.uima.cas.CAS}. If this is set explicitly here,
   *          any indexes declared via {@link org.apache.uima.fit.descriptor.FsIndexCollection} in
   *          the class are ignored.
   * @param capabilities
   *          the operations the component can perform in terms of consumed and produced types, sofa
   *          names, and languages. If this is set explicitly here, any capabilities declared via
   *          {@link SofaCapability} or {@link TypeCapability} in the class are ignored.
   * @param configurationParameters
   *          the configuration parameter declarations.
   * @param configurationValues
   *          the configuration parameter values.
   * @param externalResources
   *          external resources to bind to the analysis engine. (may be null)
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          Class<? extends AnalysisComponent> componentClass, TypeSystemDescription typeSystem,
          TypePriorities typePriorities, FsIndexCollection indexes, Capability[] capabilities,
          ConfigurationParameter[] configurationParameters, Object[] configurationValues,
          Map<String, ExternalResourceDescription> externalResources)
          throws ResourceInitializationException {

    // create the descriptor and set configuration parameters
    AnalysisEngineDescription desc = UIMAFramework.getResourceSpecifierFactory()
            .createAnalysisEngineDescription();
    desc.setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
    desc.setPrimitive(true);
    desc.setAnnotatorImplementationName(componentClass.getName());
    org.apache.uima.fit.descriptor.OperationalProperties componentAnno = ReflectionUtil
            .getInheritableAnnotation(org.apache.uima.fit.descriptor.OperationalProperties.class,
                    componentClass);
    if (componentAnno != null) {
      OperationalProperties op = desc.getAnalysisEngineMetaData().getOperationalProperties();
      op.setMultipleDeploymentAllowed(componentAnno.multipleDeploymentAllowed());
      op.setModifiesCas(componentAnno.modifiesCas());
      op.setOutputsNewCASes(componentAnno.outputsNewCases());
    } else {
      OperationalProperties op = desc.getAnalysisEngineMetaData().getOperationalProperties();
      op.setMultipleDeploymentAllowed(MULTIPLE_DEPLOYMENT_ALLOWED_DEFAULT);
      op.setModifiesCas(MODIFIES_CAS_DEFAULT);
      op.setOutputsNewCASes(OUTPUTS_NEW_CASES_DEFAULT);
    }

    // Configure resource meta data
    AnalysisEngineMetaData meta = desc.getAnalysisEngineMetaData();
    ResourceMetaDataFactory.configureResourceMetaData(meta, componentClass);

    // set parameters
    setParameters(desc, componentClass, configurationParameters, configurationValues);

    // set the type system
    if (typeSystem != null) {
      desc.getAnalysisEngineMetaData().setTypeSystem(typeSystem);
    }

    if (typePriorities != null) {
      desc.getAnalysisEngineMetaData().setTypePriorities(typePriorities);
    }

    // set indexes from the argument to this call and from the annotation present in the
    // component
    List<FsIndexCollection> fsIndexes = new ArrayList<FsIndexCollection>();
    if (indexes != null) {
      fsIndexes.add(indexes);
    }
    fsIndexes.add(FsIndexFactory.createFsIndexCollection(componentClass));
    FsIndexCollection aggIndexColl = CasCreationUtils.mergeFsIndexes(fsIndexes,
            ResourceManagerFactory.newResourceManager());
    desc.getAnalysisEngineMetaData().setFsIndexCollection(aggIndexColl);

    // set capabilities from the argument to this call or from the annotation present in the
    // component if the argument is null
    if (capabilities != null) {
      desc.getAnalysisEngineMetaData().setCapabilities(capabilities);
    } else {
      Capability capability = CapabilityFactory.createCapability(componentClass);
      if (capability != null) {
        desc.getAnalysisEngineMetaData().setCapabilities(new Capability[] { capability });
      }
    }

    // Extract external resource dependencies
    desc.setExternalResourceDependencies(createResourceDependencies(componentClass));

    // Bind External Resources
    if (externalResources != null) {
      for (Entry<String, ExternalResourceDescription> e : externalResources.entrySet()) {
        bindResource(desc, e.getKey(), e.getValue());
      }
    }

    return desc;
  }

  /**
   * Create and configure a primitive {@link AnalysisEngine}.
   * 
   * @param componentClass
   *          a class that extends {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param indexes
   *          the Feature Structure Index collection used by this analysis engine to iterate over
   *          annotations in the {@link org.apache.uima.cas.CAS}. If this is set explicitly here,
   *          any indexes declared via {@link org.apache.uima.fit.descriptor.FsIndexCollection} in
   *          the class are ignored.
   * @param capabilities
   *          the operations the component can perform in terms of consumed and produced types, sofa
   *          names, and languages. If this is set explicitly here, any capabilities declared via
   *          {@link SofaCapability} or {@link TypeCapability} in the class are ignored.
   * @param configurationParameters
   *          the configuration parameter declarations.
   * @param configurationValues
   *          the configuration parameter values.
   * @param externalResources
   *          external resources to bind to the analysis engine. (may be null)
   * @return a description for this analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use
   *             {@link #createEngineDescription(Class, TypeSystemDescription, TypePriorities, FsIndexCollection, Capability[], ConfigurationParameter[], Object[], Map)}
   */
  @Deprecated
  public static AnalysisEngineDescription createPrimitiveDescription(
          Class<? extends AnalysisComponent> componentClass, TypeSystemDescription typeSystem,
          TypePriorities typePriorities, FsIndexCollection indexes, Capability[] capabilities,
          ConfigurationParameter[] configurationParameters, Object[] configurationValues,
          Map<String, ExternalResourceDescription> externalResources)
          throws ResourceInitializationException {
    return createEngineDescription(componentClass, typeSystem, typePriorities, indexes,
            capabilities, configurationParameters, configurationValues, externalResources);
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component classes.
   * 
   * @param componentClasses
   *          a list of class that extend {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return a description for this aggregate analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          List<Class<? extends AnalysisComponent>> componentClasses,
          TypeSystemDescription typeSystem, TypePriorities typePriorities,
          SofaMapping[] sofaMappings, Object... configurationData)
          throws ResourceInitializationException {

    List<AnalysisEngineDescription> primitiveEngineDescriptions = new ArrayList<AnalysisEngineDescription>();
    List<String> componentNames = new ArrayList<String>();

    for (Class<? extends AnalysisComponent> componentClass : componentClasses) {
      AnalysisEngineDescription primitiveDescription = createEngineDescription(componentClass,
              typeSystem, typePriorities, configurationData);
      primitiveEngineDescriptions.add(primitiveDescription);
      componentNames.add(componentClass.getName());
    }
    return createEngineDescription(primitiveEngineDescriptions, componentNames, typePriorities,
            sofaMappings, null);
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component classes.
   * 
   * @param componentClasses
   *          a list of class that extend {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return a description for this aggregate analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use
   *             {@link #createEngineDescription(List, TypeSystemDescription, TypePriorities, SofaMapping[], Object...)}
   */
  @Deprecated
  public static AnalysisEngineDescription createAggregateDescription(
          List<Class<? extends AnalysisComponent>> componentClasses,
          TypeSystemDescription typeSystem, TypePriorities typePriorities,
          SofaMapping[] sofaMappings, Object... configurationData)
          throws ResourceInitializationException {
    return createEngineDescription(componentClasses, typeSystem, typePriorities, sofaMappings,
            configurationData);
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component descriptions.
   * 
   * @param analysisEngineDescriptions
   *          a list of analysis engine descriptions from which the aggregate engine is instantiated
   * @return a description for this aggregate analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          AnalysisEngineDescription... analysisEngineDescriptions)
          throws ResourceInitializationException {
    String[] names = new String[analysisEngineDescriptions.length];
    int i = 0;
    for (AnalysisEngineDescription aed : analysisEngineDescriptions) {
      names[i] = aed.getImplementationName() + "-" + i;
      i++;
    }

    return createEngineDescription(asList(analysisEngineDescriptions), asList(names), null, null,
            null);
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component descriptions.
   * 
   * @param analysisEngineDescriptions
   *          a list of analysis engine descriptions from which the aggregate engine is instantiated
   * @return a description for this aggregate analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use {@link #createEngineDescription(AnalysisEngineDescription...)}
   */
  @Deprecated
  public static AnalysisEngineDescription createAggregateDescription(
          AnalysisEngineDescription... analysisEngineDescriptions)
          throws ResourceInitializationException {
    return createEngineDescription(analysisEngineDescriptions);
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component classes.
   * 
   * @param componentClasses
   *          a list of class that extend {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param flowControllerDescription
   *          the flow controller description to be used by this aggregate (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return a description for this aggregate analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          List<Class<? extends AnalysisComponent>> componentClasses,
          TypeSystemDescription typeSystem, TypePriorities typePriorities,
          SofaMapping[] sofaMappings, FlowControllerDescription flowControllerDescription,
          Object... configurationData) throws ResourceInitializationException {

    List<AnalysisEngineDescription> primitiveEngineDescriptions = new ArrayList<AnalysisEngineDescription>();
    List<String> componentNames = new ArrayList<String>();

    for (Class<? extends AnalysisComponent> componentClass : componentClasses) {
      AnalysisEngineDescription primitiveDescription = createEngineDescription(componentClass,
              typeSystem, typePriorities, configurationData);
      primitiveEngineDescriptions.add(primitiveDescription);
      componentNames.add(componentClass.getName());
    }
    return createEngineDescription(primitiveEngineDescriptions, componentNames, typePriorities,
            sofaMappings, flowControllerDescription);
  }

  /**
   * Create and configure an aggregate {@link AnalysisEngine} from several component classes.
   * 
   * @param componentClasses
   *          a list of class that extend {@link AnalysisComponent} e.g. via
   *          {@link org.apache.uima.fit.component.JCasAnnotator_ImplBase}
   * @param typeSystem
   *          A description of the types (may be null).
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param flowControllerDescription
   *          the flow controller description to be used by this aggregate (may be null).
   * @param configurationData
   *          Any additional configuration parameters to be set. These should be supplied as (name,
   *          value) pairs, so there should always be an even number of parameters.
   * @return a description for this aggregate analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use
   *             {@link #createEngineDescription(List, TypeSystemDescription, TypePriorities, SofaMapping[], FlowControllerDescription, Object...)}
   */
  @Deprecated
  public static AnalysisEngineDescription createAggregateDescription(
          List<Class<? extends AnalysisComponent>> componentClasses,
          TypeSystemDescription typeSystem, TypePriorities typePriorities,
          SofaMapping[] sofaMappings, FlowControllerDescription flowControllerDescription,
          Object... configurationData) throws ResourceInitializationException {
    return createEngineDescription(componentClasses, typeSystem, typePriorities, sofaMappings,
            flowControllerDescription, configurationData);
  }

  /**
   * A simplified factory method for creating an aggregate description for a given flow controller
   * and a sequence of analysis engine descriptions
   * 
   * @param flowControllerDescription
   *          the flow controller description to be used by this aggregate (may be null).
   * @param analysisEngineDescriptions
   *          a list of analysis engine descriptions from which the aggregate engine is instantiated
   * @return a description for this aggregate analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          FlowControllerDescription flowControllerDescription,
          AnalysisEngineDescription... analysisEngineDescriptions)
          throws ResourceInitializationException {
    String[] names = new String[analysisEngineDescriptions.length];
    int i = 0;
    for (AnalysisEngineDescription aed : analysisEngineDescriptions) {
      names[i] = aed.getImplementationName() + "-" + i;
      i++;
    }

    return createEngineDescription(asList(analysisEngineDescriptions), asList(names), null, null,
            flowControllerDescription);
  }

  /**
   * A simplified factory method for creating an aggregate description for a given flow controller
   * and a sequence of analysis engine descriptions
   * 
   * @param flowControllerDescription
   *          the flow controller description to be used by this aggregate (may be null).
   * @param analysisEngineDescriptions
   *          a list of analysis engine descriptions from which the aggregate engine is instantiated
   * @return a description for this aggregate analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use
   *             {@link #createEngineDescription(FlowControllerDescription, AnalysisEngineDescription...)}
   */
  @Deprecated
  public static AnalysisEngineDescription createAggregateDescription(
          FlowControllerDescription flowControllerDescription,
          AnalysisEngineDescription... analysisEngineDescriptions)
          throws ResourceInitializationException {
    return createEngineDescription(flowControllerDescription, analysisEngineDescriptions);
  }

  /**
   * A factory method for creating an aggregate description.
   * 
   * @param analysisEngineDescriptions
   *          list of analysis engine descriptions.
   * @param componentNames
   *          list of component names - must be one name per description!
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param flowControllerDescription
   *          the flow controller description to be used by this aggregate (may be null).
   * @return a description for this aggregate analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   */
  public static AnalysisEngineDescription createEngineDescription(
          List<AnalysisEngineDescription> analysisEngineDescriptions, List<String> componentNames,
          TypePriorities typePriorities, SofaMapping[] sofaMappings,
          FlowControllerDescription flowControllerDescription)
          throws ResourceInitializationException {

    if (componentNames == null) {
      throw new IllegalArgumentException("Parameter [componentNames] cannot be null");
    }

    if (analysisEngineDescriptions == null) {
      throw new IllegalArgumentException("Parameter [analysisEngineDescriptions] cannot be null");
    }

    if (analysisEngineDescriptions.size() != componentNames.size()) {
      throw new IllegalArgumentException("Number of descriptions ["
              + analysisEngineDescriptions.size() + "]does not match number of component names ["
              + componentNames.size() + "].");
    }

    // create the descriptor and set configuration parameters
    AnalysisEngineDescription desc = new AnalysisEngineDescription_impl();
    desc.setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
    desc.setPrimitive(false);

    // if any of the aggregated analysis engines does not allow multiple
    // deployment, then the
    // aggregate engine may also not be multiply deployed
    boolean allowMultipleDeploy = true;
    for (AnalysisEngineDescription d : analysisEngineDescriptions) {
      allowMultipleDeploy &= d.getAnalysisEngineMetaData().getOperationalProperties()
              .isMultipleDeploymentAllowed();
    }
    desc.getAnalysisEngineMetaData().getOperationalProperties()
            .setMultipleDeploymentAllowed(allowMultipleDeploy);

    List<String> flowNames = new ArrayList<String>();

    for (int i = 0; i < analysisEngineDescriptions.size(); i++) {
      AnalysisEngineDescription aed = analysisEngineDescriptions.get(i);
      String componentName = componentNames.get(i);
      desc.getDelegateAnalysisEngineSpecifiersWithImports().put(componentName, aed);
      flowNames.add(componentName);
    }

    if (flowControllerDescription != null) {
      FlowControllerDeclaration flowControllerDeclaration = new FlowControllerDeclaration_impl();
      flowControllerDeclaration.setSpecifier(flowControllerDescription);
      desc.setFlowControllerDeclaration(flowControllerDeclaration);
    }

    FixedFlow fixedFlow = new FixedFlow_impl();
    fixedFlow.setFixedFlow(flowNames.toArray(new String[flowNames.size()]));
    desc.getAnalysisEngineMetaData().setFlowConstraints(fixedFlow);

    if (typePriorities != null) {
      desc.getAnalysisEngineMetaData().setTypePriorities(typePriorities);
    }

    if (sofaMappings != null) {
      desc.setSofaMappings(sofaMappings);
    }

    return desc;
  }

  /**
   * A factory method for creating an aggregate description.
   * 
   * @param analysisEngineDescriptions
   *          list of analysis engine descriptions.
   * @param componentNames
   *          list of component names - must be one name per description!
   * @param typePriorities
   *          The type priorities (may be null).
   * @param sofaMappings
   *          The SofA mappings (may be null).
   * @param flowControllerDescription
   *          the flow controller description to be used by this aggregate (may be null).
   * @return a description for this aggregate analysis engine.
   * @throws ResourceInitializationException
   *           if a failure occurred during production of the resource.
   * @deprecated use
   *             {@link #createEngine(List, List, TypePriorities, SofaMapping[], FlowControllerDescription)}
   */
  @Deprecated
  public static AnalysisEngineDescription createAggregateDescription(
          List<AnalysisEngineDescription> analysisEngineDescriptions, List<String> componentNames,
          TypePriorities typePriorities, SofaMapping[] sofaMappings,
          FlowControllerDescription flowControllerDescription)
          throws ResourceInitializationException {
    return createEngineDescription(analysisEngineDescriptions, componentNames, typePriorities,
            sofaMappings, flowControllerDescription);
  }
}
