You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2008/08/30 00:11:30 UTC

svn commit: r690405 [3/26] - in /incubator/uima/uimaj/trunk/uimaj-core: ./ src/main/java/org/apache/uima/ src/main/java/org/apache/uima/analysis_component/ src/main/java/org/apache/uima/analysis_engine/ src/main/java/org/apache/uima/analysis_engine/ann...

Modified: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java
URL: http://svn.apache.org/viewvc/incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java?rev=690405&r1=690404&r2=690405&view=diff
==============================================================================
--- incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java (original)
+++ incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java Fri Aug 29 15:10:52 2008
@@ -1,944 +1,944 @@
-/*
- * 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.analysis_engine.impl;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.apache.uima.Constants;
-import org.apache.uima.UIMAFramework;
-import org.apache.uima.analysis_engine.AnalysisEngine;
-import org.apache.uima.analysis_engine.AnalysisEngineDescription;
-import org.apache.uima.analysis_engine.metadata.AnalysisEngineMetaData;
-import org.apache.uima.analysis_engine.metadata.CapabilityLanguageFlow;
-import org.apache.uima.analysis_engine.metadata.FixedFlow;
-import org.apache.uima.analysis_engine.metadata.FlowConstraints;
-import org.apache.uima.analysis_engine.metadata.FlowControllerDeclaration;
-import org.apache.uima.analysis_engine.metadata.SofaMapping;
-import org.apache.uima.analysis_engine.metadata.impl.AnalysisEngineMetaData_impl;
-import org.apache.uima.cas.CAS;
-import org.apache.uima.resource.ResourceConfigurationException;
-import org.apache.uima.resource.ResourceCreationSpecifier;
-import org.apache.uima.resource.ResourceInitializationException;
-import org.apache.uima.resource.ResourceManager;
-import org.apache.uima.resource.ResourceSpecifier;
-import org.apache.uima.resource.impl.ResourceCreationSpecifier_impl;
-import org.apache.uima.resource.metadata.Capability;
-import org.apache.uima.resource.metadata.ConfigurationParameter;
-import org.apache.uima.resource.metadata.ConfigurationParameterDeclarations;
-import org.apache.uima.resource.metadata.Import;
-import org.apache.uima.resource.metadata.OperationalProperties;
-import org.apache.uima.resource.metadata.impl.Import_impl;
-import org.apache.uima.resource.metadata.impl.PropertyXmlInfo;
-import org.apache.uima.resource.metadata.impl.XmlizationInfo;
-import org.apache.uima.util.InvalidXMLException;
-import org.apache.uima.util.Level;
-import org.apache.uima.util.NameClassPair;
-import org.apache.uima.util.XMLInputSource;
-import org.apache.uima.util.XMLParser;
-import org.apache.uima.util.XMLParser.ParsingOptions;
-import org.w3c.dom.Element;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
-/**
- * Reference implementation of {@link AnalysisEngineDescription}. Note that this class contains two
- * attributes of class Map, which are not supported by the default XML input/output routines.
- * Therefore we override the {@link #writeAttributeAsElement(String,Class,Object,Writer)} and
- * {@link #readAttributeFromXMLElement(String,Class,Element,XMLParser)} methods.
- * 
- * 
- */
-public class AnalysisEngineDescription_impl extends ResourceCreationSpecifier_impl implements
-        AnalysisEngineDescription {
-
-  /**
-   * resource bundle for log messages
-   */
-  private static final String LOG_RESOURCE_BUNDLE = "org.apache.uima.impl.log_messages";
-
-  /**
-   * Name of the "delegateAnalysisEngineSpecifiers" property. Change this if interface changes.
-   */
-  protected String PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS = "delegateAnalysisEngineSpecifiers";
-
-  /**
-   * Name of the "delegateAnalysisEngineSpecifiersWithImports" property. Change this if interface
-   * changes.
-   */
-  protected String PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS = "delegateAnalysisEngineSpecifiersWithImports";
-
-  /**
-   * Name of the "delegateAnalysisEngineSpecifiers" XML Element. Change this if schema changes.
-   */
-  protected String ELEM_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS = "delegateAnalysisEngineSpecifiers";
-
-  private String mFrameworkImplementation;
-
-  private boolean mPrimitive;
-
-  private FlowControllerDeclaration mFlowControllerDeclaration;
-
-  private Map mDelegateAnalysisEngineSpecifiers = new HashMap();
-
-  private Map mDelegateAnalysisEngineSpecifiersWithImports = new HashMap();
-
-  private Map mProcessedImports = new HashMap();
-
-  private SofaMapping[] mSofaMappings;
-
-  static final long serialVersionUID = -8103625125291855592L;
-
-  /**
-   * Creates a new AnalysisEngineDescription_impl. Initializes the MetaData,
-   * DelegateAnalysisEngineSpecifiers, and ExternalResourcesRequired attributes.
-   */
-  public AnalysisEngineDescription_impl() {
-    setMetaData(new AnalysisEngineMetaData_impl());
-    setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
-    // Set default operational properties. These are used if the
-    // descriptor is constructed programatically, rather than parsed.
-    OperationalProperties opProps = UIMAFramework.getResourceSpecifierFactory()
-            .createOperationalProperties();
-    opProps.setModifiesCas(true);
-    opProps.setMultipleDeploymentAllowed(true);
-    opProps.setOutputsNewCASes(false);
-    getAnalysisEngineMetaData().setOperationalProperties(opProps);
-  }
-
-  /**
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getFrameworkImplementation()
-   */
-  public String getFrameworkImplementation() {
-    return mFrameworkImplementation;
-  }
-
-  /**
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#setFrameworkImplementation(java.lang.String)
-   */
-  public void setFrameworkImplementation(String aFrameworkImplementation) {
-    mFrameworkImplementation = aFrameworkImplementation;
-  }
-
-  /**
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#isPrimitive()
-   */
-  public boolean isPrimitive() {
-    return mPrimitive;
-  }
-
-  /**
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#setPrimitive(boolean)
-   */
-  public void setPrimitive(boolean aPrimitive) {
-    mPrimitive = aPrimitive;
-  }
-
-  /**
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getAnnotatorImplementationName()
-   */
-  public String getAnnotatorImplementationName() {
-    return getImplementationName();
-  }
-
-  /**
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#setAnnotatorImplementationName(String)
-   */
-  public void setAnnotatorImplementationName(String aImplementationName) {
-    setImplementationName(aImplementationName);
-  }
-
-  /**
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getDelegateAnalysisEngineSpecifiers()
-   */
-  public Map getDelegateAnalysisEngineSpecifiers() throws InvalidXMLException {
-    resolveDelegateAnalysisEngineImports(UIMAFramework.newDefaultResourceManager(), false);
-    return Collections.unmodifiableMap(mDelegateAnalysisEngineSpecifiers);
-  }
-
-  /**
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getDelegateAnalysisEngineSpecifiers()
-   */
-  public Map getDelegateAnalysisEngineSpecifiers(ResourceManager aResourceManager)
-          throws InvalidXMLException {
-    resolveDelegateAnalysisEngineImports(aResourceManager, false);
-    return Collections.unmodifiableMap(mDelegateAnalysisEngineSpecifiers);
-  }
-
-  /**
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getDelegateAnalysisEngineSpecifiers()
-   */
-  public Map getDelegateAnalysisEngineSpecifiersWithImports() {
-    return mDelegateAnalysisEngineSpecifiersWithImports;
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getFlowControllerDeclaration()
-   */
-  public FlowControllerDeclaration getFlowControllerDeclaration() {
-    return mFlowControllerDeclaration;
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#setFlowController(org.apache.uima.analysis_engine.metadata.FlowControllerDeclaration)
-   */
-  public void setFlowControllerDeclaration(FlowControllerDeclaration aFlowControllerDeclaration) {
-    mFlowControllerDeclaration = aFlowControllerDeclaration;
-  }
-
-  public Map getAllComponentSpecifiers(ResourceManager aResourceManager) throws InvalidXMLException {
-    if (aResourceManager == null) {
-      aResourceManager = UIMAFramework.newDefaultResourceManager();
-    }
-    resolveImports(aResourceManager);
-    Map map = new HashMap(mDelegateAnalysisEngineSpecifiers);
-    if (getFlowControllerDeclaration() != null) {
-      map.put(getFlowControllerDeclaration().getKey(), getFlowControllerDeclaration()
-              .getSpecifier());
-    }
-    return Collections.unmodifiableMap(map);
-  }
-
-  /**
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getAnalysisEngineMetaData()
-   */
-  public AnalysisEngineMetaData getAnalysisEngineMetaData() {
-    return (AnalysisEngineMetaData) getMetaData();
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getSofaMappings()
-   */
-  public SofaMapping[] getSofaMappings() {
-    return mSofaMappings;
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#setSofaMappings(org.apache.uima.analysis_engine.metadata.SofaMapping[])
-   */
-  public void setSofaMappings(SofaMapping[] aSofaMappings) {
-    mSofaMappings = aSofaMappings;
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#doFullValidation()
-   */
-  public void doFullValidation() throws ResourceInitializationException {
-    // attempt to instantiate AE in "verification mode"
-    Map m = new HashMap();
-    m.put(AnalysisEngineImplBase.PARAM_VERIFICATION_MODE, Boolean.TRUE);
-    AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(this, m);
-    validateSofaMappings();
-    ae.newCAS();
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#doFullValidation(org.apache.uima.resource.ResourceManager)
-   */
-  public void doFullValidation(ResourceManager aResourceManager)
-          throws ResourceInitializationException {
-    // attempt to instantiate AE in "verification mode"
-    Map m = new HashMap();
-    m.put(AnalysisEngineImplBase.PARAM_VERIFICATION_MODE, Boolean.TRUE);
-    AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(this, aResourceManager, m);
-    validateSofaMappings();
-    ae.newCAS();
-  }
-
-  /**
-   * Determines if the AnalysisEngineDescription is valid. An exception is thrown if it is not
-   * valid. This should be called from this Analysis Engine's initialize method. Note this does not
-   * check configuration parameter settings - that must be done by an explicit call to
-   * validateConfigurationParameterSettings.
-   * 
-   * @param aResourceManager
-   *          a ResourceManager instance to use to resolve imports by name.
-   *  
-   * @throws ResourceInitializationException
-   *           if <code>aDesc</code> is invalid
-   * @throws ResourceConfigurationException
-   *           if the configuration parameter settings in <code>aDesc</code> are invalid
-   */
-  public void validate(ResourceManager aResourceManager) throws ResourceInitializationException, ResourceConfigurationException {
-    // do validation common to all descriptor types (e.g. config parameters)
-    super.validate(aResourceManager);
-
-    // TypeSystem may not be specified for an Aggregate Analysis Engine
-    if (!isPrimitive() && getAnalysisEngineMetaData().getTypeSystem() != null) {
-      throw new ResourceInitializationException(
-              ResourceInitializationException.AGGREGATE_AE_TYPE_SYSTEM,
-              new Object[] { getSourceUrlString() });
-    }
-    
-    //Keys in FixedFlow or LanguageCapabilityFlow must be defined
-    FlowConstraints fc = getAnalysisEngineMetaData().getFlowConstraints();
-    String[] keys = null;
-    if (fc instanceof FixedFlow) {
-      keys = ((FixedFlow)fc).getFixedFlow();
-    }
-    else if (fc instanceof CapabilityLanguageFlow) {
-      keys = ((CapabilityLanguageFlow)fc).getCapabilityLanguageFlow();
-    }
-    if (keys != null) {
-      for (int i = 0; i < keys.length; i++) {
-        if (!getDelegateAnalysisEngineSpecifiersWithImports().containsKey(keys[i])) {
-          throw new ResourceInitializationException(ResourceInitializationException.UNDEFINED_KEY_IN_FLOW,
-                  new Object[]{getAnalysisEngineMetaData().getName(), keys[i], getSourceUrlString()});
-        }
-      }
-    }
-  }
-
-  /**
-   * Overrides{@link ResourceCreationSpecifier_impl#checkForInvalidParameterOverrides(ConfigurationParameter[], String)
-   * to validate parameter overrides in an aggregate AE. Also logs a warning for aggregate
-   * parameters with no declared overrides.
-   * 
-   * @param aParams
-   *          an array of ConfigurationParameters
-   * @param aGroupName
-   *          name of groups in which these parameters are contained. Null if no group
-   * @param aResourceManager
-   *          a ResourceManager instance to use to resolve imports by name.
-   *           
-   * @throws ResourceInitializationException
-   *           if there is an invalid parameter override declaration
-   */
-  protected void checkForInvalidParameterOverrides(ConfigurationParameter[] aParams,
-          String aGroupName, ResourceManager aResourceManager) throws ResourceInitializationException {
-    //make sure delegate analysis engine specifiers are resolved using the correct resource manager
-    try {
-      resolveImports(aResourceManager);
-    } catch (InvalidXMLException e) {
-      throw new ResourceInitializationException(e);
-    }
-    
-    for (int i = 0; i < aParams.length; i++) {
-      String[] overrides = aParams[i].getOverrides();
-      if (overrides.length > 0 && isPrimitive()) {
-        throw new ResourceInitializationException(
-                ResourceInitializationException.PARAM_OVERRIDE_IN_PRIMITIVE, new Object[] {
-                    aParams[i].getName(), getMetaData().getName(), getSourceUrlString() });
-      } else if (overrides.length == 0 && !isPrimitive()) {
-        UIMAFramework.getLogger(this.getClass()).logrb(Level.WARNING, this.getClass().getName(),
-                "checkForInvalidParameterOverrides", LOG_RESOURCE_BUNDLE,
-                "UIMA_aggregate_param_no_overrides__WARNING",
-                new Object[] { getMetaData().getName(), aParams[i].getName() });
-      }
-      for (int j = 0; j < overrides.length; j++) {
-        // overrides should be of form delegateKey/paramName
-        int slashPos = overrides[j].indexOf('/');
-        if (slashPos <= 0 || slashPos >= overrides[j].length()) {
-          throw new ResourceInitializationException(
-                  ResourceInitializationException.INVALID_PARAM_OVERRIDE_SYNTAX, new Object[] {
-                      overrides[j], aParams[i].getName(), getMetaData().getName(),
-                      getSourceUrlString() });
-        }
-        String delegateKey = overrides[j].substring(0, slashPos);
-        String paramName = overrides[j].substring(slashPos + 1);
-        // get component descriptor (could be an AE or could be the FlowController)
-        ResourceSpecifier componentSpecifier = getComponentSpecifier(delegateKey);
-        if (componentSpecifier == null) {
-          throw new ResourceInitializationException(
-                  ResourceInitializationException.INVALID_PARAM_OVERRIDE_NONEXISTENT_DELEGATE,
-                  new Object[] { overrides[j], aParams[i].getName(), getMetaData().getName(),
-                      delegateKey, getSourceUrlString() });
-        }
-        if (componentSpecifier instanceof ResourceCreationSpecifier) {
-          ConfigurationParameter overriddenParam = null;
-          ConfigurationParameterDeclarations delegateParamDecls = ((ResourceCreationSpecifier) componentSpecifier)
-                  .getMetaData().getConfigurationParameterDeclarations();
-          if (aGroupName == null) // param not in group
-          {
-            overriddenParam = delegateParamDecls.getConfigurationParameter(null, paramName);
-            if (overriddenParam == null) {
-              throw new ResourceInitializationException(
-                      ResourceInitializationException.INVALID_PARAM_OVERRIDE_NONEXISTENT_PARAMETER,
-                      new Object[] { overrides[j], aParams[i].getName(), getMetaData().getName(),
-                          delegateKey, paramName, getSourceUrlString() });
-
-            }
-          } else {
-            // make sure parameter exists in group
-            overriddenParam = delegateParamDecls.getConfigurationParameter(aGroupName, paramName);
-            if (overriddenParam == null) {
-              throw new ResourceInitializationException(
-                      ResourceInitializationException.INVALID_PARAM_OVERRIDE_NONEXISTENT_PARAMETER_IN_GROUP,
-                      new Object[] { overrides[j], aParams[i].getName(), getMetaData().getName(),
-                          delegateKey, paramName, aGroupName, getSourceUrlString() });
-            }
-          }
-        }
-      }
-    }
-  }
-
-  /**
-   * Gets the ResourceSpecifier of one a component of this aggregate, based on its key. This may be
-   * the specifier of a component (i.e. delegate) AnalysisEngine, or it may be the specifier of the
-   * FlowController.
-   * 
-   * @param key
-   *          the key of the component specifier to get
-   * @return the specifier for the component, null if there is no component with the given key
-   * @throws ResourceInitializationException
-   *           if there's a problem resolving imports
-   */
-  public ResourceSpecifier getComponentSpecifier(String key) throws ResourceInitializationException {
-    ResourceSpecifier componentSpecifier;
-    if (getFlowControllerDeclaration() != null
-            && key.equals(getFlowControllerDeclaration().getKey())) {
-      try {
-        getFlowControllerDeclaration().resolveImports();
-      } catch (InvalidXMLException e) {
-        throw new ResourceInitializationException(e);
-      }
-      componentSpecifier = getFlowControllerDeclaration().getSpecifier();
-    } else {
-      try {
-        componentSpecifier = (ResourceSpecifier) getDelegateAnalysisEngineSpecifiers().get(key);
-      } catch (InvalidXMLException e) {
-        throw new ResourceInitializationException(e);
-      }
-    }
-    return componentSpecifier;
-  }
-
-  /**
-   * Validate SofA mappings and inputs/outputs for an aggregate AE.
-   * 
-   * @param aDesc
-   */
-  protected void validateSofaMappings() throws ResourceInitializationException {
-    if (this.isPrimitive())
-      return;
-    String aggName = this.getAnalysisEngineMetaData().getName();
-    // build an actual Map (key: componentKey@/@componentSofa) from the sofa mappings
-    // along the way check that all component keys and component sofa names exist
-    Map sofamap = new TreeMap();
-    SofaMapping[] sofaMappings = this.getSofaMappings();
-    if (sofaMappings != null) {
-      for (int s = 0; s < sofaMappings.length; s++) {
-        String componentKey = sofaMappings[s].getComponentKey();
-        ResourceSpecifier componentSpec = getComponentSpecifier(componentKey);
-        if (componentSpec == null) {
-          throw new ResourceInitializationException(
-                  ResourceInitializationException.SOFA_MAPPING_HAS_UNDEFINED_COMPONENT_KEY,
-                  new Object[] { componentKey, sofaMappings[s].getAggregateSofaName(), aggName,
-                      getSourceUrlString() });
-        }
-        String componentSofaName = sofaMappings[s].getComponentSofaName();
-        if (componentSofaName == null) {
-          componentSofaName = CAS.NAME_DEFAULT_SOFA;
-        } else if (componentSpec instanceof AnalysisEngineDescription
-                && !CAS.NAME_DEFAULT_SOFA.equals(componentSofaName)
-                && !declaresSofa((AnalysisEngineDescription) componentSpec, componentSofaName)) {
-          throw new ResourceInitializationException(
-                  ResourceInitializationException.SOFA_MAPPING_HAS_UNDEFINED_COMPONENT_SOFA,
-                  new Object[] { componentKey, componentSofaName,
-                      sofaMappings[s].getAggregateSofaName(), aggName, getSourceUrlString() });
-        }
-
-        String compoundKey = sofaMappings[s].getComponentKey() + "@/@"
-                + sofaMappings[s].getComponentSofaName();
-        String aggSofaName = sofaMappings[s].getAggregateSofaName();
-        // check for double-mapping
-        String existingMapping = (String) sofamap.get(compoundKey);
-        if (existingMapping != null && !existingMapping.equals(aggSofaName)) {
-          throw new ResourceInitializationException(
-                  ResourceInitializationException.SOFA_MAPPING_CONFLICT, new Object[] {
-                      sofaMappings[s].getComponentSofaName(), sofaMappings[s].getComponentKey(),
-                      aggName, existingMapping, aggSofaName, getSourceUrlString() });
-        } else {
-          sofamap.put(compoundKey, aggSofaName);
-        }
-      }
-    }
-
-    // Rules for SofAs:
-    // (1) Each component output sofa must be mapped to an aggregate output sofa
-    // (2) Each aggregate output sofa must be mapped to a component output sofa
-    // (3) Each component input sofa must be mapped to an aggregate input sofa OR a component output
-    // sofa
-    // (4) Each aggregate input sofa must be mapped to a component input sofa
-
-    // From (1) and (3) we derive that:
-    // Each component input sofa must be mapped to an aggregate input sofa OR an aggregate output
-    // sofa
-    // (which is easier to check)
-
-    // Exception: if aggregate contains a remote component, we cannot check that remote
-    // component's input or output sofas, so rules (2) and (4) cannot be checked.
-
-    boolean containsRemote = false;
-    Set correctlyMappedAggregateOutputs = new HashSet();
-    Set correctlyMappedAggregateInputs = new HashSet();
-
-    Iterator iter;
-    try {
-      iter = getDelegateAnalysisEngineSpecifiers().entrySet().iterator();
-    } catch (InvalidXMLException e) {
-      throw new ResourceInitializationException(e);
-    }
-    while (iter.hasNext()) {
-      Map.Entry entry = (Map.Entry) iter.next();
-      String componentKey = (String) entry.getKey();
-      ResourceSpecifier delegateSpec = (ResourceSpecifier) entry.getValue();
-
-      if (delegateSpec instanceof AnalysisEngineDescription) {
-        Capability[] caps = ((AnalysisEngineDescription) delegateSpec).getAnalysisEngineMetaData()
-                .getCapabilities();
-        for (int i = 0; i < caps.length; i++) {
-          // all component output sofas must be mapped to aggregate output sofas
-          String[] outputSofas = caps[i].getOutputSofas();
-          for (int j = 0; j < outputSofas.length; j++) {
-            String aggSofa = (String) sofamap.get(componentKey + "@/@" + outputSofas[j]);
-            if (aggSofa == null) // no declared mapping, name remains unchanged
-            {
-              aggSofa = outputSofas[j];
-            }
-            if (!capabilitiesContainSofa(aggSofa, true)) {
-              throw new ResourceInitializationException(
-                      ResourceInitializationException.OUTPUT_SOFA_NOT_DECLARED_IN_AGGREGATE,
-                      new Object[] { outputSofas[j], componentKey, aggName, getSourceUrlString() });
-            }
-            correctlyMappedAggregateOutputs.add(aggSofa);
-          }
-
-          // all component input sofas must be mapped to aggregate input OR output sofas
-          String[] inputSofas = caps[i].getInputSofas();
-          for (int j = 0; j < inputSofas.length; j++) {
-            String aggSofa = (String) sofamap.get(componentKey + "@/@" + inputSofas[j]);
-            if (aggSofa == null) // no declared mapping, name remains unchanged
-            {
-              aggSofa = inputSofas[j];
-            }
-            if (!capabilitiesContainSofa(aggSofa, false) && !capabilitiesContainSofa(aggSofa, true)) {
-              throw new ResourceInitializationException(
-                      ResourceInitializationException.INPUT_SOFA_HAS_NO_SOURCE, new Object[] {
-                          inputSofas[j], componentKey, aggName, getSourceUrlString() });
-            }
-            correctlyMappedAggregateInputs.add(aggSofa);
-          }
-
-          // also check default text sofa
-          String aggDefSofa = (String) sofamap.get(componentKey + "@/@" + CAS.NAME_DEFAULT_SOFA);
-          if (aggDefSofa != null) {
-            if (capabilitiesContainSofa(aggDefSofa, true)) {
-              correctlyMappedAggregateOutputs.add(aggDefSofa);
-            } else {
-              correctlyMappedAggregateInputs.add(aggDefSofa);
-            }
-          }
-        }
-      } // delegateSpec is not an AnalysisEngineDescription
-      else {
-        containsRemote = true;
-      }
-    }
-
-    if (!containsRemote) {
-      // check that all aggregate outputs and inputs were mapped correclty to
-      // component inputs/outputs
-      Capability[] caps = this.getAnalysisEngineMetaData().getCapabilities();
-      for (int i = 0; i < caps.length; i++) {
-        String[] sofas = caps[i].getOutputSofas();
-        for (int j = 0; j < sofas.length; j++) {
-          if (!correctlyMappedAggregateOutputs.contains(sofas[j])) {
-            throw new ResourceInitializationException(
-                    ResourceInitializationException.AGGREGATE_SOFA_NOT_MAPPED, new Object[] {
-                        sofas[j], aggName, getSourceUrlString() });
-          }
-        }
-        sofas = caps[i].getInputSofas();
-        for (int j = 0; j < sofas.length; j++) {
-          if (!correctlyMappedAggregateInputs.contains(sofas[j])) {
-            throw new ResourceInitializationException(
-                    ResourceInitializationException.AGGREGATE_SOFA_NOT_MAPPED, new Object[] {
-                        sofas[j], aggName, getSourceUrlString() });
-          }
-        }
-      }
-    }
-  }
-
-  private boolean declaresSofa(AnalysisEngineDescription aDesc, String aSofaName) {
-    Capability[] caps = aDesc.getAnalysisEngineMetaData().getCapabilities();
-    for (int i = 0; i < caps.length; i++) {
-      String[] sofas = caps[i].getOutputSofas();
-      for (int j = 0; j < sofas.length; j++) {
-        if (aSofaName.equals(sofas[j])) {
-          return true;
-        }
-      }
-      sofas = caps[i].getInputSofas();
-      for (int j = 0; j < sofas.length; j++) {
-        if (aSofaName.equals(sofas[j])) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  protected boolean capabilitiesContainSofa(String aSofaName, boolean aOutput) {
-    Capability[] caps = this.getAnalysisEngineMetaData().getCapabilities();
-    for (int i = 0; i < caps.length; i++) {
-      String[] sofas = aOutput ? caps[i].getOutputSofas() : caps[i].getInputSofas();
-      for (int j = 0; j < sofas.length; j++) {
-        if (aSofaName.equals(sofas[j])) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Overridden to add Delegate AE Specifiers to the result list. Default introspection
-   * implementation won't return it because it has no set method. We've also overridden the XML
-   * import/export methods, though, so that set methods are not required.
-   * 
-   * @see org.apache.uima.resource.MetaDataObject#listAttributes()
-   */
-  public List listAttributes() {
-    List result = super.listAttributes();
-    result.add(new NameClassPair(PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS, Map.class
-            .getName()));
-    return result;
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#toXML(java.io.OutputStream,
-   *      boolean)
-   */
-  public void toXML(OutputStream aOutputStream, boolean aPreserveDelegateAnalysisEngineImports)
-          throws SAXException, IOException {
-    if (aPreserveDelegateAnalysisEngineImports) {
-      // trick the writePropertyAsElement method into thinking that
-      // imports haven't been resolved yet
-      Map tempMap = mDelegateAnalysisEngineSpecifiers;
-      mDelegateAnalysisEngineSpecifiers = Collections.EMPTY_MAP;
-      toXML(aOutputStream);
-      mDelegateAnalysisEngineSpecifiers = tempMap;
-    } else {
-      toXML(aOutputStream);
-    }
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#toXML(java.io.Writer, boolean)
-   */
-  public void toXML(Writer aWriter, boolean aPreserveDelegateAnalysisEngineImports)
-          throws SAXException, IOException {
-    if (aPreserveDelegateAnalysisEngineImports) {
-      // trick the writePropertyAsElement method into thinking that
-      // imports haven't been resolved yet
-      Map tempMap = mDelegateAnalysisEngineSpecifiers;
-      mDelegateAnalysisEngineSpecifiers = Collections.EMPTY_MAP;
-      toXML(aWriter);
-      mDelegateAnalysisEngineSpecifiers = tempMap;
-    } else {
-      toXML(aWriter);
-    }
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#toXML(org.xml.sax.ContentHandler,
-   *      boolean, boolean)
-   */
-  public void toXML(ContentHandler aContentHandler, boolean aWriteDefaultNamespaceAttribute,
-          boolean aPreserveDelegateAnalysisEngineImports) throws SAXException {
-    if (aPreserveDelegateAnalysisEngineImports) {
-      // trick the writePropertyAsElement method into thinking that
-      // imports haven't been resolved yet
-      Map tempMap = mDelegateAnalysisEngineSpecifiers;
-      mDelegateAnalysisEngineSpecifiers = Collections.EMPTY_MAP;
-      toXML(aContentHandler, aWriteDefaultNamespaceAttribute);
-      mDelegateAnalysisEngineSpecifiers = tempMap;
-    } else {
-      toXML(aContentHandler, aWriteDefaultNamespaceAttribute);
-    }
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#resolveImports(org.apache.uima.resource.ResourceManager)
-   */
-  public void resolveImports(ResourceManager aResourceManager) throws InvalidXMLException {
-    resolveImports(new HashSet(), aResourceManager);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#resolveImports(java.util.Collection,
-   *      org.apache.uima.resource.ResourceManager)
-   */
-  public void resolveImports(Collection aAlreadyImportedDelegateAeUrls,
-          ResourceManager aResourceManager) throws InvalidXMLException {
-    // add our own URL, if known, to the collection of already imported URLs
-    if (getSourceUrl() != null) {
-      aAlreadyImportedDelegateAeUrls.add(getSourceUrl().toString());
-    }
-    // resolve delegate AE imports (and recursively resolve imports therein)
-    resolveDelegateAnalysisEngineImports(aAlreadyImportedDelegateAeUrls, aResourceManager, true);
-    // resolve flow controller import
-    if (getFlowControllerDeclaration() != null) {
-      getFlowControllerDeclaration().resolveImports(aResourceManager);
-    }
-
-    // resolve imports in metadata (type systems, indexes, type priorities)
-    if (getAnalysisEngineMetaData() != null) {
-      getAnalysisEngineMetaData().resolveImports(aResourceManager);
-    }
-    // resolve imports in resource manager configuration
-    if (getResourceManagerConfiguration() != null) {
-      getResourceManagerConfiguration().resolveImports(aResourceManager);
-    }
-  }
-  
-
-  /**
-   * Resolves imports of delegate Analysis Engines. This reads from the
-   * delegateAnalysisEngineSpecifiersWithImports map and populates the
-   * delegateAnalysisEngineSpecifiers map. 
-   * 
-   * @param aRecursive If true, this method will call {@link #resolveImports(Collection, ResourceManager)} 
-   *   on each delegate. If a cirular import is found, an exception will be thrown.
-   */
-  protected void resolveDelegateAnalysisEngineImports(ResourceManager aResourceManager, boolean aRecursive) 
-          throws InvalidXMLException {
-    // add our own URL, if known, to the collection of enclosing aggregate URLs
-    Set urls = new HashSet();
-    if (getSourceUrl() != null) {
-      urls.add(getSourceUrl().toString());
-    }   
-    resolveDelegateAnalysisEngineImports(urls, aResourceManager, aRecursive);
-  }  
-
-  /**
-   * Resolves imports of delegate Analysis Engines. This reads from the
-   * delegateAnalysisEngineSpecifiersWithImports map and populates the
-   * delegateAnalysisEngineSpecifiers map. 
-   * 
-   * @param aEnclosingAggregateAeUrls URLs of enclosing aggregate AEs.  Used to detect circular imports.
-   * @param aRecursive If true, this method will call {@link #resolveImports(Collection, ResourceManager)} 
-   *   on each delegate. If a cirular import is found, an exception will be thrown.
-   */
-  protected void resolveDelegateAnalysisEngineImports(Collection aEnclosingAggregateAeUrls,
-          ResourceManager aResourceManager, boolean aRecursive) throws InvalidXMLException {
-    HashSet keys = new HashSet(); // keep track of keys we've encountered
-    // so we can remove stale entries
-    Iterator entryIterator = getDelegateAnalysisEngineSpecifiersWithImports().entrySet().iterator();
-    while (entryIterator.hasNext()) {
-      Map.Entry entry = (Map.Entry) entryIterator.next();
-      String key = (String) entry.getKey();
-      keys.add(key);
-      if (entry.getValue() instanceof Import) {
-        Import aeImport = ((Import) entry.getValue());
-        // see if we processed this already
-        if (entry.getValue().equals(mProcessedImports.get(key))) {
-          continue;
-        }
-        // make sure Import's relative path base is set, to allow for
-        // users who create
-        // new import objects
-        if (aeImport instanceof Import_impl) {
-          ((Import_impl) aeImport).setSourceUrlIfNull(this.getSourceUrl());
-        }
-        // locate import target
-        URL url = aeImport.findAbsoluteUrl(aResourceManager);
-
-        // check for resursive import
-        if (aEnclosingAggregateAeUrls.contains(url.toString())) {
-          String name = getMetaData() == null ? "<null>" : getMetaData().getName();
-          throw new InvalidXMLException(InvalidXMLException.CIRCULAR_AE_IMPORT, new Object[] {
-              name, url });
-        }
-
-        // parse import target
-        XMLInputSource input;
-        try {
-          input = new XMLInputSource(url);
-        } catch (IOException e) {
-          throw new InvalidXMLException(InvalidXMLException.IMPORT_FAILED_COULD_NOT_READ_FROM_URL,
-                  new Object[] { url, aeImport.getSourceUrlString() }, e);
-        }
-        ResourceSpecifier spec = UIMAFramework.getXMLParser().parseResourceSpecifier(input);
-
-        // update entry in derived mDelegateAnalysisEngineSpecifiers map.
-        mDelegateAnalysisEngineSpecifiers.put(key, spec);
-
-        // add to processed imports map so we don't redo
-        mProcessedImports.put(key, aeImport);
-
-        // now resolve imports in ths delegate
-        if (spec instanceof AnalysisEngineDescription) {
-          Set alreadyImportedUrls = new HashSet(aEnclosingAggregateAeUrls);
-          alreadyImportedUrls.add(url.toString());
-          ((AnalysisEngineDescription) spec).resolveImports(alreadyImportedUrls, aResourceManager);
-        }
-      } else {
-        // not an import -- copy directly to derived mDelegateAnalysisEngineSpecifiers map.
-        mDelegateAnalysisEngineSpecifiers.put(entry.getKey(), entry.getValue());
-        // resolve imports recursively on the delegate
-        if (entry.getValue() instanceof AnalysisEngineDescription) {
-          ((AnalysisEngineDescription) entry.getValue()).resolveImports(
-                  aEnclosingAggregateAeUrls, aResourceManager);
-        }
-      }
-    }
-    // remove stale entries
-    List staleKeys = new ArrayList();
-    entryIterator = mDelegateAnalysisEngineSpecifiers.entrySet().iterator();
-    while (entryIterator.hasNext()) {
-      String key = (String) ((Map.Entry) entryIterator.next()).getKey();
-      if (!keys.contains(key)) {
-        staleKeys.add(key);
-      }
-    }
-    Iterator it = staleKeys.iterator();
-    while (it.hasNext()) {
-      String key = (String) it.next();
-      mDelegateAnalysisEngineSpecifiers.remove(key);
-      mProcessedImports.remove(key);
-    }
-  }
-
-  /**
-   * Overridden to handle XML export of the DelegateAnalysisEngineSpecifiers attribute. This
-   * attribute has a value of type <code>Map</code>, which is not handled by the default XML
-   * export logic.
-   * 
-   * @see org.apache.uima.MetaDataObject_impl#writePropertyAsElement(PropertyXmlInfo,String,ContentHandler)
-   */
-  protected void writePropertyAsElement(PropertyXmlInfo aPropInfo, String aNamespace,
-          ContentHandler aContentHandler) throws SAXException {
-    if (PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS.equals(aPropInfo.propertyName)) {
-      // special logic here -- if imports have been resolved, then we want
-      // to write
-      // out the XML with those resolved imports. If imports have not been
-      // resolved,
-      // (mDelegateAnalysisEngineSpecifiers is empty), then we want to
-      // write out
-      // the original XML, which has the import declarations.
-      String propName = PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS;
-      if (mDelegateAnalysisEngineSpecifiers.isEmpty()) {
-        propName = PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS;
-      }
-      writeMapPropertyToXml(propName, ELEM_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS, "key",
-              "delegateAnalysisEngine", aPropInfo.omitIfNull, aNamespace, aContentHandler);
-    } else {
-      // for all other attributes, use the default superclass behavior
-      super.writePropertyAsElement(aPropInfo, aNamespace, aContentHandler);
-    }
-  }
-
-  /**
-   * Overridden to handle XML import of the DelegateAnalysisEngineSpecifiers attribute. This
-   * attribute has a value of type <code>Map</code>, which is not handled by the default XML
-   * import logic.
-   * 
-   * @see org.apache.uima.resource.impl.MetaDataObject_impl#readPropertyValueFromXMLElement(org.apache.uima.resource.impl.PropertyXmlInfo,
-   *      org.w3c.dom.Element, org.apache.uima.util.XMLParser)
-   */
-  protected void readPropertyValueFromXMLElement(PropertyXmlInfo aPropXmlInfo, Element aElement,
-          XMLParser aParser, XMLParser.ParsingOptions aOptions) throws InvalidXMLException {
-    String propName = aPropXmlInfo.propertyName;
-    if (PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS.equals(propName)) {
-      readMapPropertyFromXml(propName, aElement, "key", "delegateAnalysisEngine", aParser,
-              aOptions, false);
-    } else {
-      // for all other attributes, use the default superclass behavior
-      super.readPropertyValueFromXMLElement(aPropXmlInfo, aElement, aParser, aOptions);
-    }
-  }
-
-  /**
-   * Overridden to set default operational properties if they are not specified in descriptor.
-   */
-  public void buildFromXMLElement(Element aElement, XMLParser aParser, ParsingOptions aOptions)
-          throws InvalidXMLException {
-    super.buildFromXMLElement(aElement, aParser, aOptions);
-    if (getAnalysisEngineMetaData().getOperationalProperties() == null) {
-      OperationalProperties opProps = UIMAFramework.getResourceSpecifierFactory()
-              .createOperationalProperties();
-      opProps.setModifiesCas(true);
-      opProps.setMultipleDeploymentAllowed(true);
-      getAnalysisEngineMetaData().setOperationalProperties(opProps);
-    }
-  }
-
-  protected XmlizationInfo getXmlizationInfo() {
-    return XMLIZATION_INFO;
-  }
-
-  /**
-   * Static method to get XmlizationInfo, used by subclasses to set up their own XmlizationInfo.
-   */
-  protected static XmlizationInfo getXmlizationInfoForClass() {
-    return XMLIZATION_INFO;
-  }
-
-  static final private XmlizationInfo XMLIZATION_INFO = new XmlizationInfo(
-          "analysisEngineDescription", new PropertyXmlInfo[] {
-              new PropertyXmlInfo("frameworkImplementation"),
-              new PropertyXmlInfo("primitive"),
-              new PropertyXmlInfo("annotatorImplementationName"),
-              new PropertyXmlInfo("delegateAnalysisEngineSpecifiersWithImports",
-                      "delegateAnalysisEngineSpecifiers"), // NOTE: custom
-              // XMLization
-              new PropertyXmlInfo("flowControllerDeclaration", null),
-              new PropertyXmlInfo("metaData", null),
-              new PropertyXmlInfo("externalResourceDependencies"),
-              new PropertyXmlInfo("resourceManagerConfiguration", null),
-              new PropertyXmlInfo("sofaMappings") });
+/*
+ * 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.analysis_engine.impl;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.uima.Constants;
+import org.apache.uima.UIMAFramework;
+import org.apache.uima.analysis_engine.AnalysisEngine;
+import org.apache.uima.analysis_engine.AnalysisEngineDescription;
+import org.apache.uima.analysis_engine.metadata.AnalysisEngineMetaData;
+import org.apache.uima.analysis_engine.metadata.CapabilityLanguageFlow;
+import org.apache.uima.analysis_engine.metadata.FixedFlow;
+import org.apache.uima.analysis_engine.metadata.FlowConstraints;
+import org.apache.uima.analysis_engine.metadata.FlowControllerDeclaration;
+import org.apache.uima.analysis_engine.metadata.SofaMapping;
+import org.apache.uima.analysis_engine.metadata.impl.AnalysisEngineMetaData_impl;
+import org.apache.uima.cas.CAS;
+import org.apache.uima.resource.ResourceConfigurationException;
+import org.apache.uima.resource.ResourceCreationSpecifier;
+import org.apache.uima.resource.ResourceInitializationException;
+import org.apache.uima.resource.ResourceManager;
+import org.apache.uima.resource.ResourceSpecifier;
+import org.apache.uima.resource.impl.ResourceCreationSpecifier_impl;
+import org.apache.uima.resource.metadata.Capability;
+import org.apache.uima.resource.metadata.ConfigurationParameter;
+import org.apache.uima.resource.metadata.ConfigurationParameterDeclarations;
+import org.apache.uima.resource.metadata.Import;
+import org.apache.uima.resource.metadata.OperationalProperties;
+import org.apache.uima.resource.metadata.impl.Import_impl;
+import org.apache.uima.resource.metadata.impl.PropertyXmlInfo;
+import org.apache.uima.resource.metadata.impl.XmlizationInfo;
+import org.apache.uima.util.InvalidXMLException;
+import org.apache.uima.util.Level;
+import org.apache.uima.util.NameClassPair;
+import org.apache.uima.util.XMLInputSource;
+import org.apache.uima.util.XMLParser;
+import org.apache.uima.util.XMLParser.ParsingOptions;
+import org.w3c.dom.Element;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * Reference implementation of {@link AnalysisEngineDescription}. Note that this class contains two
+ * attributes of class Map, which are not supported by the default XML input/output routines.
+ * Therefore we override the {@link #writeAttributeAsElement(String,Class,Object,Writer)} and
+ * {@link #readAttributeFromXMLElement(String,Class,Element,XMLParser)} methods.
+ * 
+ * 
+ */
+public class AnalysisEngineDescription_impl extends ResourceCreationSpecifier_impl implements
+        AnalysisEngineDescription {
+
+  /**
+   * resource bundle for log messages
+   */
+  private static final String LOG_RESOURCE_BUNDLE = "org.apache.uima.impl.log_messages";
+
+  /**
+   * Name of the "delegateAnalysisEngineSpecifiers" property. Change this if interface changes.
+   */
+  protected String PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS = "delegateAnalysisEngineSpecifiers";
+
+  /**
+   * Name of the "delegateAnalysisEngineSpecifiersWithImports" property. Change this if interface
+   * changes.
+   */
+  protected String PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS = "delegateAnalysisEngineSpecifiersWithImports";
+
+  /**
+   * Name of the "delegateAnalysisEngineSpecifiers" XML Element. Change this if schema changes.
+   */
+  protected String ELEM_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS = "delegateAnalysisEngineSpecifiers";
+
+  private String mFrameworkImplementation;
+
+  private boolean mPrimitive;
+
+  private FlowControllerDeclaration mFlowControllerDeclaration;
+
+  private Map mDelegateAnalysisEngineSpecifiers = new HashMap();
+
+  private Map mDelegateAnalysisEngineSpecifiersWithImports = new HashMap();
+
+  private Map mProcessedImports = new HashMap();
+
+  private SofaMapping[] mSofaMappings;
+
+  static final long serialVersionUID = -8103625125291855592L;
+
+  /**
+   * Creates a new AnalysisEngineDescription_impl. Initializes the MetaData,
+   * DelegateAnalysisEngineSpecifiers, and ExternalResourcesRequired attributes.
+   */
+  public AnalysisEngineDescription_impl() {
+    setMetaData(new AnalysisEngineMetaData_impl());
+    setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
+    // Set default operational properties. These are used if the
+    // descriptor is constructed programatically, rather than parsed.
+    OperationalProperties opProps = UIMAFramework.getResourceSpecifierFactory()
+            .createOperationalProperties();
+    opProps.setModifiesCas(true);
+    opProps.setMultipleDeploymentAllowed(true);
+    opProps.setOutputsNewCASes(false);
+    getAnalysisEngineMetaData().setOperationalProperties(opProps);
+  }
+
+  /**
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getFrameworkImplementation()
+   */
+  public String getFrameworkImplementation() {
+    return mFrameworkImplementation;
+  }
+
+  /**
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#setFrameworkImplementation(java.lang.String)
+   */
+  public void setFrameworkImplementation(String aFrameworkImplementation) {
+    mFrameworkImplementation = aFrameworkImplementation;
+  }
+
+  /**
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#isPrimitive()
+   */
+  public boolean isPrimitive() {
+    return mPrimitive;
+  }
+
+  /**
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#setPrimitive(boolean)
+   */
+  public void setPrimitive(boolean aPrimitive) {
+    mPrimitive = aPrimitive;
+  }
+
+  /**
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getAnnotatorImplementationName()
+   */
+  public String getAnnotatorImplementationName() {
+    return getImplementationName();
+  }
+
+  /**
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#setAnnotatorImplementationName(String)
+   */
+  public void setAnnotatorImplementationName(String aImplementationName) {
+    setImplementationName(aImplementationName);
+  }
+
+  /**
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getDelegateAnalysisEngineSpecifiers()
+   */
+  public Map getDelegateAnalysisEngineSpecifiers() throws InvalidXMLException {
+    resolveDelegateAnalysisEngineImports(UIMAFramework.newDefaultResourceManager(), false);
+    return Collections.unmodifiableMap(mDelegateAnalysisEngineSpecifiers);
+  }
+
+  /**
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getDelegateAnalysisEngineSpecifiers()
+   */
+  public Map getDelegateAnalysisEngineSpecifiers(ResourceManager aResourceManager)
+          throws InvalidXMLException {
+    resolveDelegateAnalysisEngineImports(aResourceManager, false);
+    return Collections.unmodifiableMap(mDelegateAnalysisEngineSpecifiers);
+  }
+
+  /**
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getDelegateAnalysisEngineSpecifiers()
+   */
+  public Map getDelegateAnalysisEngineSpecifiersWithImports() {
+    return mDelegateAnalysisEngineSpecifiersWithImports;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getFlowControllerDeclaration()
+   */
+  public FlowControllerDeclaration getFlowControllerDeclaration() {
+    return mFlowControllerDeclaration;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#setFlowController(org.apache.uima.analysis_engine.metadata.FlowControllerDeclaration)
+   */
+  public void setFlowControllerDeclaration(FlowControllerDeclaration aFlowControllerDeclaration) {
+    mFlowControllerDeclaration = aFlowControllerDeclaration;
+  }
+
+  public Map getAllComponentSpecifiers(ResourceManager aResourceManager) throws InvalidXMLException {
+    if (aResourceManager == null) {
+      aResourceManager = UIMAFramework.newDefaultResourceManager();
+    }
+    resolveImports(aResourceManager);
+    Map map = new HashMap(mDelegateAnalysisEngineSpecifiers);
+    if (getFlowControllerDeclaration() != null) {
+      map.put(getFlowControllerDeclaration().getKey(), getFlowControllerDeclaration()
+              .getSpecifier());
+    }
+    return Collections.unmodifiableMap(map);
+  }
+
+  /**
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getAnalysisEngineMetaData()
+   */
+  public AnalysisEngineMetaData getAnalysisEngineMetaData() {
+    return (AnalysisEngineMetaData) getMetaData();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#getSofaMappings()
+   */
+  public SofaMapping[] getSofaMappings() {
+    return mSofaMappings;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#setSofaMappings(org.apache.uima.analysis_engine.metadata.SofaMapping[])
+   */
+  public void setSofaMappings(SofaMapping[] aSofaMappings) {
+    mSofaMappings = aSofaMappings;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#doFullValidation()
+   */
+  public void doFullValidation() throws ResourceInitializationException {
+    // attempt to instantiate AE in "verification mode"
+    Map m = new HashMap();
+    m.put(AnalysisEngineImplBase.PARAM_VERIFICATION_MODE, Boolean.TRUE);
+    AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(this, m);
+    validateSofaMappings();
+    ae.newCAS();
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#doFullValidation(org.apache.uima.resource.ResourceManager)
+   */
+  public void doFullValidation(ResourceManager aResourceManager)
+          throws ResourceInitializationException {
+    // attempt to instantiate AE in "verification mode"
+    Map m = new HashMap();
+    m.put(AnalysisEngineImplBase.PARAM_VERIFICATION_MODE, Boolean.TRUE);
+    AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(this, aResourceManager, m);
+    validateSofaMappings();
+    ae.newCAS();
+  }
+
+  /**
+   * Determines if the AnalysisEngineDescription is valid. An exception is thrown if it is not
+   * valid. This should be called from this Analysis Engine's initialize method. Note this does not
+   * check configuration parameter settings - that must be done by an explicit call to
+   * validateConfigurationParameterSettings.
+   * 
+   * @param aResourceManager
+   *          a ResourceManager instance to use to resolve imports by name.
+   *  
+   * @throws ResourceInitializationException
+   *           if <code>aDesc</code> is invalid
+   * @throws ResourceConfigurationException
+   *           if the configuration parameter settings in <code>aDesc</code> are invalid
+   */
+  public void validate(ResourceManager aResourceManager) throws ResourceInitializationException, ResourceConfigurationException {
+    // do validation common to all descriptor types (e.g. config parameters)
+    super.validate(aResourceManager);
+
+    // TypeSystem may not be specified for an Aggregate Analysis Engine
+    if (!isPrimitive() && getAnalysisEngineMetaData().getTypeSystem() != null) {
+      throw new ResourceInitializationException(
+              ResourceInitializationException.AGGREGATE_AE_TYPE_SYSTEM,
+              new Object[] { getSourceUrlString() });
+    }
+    
+    //Keys in FixedFlow or LanguageCapabilityFlow must be defined
+    FlowConstraints fc = getAnalysisEngineMetaData().getFlowConstraints();
+    String[] keys = null;
+    if (fc instanceof FixedFlow) {
+      keys = ((FixedFlow)fc).getFixedFlow();
+    }
+    else if (fc instanceof CapabilityLanguageFlow) {
+      keys = ((CapabilityLanguageFlow)fc).getCapabilityLanguageFlow();
+    }
+    if (keys != null) {
+      for (int i = 0; i < keys.length; i++) {
+        if (!getDelegateAnalysisEngineSpecifiersWithImports().containsKey(keys[i])) {
+          throw new ResourceInitializationException(ResourceInitializationException.UNDEFINED_KEY_IN_FLOW,
+                  new Object[]{getAnalysisEngineMetaData().getName(), keys[i], getSourceUrlString()});
+        }
+      }
+    }
+  }
+
+  /**
+   * Overrides{@link ResourceCreationSpecifier_impl#checkForInvalidParameterOverrides(ConfigurationParameter[], String)
+   * to validate parameter overrides in an aggregate AE. Also logs a warning for aggregate
+   * parameters with no declared overrides.
+   * 
+   * @param aParams
+   *          an array of ConfigurationParameters
+   * @param aGroupName
+   *          name of groups in which these parameters are contained. Null if no group
+   * @param aResourceManager
+   *          a ResourceManager instance to use to resolve imports by name.
+   *           
+   * @throws ResourceInitializationException
+   *           if there is an invalid parameter override declaration
+   */
+  protected void checkForInvalidParameterOverrides(ConfigurationParameter[] aParams,
+          String aGroupName, ResourceManager aResourceManager) throws ResourceInitializationException {
+    //make sure delegate analysis engine specifiers are resolved using the correct resource manager
+    try {
+      resolveImports(aResourceManager);
+    } catch (InvalidXMLException e) {
+      throw new ResourceInitializationException(e);
+    }
+    
+    for (int i = 0; i < aParams.length; i++) {
+      String[] overrides = aParams[i].getOverrides();
+      if (overrides.length > 0 && isPrimitive()) {
+        throw new ResourceInitializationException(
+                ResourceInitializationException.PARAM_OVERRIDE_IN_PRIMITIVE, new Object[] {
+                    aParams[i].getName(), getMetaData().getName(), getSourceUrlString() });
+      } else if (overrides.length == 0 && !isPrimitive()) {
+        UIMAFramework.getLogger(this.getClass()).logrb(Level.WARNING, this.getClass().getName(),
+                "checkForInvalidParameterOverrides", LOG_RESOURCE_BUNDLE,
+                "UIMA_aggregate_param_no_overrides__WARNING",
+                new Object[] { getMetaData().getName(), aParams[i].getName() });
+      }
+      for (int j = 0; j < overrides.length; j++) {
+        // overrides should be of form delegateKey/paramName
+        int slashPos = overrides[j].indexOf('/');
+        if (slashPos <= 0 || slashPos >= overrides[j].length()) {
+          throw new ResourceInitializationException(
+                  ResourceInitializationException.INVALID_PARAM_OVERRIDE_SYNTAX, new Object[] {
+                      overrides[j], aParams[i].getName(), getMetaData().getName(),
+                      getSourceUrlString() });
+        }
+        String delegateKey = overrides[j].substring(0, slashPos);
+        String paramName = overrides[j].substring(slashPos + 1);
+        // get component descriptor (could be an AE or could be the FlowController)
+        ResourceSpecifier componentSpecifier = getComponentSpecifier(delegateKey);
+        if (componentSpecifier == null) {
+          throw new ResourceInitializationException(
+                  ResourceInitializationException.INVALID_PARAM_OVERRIDE_NONEXISTENT_DELEGATE,
+                  new Object[] { overrides[j], aParams[i].getName(), getMetaData().getName(),
+                      delegateKey, getSourceUrlString() });
+        }
+        if (componentSpecifier instanceof ResourceCreationSpecifier) {
+          ConfigurationParameter overriddenParam = null;
+          ConfigurationParameterDeclarations delegateParamDecls = ((ResourceCreationSpecifier) componentSpecifier)
+                  .getMetaData().getConfigurationParameterDeclarations();
+          if (aGroupName == null) // param not in group
+          {
+            overriddenParam = delegateParamDecls.getConfigurationParameter(null, paramName);
+            if (overriddenParam == null) {
+              throw new ResourceInitializationException(
+                      ResourceInitializationException.INVALID_PARAM_OVERRIDE_NONEXISTENT_PARAMETER,
+                      new Object[] { overrides[j], aParams[i].getName(), getMetaData().getName(),
+                          delegateKey, paramName, getSourceUrlString() });
+
+            }
+          } else {
+            // make sure parameter exists in group
+            overriddenParam = delegateParamDecls.getConfigurationParameter(aGroupName, paramName);
+            if (overriddenParam == null) {
+              throw new ResourceInitializationException(
+                      ResourceInitializationException.INVALID_PARAM_OVERRIDE_NONEXISTENT_PARAMETER_IN_GROUP,
+                      new Object[] { overrides[j], aParams[i].getName(), getMetaData().getName(),
+                          delegateKey, paramName, aGroupName, getSourceUrlString() });
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Gets the ResourceSpecifier of one a component of this aggregate, based on its key. This may be
+   * the specifier of a component (i.e. delegate) AnalysisEngine, or it may be the specifier of the
+   * FlowController.
+   * 
+   * @param key
+   *          the key of the component specifier to get
+   * @return the specifier for the component, null if there is no component with the given key
+   * @throws ResourceInitializationException
+   *           if there's a problem resolving imports
+   */
+  public ResourceSpecifier getComponentSpecifier(String key) throws ResourceInitializationException {
+    ResourceSpecifier componentSpecifier;
+    if (getFlowControllerDeclaration() != null
+            && key.equals(getFlowControllerDeclaration().getKey())) {
+      try {
+        getFlowControllerDeclaration().resolveImports();
+      } catch (InvalidXMLException e) {
+        throw new ResourceInitializationException(e);
+      }
+      componentSpecifier = getFlowControllerDeclaration().getSpecifier();
+    } else {
+      try {
+        componentSpecifier = (ResourceSpecifier) getDelegateAnalysisEngineSpecifiers().get(key);
+      } catch (InvalidXMLException e) {
+        throw new ResourceInitializationException(e);
+      }
+    }
+    return componentSpecifier;
+  }
+
+  /**
+   * Validate SofA mappings and inputs/outputs for an aggregate AE.
+   * 
+   * @param aDesc
+   */
+  protected void validateSofaMappings() throws ResourceInitializationException {
+    if (this.isPrimitive())
+      return;
+    String aggName = this.getAnalysisEngineMetaData().getName();
+    // build an actual Map (key: componentKey@/@componentSofa) from the sofa mappings
+    // along the way check that all component keys and component sofa names exist
+    Map sofamap = new TreeMap();
+    SofaMapping[] sofaMappings = this.getSofaMappings();
+    if (sofaMappings != null) {
+      for (int s = 0; s < sofaMappings.length; s++) {
+        String componentKey = sofaMappings[s].getComponentKey();
+        ResourceSpecifier componentSpec = getComponentSpecifier(componentKey);
+        if (componentSpec == null) {
+          throw new ResourceInitializationException(
+                  ResourceInitializationException.SOFA_MAPPING_HAS_UNDEFINED_COMPONENT_KEY,
+                  new Object[] { componentKey, sofaMappings[s].getAggregateSofaName(), aggName,
+                      getSourceUrlString() });
+        }
+        String componentSofaName = sofaMappings[s].getComponentSofaName();
+        if (componentSofaName == null) {
+          componentSofaName = CAS.NAME_DEFAULT_SOFA;
+        } else if (componentSpec instanceof AnalysisEngineDescription
+                && !CAS.NAME_DEFAULT_SOFA.equals(componentSofaName)
+                && !declaresSofa((AnalysisEngineDescription) componentSpec, componentSofaName)) {
+          throw new ResourceInitializationException(
+                  ResourceInitializationException.SOFA_MAPPING_HAS_UNDEFINED_COMPONENT_SOFA,
+                  new Object[] { componentKey, componentSofaName,
+                      sofaMappings[s].getAggregateSofaName(), aggName, getSourceUrlString() });
+        }
+
+        String compoundKey = sofaMappings[s].getComponentKey() + "@/@"
+                + sofaMappings[s].getComponentSofaName();
+        String aggSofaName = sofaMappings[s].getAggregateSofaName();
+        // check for double-mapping
+        String existingMapping = (String) sofamap.get(compoundKey);
+        if (existingMapping != null && !existingMapping.equals(aggSofaName)) {
+          throw new ResourceInitializationException(
+                  ResourceInitializationException.SOFA_MAPPING_CONFLICT, new Object[] {
+                      sofaMappings[s].getComponentSofaName(), sofaMappings[s].getComponentKey(),
+                      aggName, existingMapping, aggSofaName, getSourceUrlString() });
+        } else {
+          sofamap.put(compoundKey, aggSofaName);
+        }
+      }
+    }
+
+    // Rules for SofAs:
+    // (1) Each component output sofa must be mapped to an aggregate output sofa
+    // (2) Each aggregate output sofa must be mapped to a component output sofa
+    // (3) Each component input sofa must be mapped to an aggregate input sofa OR a component output
+    // sofa
+    // (4) Each aggregate input sofa must be mapped to a component input sofa
+
+    // From (1) and (3) we derive that:
+    // Each component input sofa must be mapped to an aggregate input sofa OR an aggregate output
+    // sofa
+    // (which is easier to check)
+
+    // Exception: if aggregate contains a remote component, we cannot check that remote
+    // component's input or output sofas, so rules (2) and (4) cannot be checked.
+
+    boolean containsRemote = false;
+    Set correctlyMappedAggregateOutputs = new HashSet();
+    Set correctlyMappedAggregateInputs = new HashSet();
+
+    Iterator iter;
+    try {
+      iter = getDelegateAnalysisEngineSpecifiers().entrySet().iterator();
+    } catch (InvalidXMLException e) {
+      throw new ResourceInitializationException(e);
+    }
+    while (iter.hasNext()) {
+      Map.Entry entry = (Map.Entry) iter.next();
+      String componentKey = (String) entry.getKey();
+      ResourceSpecifier delegateSpec = (ResourceSpecifier) entry.getValue();
+
+      if (delegateSpec instanceof AnalysisEngineDescription) {
+        Capability[] caps = ((AnalysisEngineDescription) delegateSpec).getAnalysisEngineMetaData()
+                .getCapabilities();
+        for (int i = 0; i < caps.length; i++) {
+          // all component output sofas must be mapped to aggregate output sofas
+          String[] outputSofas = caps[i].getOutputSofas();
+          for (int j = 0; j < outputSofas.length; j++) {
+            String aggSofa = (String) sofamap.get(componentKey + "@/@" + outputSofas[j]);
+            if (aggSofa == null) // no declared mapping, name remains unchanged
+            {
+              aggSofa = outputSofas[j];
+            }
+            if (!capabilitiesContainSofa(aggSofa, true)) {
+              throw new ResourceInitializationException(
+                      ResourceInitializationException.OUTPUT_SOFA_NOT_DECLARED_IN_AGGREGATE,
+                      new Object[] { outputSofas[j], componentKey, aggName, getSourceUrlString() });
+            }
+            correctlyMappedAggregateOutputs.add(aggSofa);
+          }
+
+          // all component input sofas must be mapped to aggregate input OR output sofas
+          String[] inputSofas = caps[i].getInputSofas();
+          for (int j = 0; j < inputSofas.length; j++) {
+            String aggSofa = (String) sofamap.get(componentKey + "@/@" + inputSofas[j]);
+            if (aggSofa == null) // no declared mapping, name remains unchanged
+            {
+              aggSofa = inputSofas[j];
+            }
+            if (!capabilitiesContainSofa(aggSofa, false) && !capabilitiesContainSofa(aggSofa, true)) {
+              throw new ResourceInitializationException(
+                      ResourceInitializationException.INPUT_SOFA_HAS_NO_SOURCE, new Object[] {
+                          inputSofas[j], componentKey, aggName, getSourceUrlString() });
+            }
+            correctlyMappedAggregateInputs.add(aggSofa);
+          }
+
+          // also check default text sofa
+          String aggDefSofa = (String) sofamap.get(componentKey + "@/@" + CAS.NAME_DEFAULT_SOFA);
+          if (aggDefSofa != null) {
+            if (capabilitiesContainSofa(aggDefSofa, true)) {
+              correctlyMappedAggregateOutputs.add(aggDefSofa);
+            } else {
+              correctlyMappedAggregateInputs.add(aggDefSofa);
+            }
+          }
+        }
+      } // delegateSpec is not an AnalysisEngineDescription
+      else {
+        containsRemote = true;
+      }
+    }
+
+    if (!containsRemote) {
+      // check that all aggregate outputs and inputs were mapped correclty to
+      // component inputs/outputs
+      Capability[] caps = this.getAnalysisEngineMetaData().getCapabilities();
+      for (int i = 0; i < caps.length; i++) {
+        String[] sofas = caps[i].getOutputSofas();
+        for (int j = 0; j < sofas.length; j++) {
+          if (!correctlyMappedAggregateOutputs.contains(sofas[j])) {
+            throw new ResourceInitializationException(
+                    ResourceInitializationException.AGGREGATE_SOFA_NOT_MAPPED, new Object[] {
+                        sofas[j], aggName, getSourceUrlString() });
+          }
+        }
+        sofas = caps[i].getInputSofas();
+        for (int j = 0; j < sofas.length; j++) {
+          if (!correctlyMappedAggregateInputs.contains(sofas[j])) {
+            throw new ResourceInitializationException(
+                    ResourceInitializationException.AGGREGATE_SOFA_NOT_MAPPED, new Object[] {
+                        sofas[j], aggName, getSourceUrlString() });
+          }
+        }
+      }
+    }
+  }
+
+  private boolean declaresSofa(AnalysisEngineDescription aDesc, String aSofaName) {
+    Capability[] caps = aDesc.getAnalysisEngineMetaData().getCapabilities();
+    for (int i = 0; i < caps.length; i++) {
+      String[] sofas = caps[i].getOutputSofas();
+      for (int j = 0; j < sofas.length; j++) {
+        if (aSofaName.equals(sofas[j])) {
+          return true;
+        }
+      }
+      sofas = caps[i].getInputSofas();
+      for (int j = 0; j < sofas.length; j++) {
+        if (aSofaName.equals(sofas[j])) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  protected boolean capabilitiesContainSofa(String aSofaName, boolean aOutput) {
+    Capability[] caps = this.getAnalysisEngineMetaData().getCapabilities();
+    for (int i = 0; i < caps.length; i++) {
+      String[] sofas = aOutput ? caps[i].getOutputSofas() : caps[i].getInputSofas();
+      for (int j = 0; j < sofas.length; j++) {
+        if (aSofaName.equals(sofas[j])) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Overridden to add Delegate AE Specifiers to the result list. Default introspection
+   * implementation won't return it because it has no set method. We've also overridden the XML
+   * import/export methods, though, so that set methods are not required.
+   * 
+   * @see org.apache.uima.resource.MetaDataObject#listAttributes()
+   */
+  public List listAttributes() {
+    List result = super.listAttributes();
+    result.add(new NameClassPair(PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS, Map.class
+            .getName()));
+    return result;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#toXML(java.io.OutputStream,
+   *      boolean)
+   */
+  public void toXML(OutputStream aOutputStream, boolean aPreserveDelegateAnalysisEngineImports)
+          throws SAXException, IOException {
+    if (aPreserveDelegateAnalysisEngineImports) {
+      // trick the writePropertyAsElement method into thinking that
+      // imports haven't been resolved yet
+      Map tempMap = mDelegateAnalysisEngineSpecifiers;
+      mDelegateAnalysisEngineSpecifiers = Collections.EMPTY_MAP;
+      toXML(aOutputStream);
+      mDelegateAnalysisEngineSpecifiers = tempMap;
+    } else {
+      toXML(aOutputStream);
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#toXML(java.io.Writer, boolean)
+   */
+  public void toXML(Writer aWriter, boolean aPreserveDelegateAnalysisEngineImports)
+          throws SAXException, IOException {
+    if (aPreserveDelegateAnalysisEngineImports) {
+      // trick the writePropertyAsElement method into thinking that
+      // imports haven't been resolved yet
+      Map tempMap = mDelegateAnalysisEngineSpecifiers;
+      mDelegateAnalysisEngineSpecifiers = Collections.EMPTY_MAP;
+      toXML(aWriter);
+      mDelegateAnalysisEngineSpecifiers = tempMap;
+    } else {
+      toXML(aWriter);
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#toXML(org.xml.sax.ContentHandler,
+   *      boolean, boolean)
+   */
+  public void toXML(ContentHandler aContentHandler, boolean aWriteDefaultNamespaceAttribute,
+          boolean aPreserveDelegateAnalysisEngineImports) throws SAXException {
+    if (aPreserveDelegateAnalysisEngineImports) {
+      // trick the writePropertyAsElement method into thinking that
+      // imports haven't been resolved yet
+      Map tempMap = mDelegateAnalysisEngineSpecifiers;
+      mDelegateAnalysisEngineSpecifiers = Collections.EMPTY_MAP;
+      toXML(aContentHandler, aWriteDefaultNamespaceAttribute);
+      mDelegateAnalysisEngineSpecifiers = tempMap;
+    } else {
+      toXML(aContentHandler, aWriteDefaultNamespaceAttribute);
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#resolveImports(org.apache.uima.resource.ResourceManager)
+   */
+  public void resolveImports(ResourceManager aResourceManager) throws InvalidXMLException {
+    resolveImports(new HashSet(), aResourceManager);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.uima.analysis_engine.AnalysisEngineDescription#resolveImports(java.util.Collection,
+   *      org.apache.uima.resource.ResourceManager)
+   */
+  public void resolveImports(Collection aAlreadyImportedDelegateAeUrls,
+          ResourceManager aResourceManager) throws InvalidXMLException {
+    // add our own URL, if known, to the collection of already imported URLs
+    if (getSourceUrl() != null) {
+      aAlreadyImportedDelegateAeUrls.add(getSourceUrl().toString());
+    }
+    // resolve delegate AE imports (and recursively resolve imports therein)
+    resolveDelegateAnalysisEngineImports(aAlreadyImportedDelegateAeUrls, aResourceManager, true);
+    // resolve flow controller import
+    if (getFlowControllerDeclaration() != null) {
+      getFlowControllerDeclaration().resolveImports(aResourceManager);
+    }
+
+    // resolve imports in metadata (type systems, indexes, type priorities)
+    if (getAnalysisEngineMetaData() != null) {
+      getAnalysisEngineMetaData().resolveImports(aResourceManager);
+    }
+    // resolve imports in resource manager configuration
+    if (getResourceManagerConfiguration() != null) {
+      getResourceManagerConfiguration().resolveImports(aResourceManager);
+    }
+  }
+  
+
+  /**
+   * Resolves imports of delegate Analysis Engines. This reads from the
+   * delegateAnalysisEngineSpecifiersWithImports map and populates the
+   * delegateAnalysisEngineSpecifiers map. 
+   * 
+   * @param aRecursive If true, this method will call {@link #resolveImports(Collection, ResourceManager)} 
+   *   on each delegate. If a cirular import is found, an exception will be thrown.
+   */
+  protected void resolveDelegateAnalysisEngineImports(ResourceManager aResourceManager, boolean aRecursive) 
+          throws InvalidXMLException {
+    // add our own URL, if known, to the collection of enclosing aggregate URLs
+    Set urls = new HashSet();
+    if (getSourceUrl() != null) {
+      urls.add(getSourceUrl().toString());
+    }   
+    resolveDelegateAnalysisEngineImports(urls, aResourceManager, aRecursive);
+  }  
+
+  /**
+   * Resolves imports of delegate Analysis Engines. This reads from the
+   * delegateAnalysisEngineSpecifiersWithImports map and populates the
+   * delegateAnalysisEngineSpecifiers map. 
+   * 
+   * @param aEnclosingAggregateAeUrls URLs of enclosing aggregate AEs.  Used to detect circular imports.
+   * @param aRecursive If true, this method will call {@link #resolveImports(Collection, ResourceManager)} 
+   *   on each delegate. If a cirular import is found, an exception will be thrown.
+   */
+  protected void resolveDelegateAnalysisEngineImports(Collection aEnclosingAggregateAeUrls,
+          ResourceManager aResourceManager, boolean aRecursive) throws InvalidXMLException {
+    HashSet keys = new HashSet(); // keep track of keys we've encountered
+    // so we can remove stale entries
+    Iterator entryIterator = getDelegateAnalysisEngineSpecifiersWithImports().entrySet().iterator();
+    while (entryIterator.hasNext()) {
+      Map.Entry entry = (Map.Entry) entryIterator.next();
+      String key = (String) entry.getKey();
+      keys.add(key);
+      if (entry.getValue() instanceof Import) {
+        Import aeImport = ((Import) entry.getValue());
+        // see if we processed this already
+        if (entry.getValue().equals(mProcessedImports.get(key))) {
+          continue;
+        }
+        // make sure Import's relative path base is set, to allow for
+        // users who create
+        // new import objects
+        if (aeImport instanceof Import_impl) {
+          ((Import_impl) aeImport).setSourceUrlIfNull(this.getSourceUrl());
+        }
+        // locate import target
+        URL url = aeImport.findAbsoluteUrl(aResourceManager);
+
+        // check for resursive import
+        if (aEnclosingAggregateAeUrls.contains(url.toString())) {
+          String name = getMetaData() == null ? "<null>" : getMetaData().getName();
+          throw new InvalidXMLException(InvalidXMLException.CIRCULAR_AE_IMPORT, new Object[] {
+              name, url });
+        }
+
+        // parse import target
+        XMLInputSource input;
+        try {
+          input = new XMLInputSource(url);
+        } catch (IOException e) {
+          throw new InvalidXMLException(InvalidXMLException.IMPORT_FAILED_COULD_NOT_READ_FROM_URL,
+                  new Object[] { url, aeImport.getSourceUrlString() }, e);
+        }
+        ResourceSpecifier spec = UIMAFramework.getXMLParser().parseResourceSpecifier(input);
+
+        // update entry in derived mDelegateAnalysisEngineSpecifiers map.
+        mDelegateAnalysisEngineSpecifiers.put(key, spec);
+
+        // add to processed imports map so we don't redo
+        mProcessedImports.put(key, aeImport);
+
+        // now resolve imports in ths delegate
+        if (spec instanceof AnalysisEngineDescription) {
+          Set alreadyImportedUrls = new HashSet(aEnclosingAggregateAeUrls);
+          alreadyImportedUrls.add(url.toString());
+          ((AnalysisEngineDescription) spec).resolveImports(alreadyImportedUrls, aResourceManager);
+        }
+      } else {
+        // not an import -- copy directly to derived mDelegateAnalysisEngineSpecifiers map.
+        mDelegateAnalysisEngineSpecifiers.put(entry.getKey(), entry.getValue());
+        // resolve imports recursively on the delegate
+        if (entry.getValue() instanceof AnalysisEngineDescription) {
+          ((AnalysisEngineDescription) entry.getValue()).resolveImports(
+                  aEnclosingAggregateAeUrls, aResourceManager);
+        }
+      }
+    }
+    // remove stale entries
+    List staleKeys = new ArrayList();
+    entryIterator = mDelegateAnalysisEngineSpecifiers.entrySet().iterator();
+    while (entryIterator.hasNext()) {
+      String key = (String) ((Map.Entry) entryIterator.next()).getKey();
+      if (!keys.contains(key)) {
+        staleKeys.add(key);
+      }
+    }
+    Iterator it = staleKeys.iterator();
+    while (it.hasNext()) {
+      String key = (String) it.next();
+      mDelegateAnalysisEngineSpecifiers.remove(key);
+      mProcessedImports.remove(key);
+    }
+  }
+
+  /**
+   * Overridden to handle XML export of the DelegateAnalysisEngineSpecifiers attribute. This
+   * attribute has a value of type <code>Map</code>, which is not handled by the default XML
+   * export logic.
+   * 
+   * @see org.apache.uima.MetaDataObject_impl#writePropertyAsElement(PropertyXmlInfo,String,ContentHandler)
+   */
+  protected void writePropertyAsElement(PropertyXmlInfo aPropInfo, String aNamespace,
+          ContentHandler aContentHandler) throws SAXException {
+    if (PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS.equals(aPropInfo.propertyName)) {
+      // special logic here -- if imports have been resolved, then we want
+      // to write
+      // out the XML with those resolved imports. If imports have not been
+      // resolved,
+      // (mDelegateAnalysisEngineSpecifiers is empty), then we want to
+      // write out
+      // the original XML, which has the import declarations.
+      String propName = PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS;
+      if (mDelegateAnalysisEngineSpecifiers.isEmpty()) {
+        propName = PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS;
+      }
+      writeMapPropertyToXml(propName, ELEM_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS, "key",
+              "delegateAnalysisEngine", aPropInfo.omitIfNull, aNamespace, aContentHandler);
+    } else {
+      // for all other attributes, use the default superclass behavior
+      super.writePropertyAsElement(aPropInfo, aNamespace, aContentHandler);
+    }
+  }
+
+  /**
+   * Overridden to handle XML import of the DelegateAnalysisEngineSpecifiers attribute. This
+   * attribute has a value of type <code>Map</code>, which is not handled by the default XML
+   * import logic.
+   * 
+   * @see org.apache.uima.resource.impl.MetaDataObject_impl#readPropertyValueFromXMLElement(org.apache.uima.resource.impl.PropertyXmlInfo,
+   *      org.w3c.dom.Element, org.apache.uima.util.XMLParser)
+   */
+  protected void readPropertyValueFromXMLElement(PropertyXmlInfo aPropXmlInfo, Element aElement,
+          XMLParser aParser, XMLParser.ParsingOptions aOptions) throws InvalidXMLException {
+    String propName = aPropXmlInfo.propertyName;
+    if (PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS.equals(propName)) {
+      readMapPropertyFromXml(propName, aElement, "key", "delegateAnalysisEngine", aParser,
+              aOptions, false);
+    } else {
+      // for all other attributes, use the default superclass behavior
+      super.readPropertyValueFromXMLElement(aPropXmlInfo, aElement, aParser, aOptions);
+    }
+  }
+
+  /**
+   * Overridden to set default operational properties if they are not specified in descriptor.
+   */
+  public void buildFromXMLElement(Element aElement, XMLParser aParser, ParsingOptions aOptions)
+          throws InvalidXMLException {
+    super.buildFromXMLElement(aElement, aParser, aOptions);
+    if (getAnalysisEngineMetaData().getOperationalProperties() == null) {
+      OperationalProperties opProps = UIMAFramework.getResourceSpecifierFactory()
+              .createOperationalProperties();
+      opProps.setModifiesCas(true);
+      opProps.setMultipleDeploymentAllowed(true);
+      getAnalysisEngineMetaData().setOperationalProperties(opProps);
+    }
+  }
+
+  protected XmlizationInfo getXmlizationInfo() {
+    return XMLIZATION_INFO;
+  }
+
+  /**
+   * Static method to get XmlizationInfo, used by subclasses to set up their own XmlizationInfo.
+   */
+  protected static XmlizationInfo getXmlizationInfoForClass() {
+    return XMLIZATION_INFO;
+  }
+
+  static final private XmlizationInfo XMLIZATION_INFO = new XmlizationInfo(
+          "analysisEngineDescription", new PropertyXmlInfo[] {
+              new PropertyXmlInfo("frameworkImplementation"),
+              new PropertyXmlInfo("primitive"),
+              new PropertyXmlInfo("annotatorImplementationName"),
+              new PropertyXmlInfo("delegateAnalysisEngineSpecifiersWithImports",
+                      "delegateAnalysisEngineSpecifiers"), // NOTE: custom
+              // XMLization
+              new PropertyXmlInfo("flowControllerDeclaration", null),
+              new PropertyXmlInfo("metaData", null),
+              new PropertyXmlInfo("externalResourceDependencies"),
+              new PropertyXmlInfo("resourceManagerConfiguration", null),
+              new PropertyXmlInfo("sofaMappings") });
 }
\ No newline at end of file

Propchange: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineImplBase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineManagementImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineManagementImplMBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisProcessData_impl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnnotatorContext_impl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/EmptyCasIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/JCasIteratorWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/MultiprocessingAnalysisEngine_impl.java
------------------------------------------------------------------------------
    svn:eol-style = native