/** \file taespecifier.cpp .
-----------------------------------------------------------------------------

 * 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.

-----------------------------------------------------------------------------

   Description: Resource Specifier Classes for Text Analysis Engines

-----------------------------------------------------------------------------


   01/30/2003  Initial creation

-------------------------------------------------------------------------- */
// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------

#include "uima/pragmas.hpp" //must be first to surpress warnings
#include "uima/err_ids.h"
#include "uima/msg.h"


#include "uima/taespecifierbuilder.hpp"
#include "uima/typesystemdescription.hpp"
#include "uima/capability.hpp"
#include "uima/config_param.hpp"
#include "uima/taespecifier.hpp"
#include "uima/caswriter_abase.hpp"

namespace uima {
  UIMA_EXC_CLASSIMPLEMENT(ConfigParamLookupException, ConfigException);

  AnalysisEngineMetaData::~AnalysisEngineMetaData() {
    delete iv_pTypeSystemDesc;
    delete iv_pFlowConstraints;
    if (iv_pOperationalProperties != 0) {
      delete iv_pOperationalProperties;
    }
    size_t i=0;
    for (i=0; i < iv_capabilities.size(); i++) {
      delete iv_capabilities[i];
    }
    for (i=0; i < iv_indexDescs.size(); i++) {
      delete iv_indexDescs[i];
    }
    for (i=0; i < iv_vecpTypePriorities.size(); i++) {
      delete iv_vecpTypePriorities[i];
    }
    for (i=0; i < iv_fsindexImportDescs.size(); i++) {
      delete iv_fsindexImportDescs[i];
    }
    for (i=0; i < iv_typepriorityImportDescs.size(); i++) {
      delete iv_typepriorityImportDescs[i];
    }

  }

  void AnalysisEngineMetaData::validate() {
    size_t i=0;
    //validate the type system
    //validate(*aeMetadata.getTypeSystemDescription());
    getTypeSystemDescription()->validate();

    //validate the capabilities
    AnalysisEngineMetaData::TyVecpCapabilities capabilities = getCapabilites();
    for (i=0; i<capabilities.size(); i++) {
		if ( !(EXISTS(capabilities[i])) ) {
			UIMA_EXC_THROW_NEW(ValidationException,
                           UIMA_ERR_CONFIG_OBJECT_NOT_FOUND,
                           ErrorMessage(UIMA_MSG_ID_EXCON_CHECKING_CAPABILITY_SPEC),
                           UIMA_MSG_ID_EXCON_CHECKING_CAPABILITY_SPEC,
                           ErrorInfo::unrecoverable);
		}
    }

    //validate the index descriptions
    AnalysisEngineMetaData::TyVecpFSIndexDescriptions indexDescs = getFSIndexDescriptions();
    vector <icu::UnicodeString> indexLabels;
    for (i=0; i<indexDescs.size(); i++) {
      if ( !(EXISTS(indexDescs[i])) ){
			UIMA_EXC_THROW_NEW(ValidationException,
                           UIMA_ERR_CONFIG_OBJECT_NOT_FOUND,
                           ErrorMessage(UIMA_MSG_ID_EXC_INVALID_INDEX_OBJECT, indexLabels[i]),
                           UIMA_MSG_ID_EXCON_CHECKING_INDEX_DEFINITION,
                           ErrorInfo::unrecoverable);
	  }
      indexLabels.push_back((*indexDescs[i]).getLabel());
    }

    //check uniqueness of the index description labels
    for (i=0; i<indexLabels.size(); i++) {
      if ( countValues(indexLabels.begin(), indexLabels.end(), indexLabels[i]) != 1) {

        UIMA_EXC_THROW_NEW(ValidationException,
                           UIMA_ERR_CONFIG_DUPLICATE_INDEX_LABEL,
                           ErrorMessage(UIMA_MSG_ID_EXC_DUPLICATE_INDEX_LABEL, indexLabels[i]),
                           UIMA_MSG_ID_EXCON_CHECKING_INDEX_DEFINITION,
                           ErrorInfo::unrecoverable);
      }
    }

    //validate the configuration parameters

    //make sure that there's a value for each mandatory configuration parameter
    const vector <icu::UnicodeString> groupNames = getConfigurationGroupNames();
    for (i=0; i < groupNames.size(); i++) {
      const vector <const ConfigurationParameter *> params = getConfigurationParameters(groupNames[i]);
      for (size_t j=0; j < params.size(); j++) {
        if (params[j]->isMandatory()) {
          NameValuePair * nvPair = getNameValuePair(groupNames[i], params[j]->getName(),
                                   getSearchStrategy());
          if (! EXISTS(nvPair)) {
            if (hasGroups()) {
              ErrorMessage err(UIMA_MSG_ID_EXC_NO_VALUE_FOR_MANDATORY_PARAM_IN_GROUP);
              err.addParam(groupNames[i]);
              err.addParam(params[j]->getName());
              UIMA_EXC_THROW_NEW(ValidationException,
                                 UIMA_ERR_CONFIG_NO_VALUE_FOR_MANDATORY_PARAM_IN_GROUP,
                                 err,
                                 UIMA_MSG_ID_EXCON_VALIDATE_TAE_SPEC,
                                 ErrorInfo::unrecoverable);
            } else {
              ErrorMessage err(UIMA_MSG_ID_EXC_NO_VALUE_FOR_MANDATORY_PARAM);
              err.addParam(params[j]->getName());
              UIMA_EXC_THROW_NEW(ValidationException,
                                 UIMA_ERR_CONFIG_NO_VALUE_FOR_MANDATORY_PARAM,
                                 err,
                                 UIMA_MSG_ID_EXCON_VALIDATE_TAE_SPEC,
                                 ErrorInfo::unrecoverable);

            }
          }
        }
      }
    }
  }

  void AnalysisEngineMetaData::commit() {
    if (EXISTS(iv_pTypeSystemDesc)) {
      iv_pTypeSystemDesc->commit();
    }
    if (EXISTS(iv_pFlowConstraints)) {
      iv_pFlowConstraints->commit();
    }
    TyConfigGroup::iterator ite;
    for (ite = iv_configurationGroups.begin(); ite != iv_configurationGroups.end(); ite++) {
      (*ite).second.commit();
    }
    size_t i;
    for (i=0; i < iv_capabilities.size(); i++) {
      iv_capabilities[i]->commit();
    }
    for (i=0; i < iv_indexDescs.size(); i++) {
      iv_indexDescs[i]->commit();
    }
    for (i=0; i < iv_vecpTypePriorities.size(); i++) {
      iv_vecpTypePriorities[i]->commit();
    }
    if (hasDefaultGroup()) {
      TyConfigGroup::const_iterator ite = iv_configurationGroups.find(iv_defaultGroup);
      if (ite == iv_configurationGroups.end()) {
        iv_configurationGroups [iv_defaultGroup] = ConfigurationGroup();
      }
    }
    iv_bIsModifiable = false;
  }

  /**
  * Note: The configuration group is set during <code>commit</code>, if it doesn't exist already.
  * If we set it here, <code>addConfigurationGroup</code> throws an exception when it encounters
  * the group again.
  **/
  TyErrorId AnalysisEngineMetaData::setDefaultGroupName(const icu::UnicodeString & groupName) {
    if (! isModifiable()) {
      return UIMA_ERR_CONFIG_OBJECT_COMITTED;
    }
    iv_hasDefaultGroup = true;
    iv_defaultGroup = groupName;
    return UIMA_ERR_NONE;
  }


  TyErrorId AnalysisEngineMetaData::addConfigurationGroup(const icu::UnicodeString & groupName) {
    if (! isModifiable()) {
      return UIMA_ERR_CONFIG_OBJECT_COMITTED;
    }
    TyConfigGroup::iterator ite = iv_configurationGroups.find(groupName);
    if (ite == iv_configurationGroups.end()) {
      iv_configurationGroups [groupName] = ConfigurationGroup();
      return UIMA_ERR_NONE;
    } else {
      UIMA_EXC_THROW_NEW(DuplicateConfigElemException,
                         UIMA_ERR_CONFIG_DUPLICATE_GROUP,
                         UIMA_MSG_ID_EXC_CONFIG_DUPLICATE_GROUP,
                         ErrorMessage(UIMA_MSG_ID_EXC_CONFIG_DUPLICATE_GROUP, groupName),
                         ErrorInfo::recoverable);
    }
  }

  TyErrorId AnalysisEngineMetaData::addConfigurationParameter(const icu::UnicodeString & groupName,
      ConfigurationParameter * param) {
    if (! isModifiable()) {
      return UIMA_ERR_CONFIG_OBJECT_COMITTED;
    }

    if (groupName.compare(CONFIG_GROUP_NAME_WHEN_NO_GROUPS) != 0) {
      iv_hasGroups = true;
    }
    TyConfigGroup::iterator ite = iv_configurationGroups.find(groupName);
    if (ite == iv_configurationGroups.end()) {
      iv_configurationGroups [groupName] = ConfigurationGroup();
      ite = iv_configurationGroups.find(groupName);
    }
    ConfigurationGroup & group = (*ite).second;
    if (isParameterDefined(groupName, param->getName(), "")) {
      ErrorMessage msg(UIMA_MSG_ID_EXC_CONFIG_DUPLICATE_CONFIG_PARAM);
      msg.addParam(param->getName());
      UIMA_EXC_THROW_NEW(DuplicateConfigElemException,
                         UIMA_ERR_CONFIG_DUPLICATE_CONFIG_PARAM,
                         UIMA_MSG_ID_EXC_CONFIG_DUPLICATE_CONFIG_PARAM,
                         msg,
                         ErrorInfo::recoverable);
    }
    return group.addConfigurationParameter(param);
  }

  void AnalysisEngineMetaData::addNameValuePair(const icu::UnicodeString & groupName,
      NameValuePair * nvPair) {
    if (! isParameterDefined(groupName, nvPair->getName(), "")) {
      const icu::UnicodeString & paramName = nvPair->getName();
      if (hasGroups()) {
        ErrorMessage msg(UIMA_MSG_ID_EXC_CONFIG_PARAM_NOT_DEFINED_IN_GROUP);
        msg.addParam(paramName);
        msg.addParam(groupName);
        UIMA_EXC_THROW_NEW(ConfigParamLookupException,
                           UIMA_ERR_CONFIG_PARAM_NOT_DEFINED_IN_GROUP,
                           msg,
                           ErrorMessage(UIMA_MSG_ID_EXCON_CONFIG_PARAM_SEARCH, paramName),
                           ErrorInfo::recoverable);
      } else {
        UIMA_EXC_THROW_NEW(ConfigParamLookupException,
                           UIMA_ERR_CONFIG_PARAM_NOT_DEFINED,
                           ErrorMessage(UIMA_MSG_ID_EXC_CONFIG_PARAM_NOT_DEFINED, paramName),
                           ErrorMessage(UIMA_MSG_ID_EXCON_CONFIG_PARAM_SEARCH, paramName),
                           ErrorInfo::recoverable);
      }
    }
    TyConfigSettings::iterator ite = iv_configurationSettings.find(groupName);
    if (ite == iv_configurationSettings.end()) {
      iv_configurationSettings [groupName] = SettingsForGroup();
      ite = iv_configurationSettings.find(groupName);
    }
    SettingsForGroup & settings = (*ite).second;
    settings.addNameValuePair(nvPair);
  }

  NameValuePair * AnalysisEngineMetaData::getNameValuePairPtr(const icu::UnicodeString & groupName,
      const icu::UnicodeString & paramName) {
    TyConfigSettings::iterator ite = iv_configurationSettings.find(groupName);
    if (ite == iv_configurationSettings.end()) { // the group doesn't exist
      return NULL;
    }
    SettingsForGroup & settings = (*ite).second;
    return settings.getNameValuePair(paramName);
  }

  const icu::UnicodeString & AnalysisEngineMetaData::getGroupNameWhenNotSpec() const {
    if (hasGroups()) {
      if (hasDefaultGroup()) {
        return getDefaultGroupName();
      } else {
        UIMA_EXC_THROW_NEW(ConfigParamLookupException,
                           UIMA_ERR_CONFIG_NO_DEFAULT_GROUP_DEFINED,
                           UIMA_MSG_ID_EXC_CONFIG_NO_DEFAULT_GROUP_DEFINED,
                           UIMA_MSG_ID_EXC_CONFIG_NO_DEFAULT_GROUP_DEFINED,
                           ErrorInfo::recoverable);
      }
    } else {
      return CONFIG_GROUP_NAME_WHEN_NO_GROUPS;
    }
  }


  /**
  * This behavior ensures that an aggregate TAESpecifier that contains groups can
  * redefine parameters for TAESpecifiers that don't contain a group:
  * the aggregate has to define the parameter in its default group.
  **/
  NameValuePair * AnalysisEngineMetaData::getNameValuePair(const icu::UnicodeString & paramName,
      const icu::UnicodeString & ancKey) {
    return getNameValuePair(getGroupNameWhenNotSpec(), paramName, getSearchStrategy(), ancKey);
  }

  NameValuePair *  AnalysisEngineMetaData::getNameValuePair(const icu::UnicodeString & groupName,
      const icu::UnicodeString & paramName,
      EnSearchStrategy strategy,
      const icu::UnicodeString & ancKey) {

    NameValuePair * value = getNameValuePairNoFallback(groupName, paramName, ancKey);

    if (EXISTS(value)) {
      return value;
    }

    //check the fallback groups, if any
    vector < icu::UnicodeString> fallbackGroups;
    generateFallbackGroups(groupName, strategy, fallbackGroups);
    size_t i=0;
    while (i< fallbackGroups.size() && (! EXISTS(value))) {
      value = getNameValuePairNoFallback(fallbackGroups[i], paramName, ancKey);
      i++;
    }

    if (EXISTS(value)) {
      return value;
    }

    //if we get here, one of the following holds true:
    // a) the parameter name is invalid
    // b) the parameter is defined, but no value is specified
    //check for a)
    bool isDefined = isParameterDefined(groupName, paramName, ancKey);
    i = 0;
    while (! isDefined && i < fallbackGroups.size()) {
      isDefined = isParameterDefined(fallbackGroups[i], paramName, ancKey);
      i++;
    }

    if (isDefined) { // case b)
      return NULL;
    } else { // a)
      if (hasGroups()) {
        ErrorMessage msg(UIMA_MSG_ID_EXC_CONFIG_PARAM_NOT_DEFINED_IN_GROUP);
        msg.addParam(paramName);
        msg.addParam(groupName);
        UIMA_EXC_THROW_NEW(ConfigParamLookupException,
                           UIMA_ERR_CONFIG_PARAM_NOT_DEFINED_IN_GROUP,
                           msg,
                           ErrorMessage(UIMA_MSG_ID_EXCON_CONFIG_PARAM_SEARCH, paramName),
                           ErrorInfo::recoverable);
      } else {
        UIMA_EXC_THROW_NEW(ConfigParamLookupException,
                           UIMA_ERR_CONFIG_PARAM_NOT_DEFINED,
                           ErrorMessage(UIMA_MSG_ID_EXC_CONFIG_PARAM_NOT_DEFINED, paramName),
                           ErrorMessage(UIMA_MSG_ID_EXCON_CONFIG_PARAM_SEARCH, paramName),
                           ErrorInfo::recoverable);
      }
    }
  }

  NameValuePair * AnalysisEngineMetaData::getNameValuePairNoFallback(const icu::UnicodeString & groupName,
      const icu::UnicodeString & paramName,
      const icu::UnicodeString & ancKey) {
    //sanity check
    if (! hasGroups()
        && (groupName.compare(CONFIG_GROUP_NAME_WHEN_NO_GROUPS) != 0)
       ) {
      // return UIMA_ERR_CONFIG_NO_GROUPS_DEFINED;
      ErrorMessage errmsgContext(UIMA_MSG_ID_EXCON_CONFIG_PARAM_IN_GROUP_SEARCH);
      errmsgContext.addParam(paramName);
      errmsgContext.addParam(groupName);
      UIMA_EXC_THROW_NEW(ConfigParamLookupException,
                         UIMA_ERR_CONFIG_NO_GROUPS_DEFINED,
                         UIMA_MSG_ID_EXC_CONFIG_NO_GROUPS_DEFINED,
                         errmsgContext,
                         ErrorInfo::recoverable);
    }

    //try to find the value for the exact group
    NameValuePair * value = getNameValuePairPtr(groupName, paramName);
    if (EXISTS(value)) {
      //check whether the parameter is defined for that group
      if (isParameterDefined(groupName, paramName, ancKey)) {
        return value;
      } else {
        //return UIMA_ERR_CONFIG_PARAM_NOT_DEFINED_IN_GROUP;
        if (hasGroups()) {
          ErrorMessage errmsgContext(UIMA_MSG_ID_EXCON_CONFIG_PARAM_IN_GROUP_SEARCH);
          errmsgContext.addParam(paramName);
          errmsgContext.addParam(groupName);
          ErrorMessage errmsgExc(UIMA_MSG_ID_EXC_CONFIG_PARAM_NOT_DEFINED_IN_GROUP);
          errmsgExc.addParam(paramName);
          errmsgExc.addParam(groupName);
          UIMA_EXC_THROW_NEW(ConfigParamLookupException,
                             UIMA_ERR_CONFIG_PARAM_NOT_DEFINED_IN_GROUP,
                             errmsgExc,
                             errmsgContext,
                             ErrorInfo::recoverable);
        } else {
          UIMA_EXC_THROW_NEW(ConfigParamLookupException,
                             UIMA_ERR_CONFIG_PARAM_NOT_DEFINED,
                             ErrorMessage(UIMA_MSG_ID_EXC_CONFIG_PARAM_NOT_DEFINED, paramName),
                             ErrorMessage(UIMA_MSG_ID_EXCON_CONFIG_PARAM_SEARCH, paramName),
                             ErrorInfo::recoverable);
        }
        return NULL;
      }
    } else {
      return NULL;
    }
  }

  TyErrorId AnalysisEngineMetaData::setNameValuePair(const icu::UnicodeString & groupName,
      const NameValuePair & nvPair) {

    if (iv_configurationGroups.size() == 0) {
      return UIMA_ERR_CONFIG_PARAM_NOT_DEFINED;
    }
    const icu::UnicodeString & paramName = nvPair.getName();
    TyConfigGroup::const_iterator ite = iv_configurationGroups.find(groupName);
    if (ite == iv_configurationGroups.end()) {
      return UIMA_ERR_CONFIG_INVALID_GROUP_NAME;
    }
    const ConfigurationParameter * pConfigParm = NULL;

    //now check whether the parameter is defined in the group
    //or in the common parameters
    const ConfigurationGroup & confGroup = ite->second;

    if (confGroup.hasConfigurationParameter(paramName)) {
      pConfigParm = confGroup.getConfigurationParameter(paramName);
    } else {
      //check in the common parameters
      ite = iv_configurationGroups.find(CONFIG_GROUP_NAME_COMMON_PARMS);
      if (ite == iv_configurationGroups.end()) { //there are no common parameters
        return UIMA_ERR_CONFIG_INVALID_PARAM_NAME;
      }
      const ConfigurationGroup & commonGroup = ite->second;
      if (commonGroup.hasConfigurationParameter(paramName)) {
        pConfigParm = commonGroup.getConfigurationParameter(paramName);
      } else {
        return UIMA_ERR_CONFIG_INVALID_PARAM_NAME;
      }
    }

    assert(EXISTS(pConfigParm));
    //check if types and multiplicity match
    if (pConfigParm->getType() != nvPair.getType()) {
      return UIMA_ERR_CONFIG_INVALID_TYPE_FOR_PARAM;
    }
    if ((pConfigParm->isMultiValued() && (! nvPair.isMultiValued())
         || ((! pConfigParm->isMultiValued() && nvPair.isMultiValued())))
       ) {
      return UIMA_ERR_CONFIG_INVALID_TYPE_FOR_PARAM;
    }

    NameValuePair * pair = new NameValuePair(nvPair);
    //we can be sure that the configuration parameter is valid
    addNameValuePair(groupName, pair);
    return UIMA_ERR_NONE;
  }

  void AnalysisEngineMetaData::generateFallbackGroups(const icu::UnicodeString & groupName,
      EnSearchStrategy strategy,
      vector < icu::UnicodeString> & fallbackGroups) {
    int i;
    bool cutOffPossible;
    switch (strategy) {
    case NONE:
      //nothing to be done
      break;
    case DEFAULT_FALLBACK:
      fallbackGroups.push_back(getDefaultGroupName());
      break;
    case LANGUAGE_FALLBACK:
      i=groupName.lastIndexOf("-");
      cutOffPossible = (i != -1);
      while (cutOffPossible) {
        icu::UnicodeString fallback;
        groupName.extract(0, i, fallback);
        fallbackGroups.push_back(fallback);
        i=groupName.lastIndexOf("-", 0,i);
        cutOffPossible = (i != -1);
      }
      fallbackGroups.push_back(getDefaultGroupName());
      break;
    default:
      assert(false);
    }
  }

  /**
  * returns TRUE iff paramName is defined and the configuration parameter is visible
  * to the annotator context with key ancKey.
  **/
  bool AnalysisEngineMetaData::isParameterDefined(const icu::UnicodeString & paramName,
      const icu::UnicodeString & ancKey) const {
    return isParameterDefined(CONFIG_GROUP_NAME_WHEN_NO_GROUPS, paramName, ancKey);
  }
  /**
  * returns TRUE iff paramName is either defined for group groupName or in the commonParameter section.
  * Moreover, the configuration parameter must be visible to the annotator context with key ancKey
  **/
  bool AnalysisEngineMetaData::isParameterDefined(const icu::UnicodeString & groupName,
      const icu::UnicodeString & paramName,
      const icu::UnicodeString & ancKey) const {
    //check if it's defined in the group groupName
    TyConfigGroup::const_iterator ite = iv_configurationGroups.find(groupName);
    if (ite != iv_configurationGroups.end()) {
      const ConfigurationGroup & group = ite->second;
      const ConfigurationParameter * pConfigParm = group.getConfigurationParameter(paramName);
      if (EXISTS(pConfigParm)) { //the parameter exists
        return pConfigParm->isDefinedForAnnotatorContext(ancKey);
      }
      /*          if (group.hasConfigurationParameter(paramName)) { */
      /*             return true;                                   */
      /*          }                                                 */
    }
    //either the group does not exist or it doesn't define the parameter
    //we check in the common parameters
    ite = iv_configurationGroups.find(CONFIG_GROUP_NAME_COMMON_PARMS);
    if (ite != iv_configurationGroups.end()) {
      const ConfigurationGroup & group = ite->second;
      const ConfigurationParameter * pConfigParm = group.getConfigurationParameter(paramName);
      if (EXISTS(pConfigParm)) { //the parameter exists
        return pConfigParm->isDefinedForAnnotatorContext(ancKey);
      } else {
        return false;
      }
      //return group.hasConfigurationParameter(paramName);
    } else {
      return false;
    }
  }

  const vector <icu::UnicodeString> AnalysisEngineMetaData::getConfigurationGroupNames() const {
    vector <icu::UnicodeString> groupNames;
    TyConfigGroup::const_iterator ite;
    for (ite = iv_configurationGroups.begin(); ite != iv_configurationGroups.end(); ite++) {
      const icu::UnicodeString & groupName = ite->first;
      if (CONFIG_GROUP_NAME_COMMON_PARMS.compare(groupName) != 0) {
        groupNames.push_back(groupName);
      }
    }
    return groupNames;
  }

  const vector <const ConfigurationParameter *> AnalysisEngineMetaData::getConfigurationParameters(const icu::UnicodeString & groupName) const {
    vector <const ConfigurationParameter *> confParams;
    TyConfigGroup::const_iterator ite = iv_configurationGroups.find(groupName);
    if (ite == iv_configurationGroups.end()) {
      return confParams;
    }

    //collect the parameters from the group
    const ConfigurationGroup & confGroup = ite->second;
    const vector <const ConfigurationParameter *> params = confGroup.getConfigurationParameters();
    size_t i=0;
    for (i=0; i < params.size(); i++) {
      confParams.push_back(params[i]);
    }

    //collect the parameters from the common group, if any
    if (CONFIG_GROUP_NAME_COMMON_PARMS.compare(groupName) != 0) {
      const vector <const ConfigurationParameter *> commonParams = getConfigurationParameters(CONFIG_GROUP_NAME_COMMON_PARMS);
      for (i=0; i < commonParams.size(); i++) {
        confParams.push_back(commonParams[i]);
      }
    }

    return confParams;
  }

  const vector <icu::UnicodeString > AnalysisEngineMetaData::getGroupNamesForParameter(const icu::UnicodeString & paramName) const {
    vector <icu::UnicodeString > groups;
    vector <icu::UnicodeString> allGroups = getConfigurationGroupNames();
    vector <icu::UnicodeString>::const_iterator ite;
    for (ite = allGroups.begin(); ite != allGroups.end(); ite++) {
      if (isParameterDefined(*ite, paramName, "")) {
        groups.push_back(*ite);
      }
    }
    if (isParameterDefined(CONFIG_GROUP_NAME_COMMON_PARMS, paramName, "") && hasDefaultGroup()) {
      groups.push_back(getDefaultGroupName());
    }
    return groups;
  }


  TyErrorId AnalysisEngineMetaData::addTypePriority(TypePriority * prio) {
    if (! isModifiable()) {
      return UIMA_ERR_CONFIG_OBJECT_COMITTED;
    }
    iv_vecpTypePriorities.push_back(prio);
    return UIMA_ERR_NONE;
  }

  void AnalysisEngineDescription::commit() {
    if (EXISTS(iv_pAeMetaData)) {
      iv_pAeMetaData->commit();
    }
    TyMapDelegateSpecs::iterator ite;
    for (ite=iv_pMapDelegateSpecifiers->begin(); ite != iv_pMapDelegateSpecifiers->end(); ite++) {
      AnalysisEngineDescription * del = ite->second;
      del->commit();
    }
    iv_bIsModifiable = false;
  }


  /*-------------------------------------------------------*/
  /*                                                       */
  /*   AnalysisEngineDescription implementation            */
  /*-------------------------------------------------------*/
  AnalysisEngineDescription * AnalysisEngineDescription::getDelegate(const icu::UnicodeString & key) const {
    TyMapDelegateSpecs::iterator ite = iv_pMapDelegateSpecifiers->find(key);
    if (ite == iv_pMapDelegateSpecifiers->end()) {
      return NULL;
    } else {
      return ite->second;
    }
  }

  AnalysisEngineDescription * AnalysisEngineDescription::extractDelegate(const icu::UnicodeString & key) {
    TyMapDelegateSpecs::iterator ite = iv_pMapDelegateSpecifiers->find(key);
    if (ite == iv_pMapDelegateSpecifiers->end()) {
      return NULL;
    } else {
      AnalysisEngineDescription * taeSpec = ite->second;
      iv_pMapDelegateSpecifiers->erase(ite);
      return taeSpec;
    }
  }

  void AnalysisEngineDescription::toXMLBuffer(icu::UnicodeString & s) const {
    s.removeBetween(0, s.length());
    toXMLBufferNoXMLHeader(s);
    s.insert(0, "<?xml version=\"1.0\"?>");
  }

  void AnalysisEngineDescription::validate() {
    try {
      //first, validate the delegate specs
      AnalysisEngineDescription::TyMapDelegateSpecs delegates = getDelegates();
      AnalysisEngineDescription::TyMapDelegateSpecs::iterator ite = delegates.begin();
      while (ite != delegates.end()) {
		ite->second->validate();
        ite++;
      }

      //merge the type systems
      TypeSystemDescription * typeDesc = getAnalysisEngineMetaData()->getTypeSystemDescription();
      for (ite=delegates.begin(); ite != delegates.end(); ite++) {
        TypeSystemDescription * typeDescDel = ite->second->getAnalysisEngineMetaData()->getTypeSystemDescription();
        typeDesc->mergeTypeDescriptions(typeDescDel->getTypeDescriptions());
      }

      getAnalysisEngineMetaData()->validate();
      //tbd: validate the flow constraints
    } catch (ValidationException & rclException) {
      rclException.getErrorInfo().addContext(ErrorMessage(UIMA_MSG_ID_EXCON_VALIDATE_TAE_SPEC_FROM_FILE, getXmlFileLocation()));
      throw rclException;
    }
  }

  void appendCapabilities(Capability::TyVecCapabilityTofs const & v, char const * xmlTag, icu::UnicodeString & s) {
    size_t i;
    for (i=0; i<v.size(); ++i) {
      s.append("<");
      s.append(xmlTag);
      s.append(">");

      s.append(v[i]);

      s.append("</");
      s.append(xmlTag);
      s.append(">");
    }
  }

  void appendSofaName(Capability::TyVecCapabilitySofas const & v, char const * xmlTag, icu::UnicodeString & s) {
    size_t i;
    for (i=0; i<v.size(); ++i) {
      s.append("<");
      s.append(xmlTag);
      s.append(">");

      s.append(v[i]);

      s.append("</");
      s.append(xmlTag);
      s.append(">");
    }
  }

  void appendBool(bool b, icu::UnicodeString & s) {
    if (b) {
      s.append("true");
    } else {
      s.append("false");
    }
  }

  void appendFloat(float f, icu::UnicodeString & s) {
    char c[256];
    sprintf(c, "%f", f);
    s.append(c);
  }

  void appendInt(int i, icu::UnicodeString & s) {
    char c[256];
    sprintf(c, "%d", i);
    s.append(c);
  }


  void AnalysisEngineDescription::appendConfigGroupToXMLBuffer(ConfigurationGroup const & config, icu::UnicodeString & s) const {
    size_t i;
    vector<ConfigurationParameter const *> configParams = config.getConfigurationParameters();
    for (i=0; i<configParams.size(); ++i) {
      ConfigurationParameter const * confParam = configParams[i];
      s.append("<configurationParameter>");
      s.append("<name>");
      s.append(confParam->getName());
      s.append("</name>");
      s.append("<description>");
      s.append(confParam->getDescription());
      s.append("</description>");
      s.append("<type>");
      ConfigurationParameter::EnParameterType paramType = confParam->getType();
      switch (paramType) {
      case ConfigurationParameter::BOOLEAN:
        s.append("Boolean");
        break;
      case ConfigurationParameter::FLOAT:
        s.append("Float");
        break;
      case ConfigurationParameter::INTEGER:
        s.append("Integer");
        break;
      case ConfigurationParameter::STRING:
        s.append("String");
        break;
      default:
        assert(false);
      }
      s.append("</type>");
      s.append("<multiValued>");
      appendBool(confParam->isMultiValued(), s);
      s.append("</multiValued>");
      s.append("<mandatory>");
      appendBool(confParam->isMandatory(), s);
      s.append("</mandatory>");
      s.append("</configurationParameter>");
    }
  }

  void AnalysisEngineDescription::appendConfigGroupSettingsToXMLBuffer(SettingsForGroup const & settings, icu::UnicodeString & s) const {
    size_t i,j;
    vector<NameValuePair const *> nvps = settings.getNameValuePairs();
    for (i=0; i<nvps.size(); ++i) {
      NameValuePair const * nvp = nvps[i];
      s.append("<nameValuePair>");
      s.append("<name>");
      s.append( nvp->getName() );
      s.append("</name>");

      s.append("<value>");

      ConfigurationParameter::EnParameterType paramType = nvp->getType();
      if (nvp->isMultiValued()) {
        s.append("<array>");

        switch (paramType) {
        case ConfigurationParameter::BOOLEAN: {
            vector<bool> const & v = nvp->extractBoolValues();
            for (j=0; j<v.size(); ++j) {
              s.append("<boolean>");
              appendBool(v[j], s);
              s.append("</boolean>");
            }
            break;
          }
        case ConfigurationParameter::FLOAT: {
            vector<float> const & v = nvp->extractFloatValues();
            for (j=0; j<v.size(); ++j) {
              s.append("<float>");
              appendFloat(v[j], s);
              s.append("</float>");
            }
            break;
          }
        case ConfigurationParameter::INTEGER: {
            vector<int> const & v = nvp->extractIntValues();
            for (j=0; j<v.size(); ++j) {
              s.append("<integer>");
              appendInt(v[j], s);
              s.append("</integer>");
            }
            break;
          }
        case ConfigurationParameter::STRING: {
            vector<icu::UnicodeString> const & v = nvp->extractStringValues();
            for (j=0; j<v.size(); ++j) {
              s.append("<string>");
              s.append(v[j]);
              s.append("</string>");
            }
            break;
          }
        default:
          assert(false);
        }

        s.append("</array>");
      } else {
        switch (paramType) {
        case ConfigurationParameter::BOOLEAN: {
            bool v = nvp->extractBoolValue();
            s.append("<boolean>");
            appendBool(v, s);
            s.append("</boolean>");
            break;
          }
        case ConfigurationParameter::FLOAT: {
            float v = nvp->extractFloatValue();
            s.append("<float>");
            appendFloat(v, s);
            s.append("</float>");
            break;
          }
        case ConfigurationParameter::INTEGER: {
            int v = nvp->extractIntValue();
            s.append("<integer>");
            appendInt(v, s);
            s.append("</integer>");
            break;
          }
        case ConfigurationParameter::STRING: {
            icu::UnicodeString const & v = nvp->extractStringValue();
            s.append("<string>");
            s.append(v);
            s.append("</string>");
            break;
          }
        default:
          assert(false);
        }

      }

      s.append("</value>");
      s.append("</nameValuePair>");
    }
  }




  void  AnalysisEngineDescription::appendToXMLBuffer
  (AnalysisEngineMetaData::TyVecpFSIndexDescriptions const & fsDesc,
   icu::UnicodeString & s) {

    size_t i,j;
    s.append("<fsIndexes>");
    AnalysisEngineMetaData::TyVecpFSIndexDescriptions const & ixVec = fsDesc;
    for (i=0; i<ixVec.size(); ++i) {
      FSIndexDescription const * ixDesc = ixVec[i];
      s.append("<fsIndexDescription>");
      s.append("<label>");
      s.append(ixDesc->getLabel());
      s.append("</label>");
      s.append("<typeName>");
      s.append(ixDesc->getTypeName());
      s.append("</typeName>");
      s.append("<kind>");
      FSIndexDescription::EnIndexKind ixKind = ixDesc->getIndexKind();
      switch (ixKind) {
      case FSIndexDescription::BAG:
        s.append("bag");
        break;
      case FSIndexDescription::SET:
        s.append("set");
        break;
      case FSIndexDescription::SORTED:
        s.append("sorted");
        break;
      default:
        assert(false);
      }
      s.append("</kind>");

      FSIndexDescription::TyVecpFSIndexKeys const & keyVec = ixDesc->getFSIndexKeys();
      if (keyVec.size() > 0) {
        s.append("<keys>");
        for (j=0; j<keyVec.size(); ++j) {
          s.append("<fsIndexKey>");
          FSIndexKeyDescription const * ixKeyDesc = keyVec[j];
          if (ixKeyDesc->isTypePriority() ) {
            s.append("<typePriority/>");
          } else {
              s.append("<featureName>");
              s.append(ixKeyDesc->getFeatureName());
              s.append("</featureName>");

              s.append("<comparator>");
              FSIndexKeyDescription::EnComparatorType comp = ixKeyDesc->getComparator();
              switch (comp) {
              case FSIndexKeyDescription::STANDARD:
                s.append("standard");
                break;
              case FSIndexKeyDescription::REVERSE:
                s.append("reverse");
                break;
              default:
                assert(false);
              }
            s.append("</comparator>");
          }
          s.append("</fsIndexKey>");
        }
        s.append("</keys>");
      }

      s.append("</fsIndexDescription>");
    }

    s.append("</fsIndexes>");

  }



  void AnalysisEngineDescription::appendToXMLBuffer
  (AnalysisEngineMetaData::TyVecpTypePriorities const & prioDesc,
   icu::UnicodeString & s) {
    size_t i,j;
    if (prioDesc.size() > 0) {
      s.append("<typePriorities>");
      for (i=0; i<prioDesc.size() ;++i) {
        s.append("<priorityList>");
        TypePriority * prio = prioDesc[i];
        vector <icu::UnicodeString> vecTypeOrder = prio->getTypeOrder();
        for ( j = 0; j < vecTypeOrder.size();  ++j) {

          s.append("<type>");
          s.append(vecTypeOrder[j]);
          s.append("</type>");
        }
        s.append("</priorityList>");
      }
      s.append("</typePriorities>");
    }
  }


  void AnalysisEngineDescription::appendToXMLBuffer
  (AnalysisEngineDescription::TyVecpSofaMappings const & sofaMapDesc,
   icu::UnicodeString & s) {
    size_t i;
    AnalysisEngineDescription::TyVecpSofaMappings const & sofamappingVec = sofaMapDesc;
    if (sofamappingVec.size() >  0) {
      s.append("<sofaMappings>");
      for (i=0; i<sofamappingVec.size(); ++i) {
        s.append("<sofaMapping>");
        s.append("<componentKey>");
        s.append(sofamappingVec[i]->getComponentKey());
        s.append("</componentKey>");

        s.append("<componentSofaName>");
        s.append(sofamappingVec[i]->getComponentSofaName());
        s.append("</componentSofaName>");

        s.append("<aggregateSofaName>");
        s.append(sofamappingVec[i]->getAggregateSofaName());
        s.append("</aggregateSofaName>");

        s.append("</sofaMapping>");
      }
      s.append("</sofaMappings>");
    }
  }



  void AnalysisEngineDescription::appendConfigParamsAndSettingsToXMLBuffer(UnicodeString & s) const  {


    AnalysisEngineMetaData const & md = * getAnalysisEngineMetaData();
    // config params
    if (md.hasGroups()) {
      s.append("<configurationParameters");

      if (md.hasDefaultGroup()) {
        s.append(" defaultGroup=\"");
        s.append( md.iv_defaultGroup );
        s.append("\"");
      }

      s.append(" searchStrategy=\"");
      AnalysisEngineMetaData::EnSearchStrategy searchStrategy = md.getSearchStrategy();
      switch (searchStrategy) {
      case AnalysisEngineMetaData::DEFAULT_FALLBACK:
        s.append("default_fallback");
        break;
      case AnalysisEngineMetaData::LANGUAGE_FALLBACK:
        s.append("language_fallback");
        break;
      case AnalysisEngineMetaData::NONE:
        s.append("none");
        break;
      }
      s.append("\">");

      AnalysisEngineMetaData::TyConfigGroup const & confGroups = md.iv_configurationGroups;
      assert( confGroups.find(md.CONFIG_GROUP_NAME_WHEN_NO_GROUPS) == confGroups.end() );
      AnalysisEngineMetaData::TyConfigGroup::const_iterator cit;
      for ( cit = confGroups.begin(); cit != confGroups.end(); ++cit) {
        icu::UnicodeString const & confGroupName = (*cit).first;
        ConfigurationGroup const & confGroup = (*cit).second;
        bool common = ( confGroupName == md.CONFIG_GROUP_NAME_COMMON_PARMS);
        if (common) {
          s.append("<commonParameters>");
        } else {
          s.append("<configurationGroup names=\"");
          s.append(confGroupName);
          s.append("\">");
        }

        appendConfigGroupToXMLBuffer( confGroup, s);

        if (common) {
          s.append("</commonParameters>");
        } else {
          s.append("</configurationGroup>");
        }
      }
      s.append("</configurationParameters>");

    } else {
      s.append("<configurationParameters>");
      AnalysisEngineMetaData::TyConfigGroup const & confGroups = md.iv_configurationGroups;
      assert( confGroups.find(md.CONFIG_GROUP_NAME_COMMON_PARMS) == confGroups.end() );
      if (confGroups.size() > 0) {
        assert( confGroups.size() == 1);
        AnalysisEngineMetaData::TyConfigGroup::const_iterator cit = confGroups.find(md.CONFIG_GROUP_NAME_WHEN_NO_GROUPS);
        assert( cit != confGroups.end() );
        appendConfigGroupToXMLBuffer( (*cit).second, s);
      }
      s.append("</configurationParameters>");
    }


    s.append("<configurationParameterSettings>");
    // config param settings
    if (md.hasGroups()) {
      AnalysisEngineMetaData::TyConfigSettings const & confSettings = md.iv_configurationSettings;
      AnalysisEngineMetaData::TyConfigSettings::const_iterator cit;
      for (cit = confSettings.begin(); cit != confSettings.end(); ++cit) {
        icu::UnicodeString const & groupName = (*cit).first;
        SettingsForGroup const & settings = (*cit).second;

        s.append("<settingsForGroup name=\"");
        s.append(groupName);
        s.append("\">");
        appendConfigGroupSettingsToXMLBuffer(settings, s);
        s.append("</settingsForGroup>");
      }

    } else {
      AnalysisEngineMetaData::TyConfigSettings const & confSettings = md.iv_configurationSettings;
      if (confSettings.size() > 0) {
        assert( confSettings.size() == 1);
        AnalysisEngineMetaData::TyConfigSettings::const_iterator cit = confSettings.find(md.CONFIG_GROUP_NAME_WHEN_NO_GROUPS);
        assert( cit != confSettings.end() );
        appendConfigGroupSettingsToXMLBuffer( (*cit).second, s);
      }
    }
    s.append("</configurationParameterSettings>");


  }




  void AnalysisEngineDescription::toXMLBufferNoXMLHeader(icu::UnicodeString & s) const {
    size_t i;
    bool isCasConsumer=false;
    if ( getXmlRootTag().compare("casConsumerDescription") == 0) {
      isCasConsumer=true;
    }

    s = "<";
    s.append(getXmlRootTag());
    s.append(" xmlns=\"" UIMA_XML_NAMESPACE "\">");

    // framework
    s.append("<frameworkImplementation>");
    EnFrameworkImplName fwName = getFrameworkImplName();
    switch (fwName) {
    case CPLUSPLUS:
      s.append("org.apache.uima.cpp");
      break;
    case JAVA:
      s.append("org.apache.uima.java");
      break;
    default:
      assert(false);
    };
    s.append("</frameworkImplementation>");


    if (isCasConsumer) {
      s.append("<implementationName>");
      s.append(getAnnotatorImpName());
      s.append("</implementationName>");
    }
    // primitive
    else  {
      // primitive
      s.append("<primitive>");
      appendBool(isPrimitive(), s);
      s.append("</primitive>");

      if (isPrimitive()) {
        // annotator implementation
        s.append("<annotatorImplementationName>");
        s.append(getAnnotatorImpName());
        s.append("</annotatorImplementationName>");
      } else {
        // delegates
        s.append("<delegateAnalysisEngineSpecifiers>");
        TyMapDelegateSpecs const & delegates = getDelegates();
        TyMapDelegateSpecs::const_iterator cit;
        for (cit = delegates.begin(); cit != delegates.end(); ++cit) {
          s.append("<delegateAnalysisEngine key=\"");
          s.append( (*cit).first );
          s.append("\">");
          icu::UnicodeString delBuf;
          (*cit).second->toXMLBufferNoXMLHeader(delBuf);
          s.append(delBuf);
          s.append("</delegateAnalysisEngine>");
        }
        s.append("</delegateAnalysisEngineSpecifiers>");
      }
    }

	toXMLBuffer( *(getAnalysisEngineMetaData()), isCasConsumer, s);

	if (!isCasConsumer) {
      TyVecpSofaMappings const & sofamappingVec = getSofaMappings();
      if (sofamappingVec.size() >  0) {
        s.append("<sofaMappings>");
        for (i=0; i<sofamappingVec.size(); ++i) {
          s.append("<sofaMapping>");
          s.append("<componentKey>");
          s.append(sofamappingVec[i]->getComponentKey());
          s.append("</componentKey>");

          s.append("<componentSofaName>");
          s.append(sofamappingVec[i]->getComponentSofaName());
          s.append("</componentSofaName>");

          s.append("<aggregateSofaName>");
          s.append(sofamappingVec[i]->getAggregateSofaName());
          s.append("</aggregateSofaName>");

          s.append("</sofaMapping>");
        }
        s.append("</sofaMappings>");
      }
    }

    s.append("</");
    s.append(getXmlRootTag());
    s.append(">");


  }

  void AnalysisEngineDescription::toXMLBuffer(AnalysisEngineMetaData const & md,  
													   bool isCasConsumer,
													   icu::UnicodeString & s) const {
    size_t i,j;
    // AE Meta data
	
    if (isCasConsumer) {
      s.append("<processingResourceMetaData>");
    } else s.append("<analysisEngineMetaData xmlns=\"http://uima.apache.org/resourceSpecifier\">");
    

    ///AnalysisEngineMetaData const & md = * getAnalysisEngineMetaData();
    
    //    name
    UnicodeString out;
    s.append("<name>");
    XMLWriterABase::normalize(UnicodeStringRef(md.getName()), out);
    s.append(out);
    s.append("</name>");

    //   description
    s.append("<description>");
    out.setTo("");
    XMLWriterABase::normalize(UnicodeStringRef(md.getDescription()), out);
    s.append( out );
    s.append("</description>");

    //   version
    s.append("<version>");
    s.append( md.getVersion() );
    s.append("</version>");

    //   vendor
    s.append("<vendor>");
    out.setTo("");
     XMLWriterABase::normalize(UnicodeStringRef(md.getVendor()), out);
    s.append( out );
    s.append("</vendor>");


    // config params
    if (md.hasGroups()) {
      s.append("<configurationParameters");

      if (md.hasDefaultGroup()) {
        s.append(" defaultGroup=\"");
        s.append( md.iv_defaultGroup );
        s.append("\"");
      }

      s.append(" searchStrategy=\"");
      AnalysisEngineMetaData::EnSearchStrategy searchStrategy = md.getSearchStrategy();
      switch (searchStrategy) {
      case AnalysisEngineMetaData::DEFAULT_FALLBACK:
        s.append("default_fallback");
        break;
      case AnalysisEngineMetaData::LANGUAGE_FALLBACK:
        s.append("language_fallback");
        break;
      case AnalysisEngineMetaData::NONE:
        s.append("none");
        break;
      }
      s.append("\">");

      AnalysisEngineMetaData::TyConfigGroup const & confGroups = md.iv_configurationGroups;
      assert( confGroups.find(md.CONFIG_GROUP_NAME_WHEN_NO_GROUPS) == confGroups.end() );
      AnalysisEngineMetaData::TyConfigGroup::const_iterator cit;
      for ( cit = confGroups.begin(); cit != confGroups.end(); ++cit) {
        icu::UnicodeString const & confGroupName = (*cit).first;
        ConfigurationGroup const & confGroup = (*cit).second;
        bool common = ( confGroupName == md.CONFIG_GROUP_NAME_COMMON_PARMS);
        if (common) {
          s.append("<commonParameters>");
        } else {
          s.append("<configurationGroup names=\"");
          s.append(confGroupName);
          s.append("\">");
        }

        appendConfigGroupToXMLBuffer( confGroup, s);

        if (common) {
          s.append("</commonParameters>");
        } else {
          s.append("</configurationGroup>");
        }
      }
      s.append("</configurationParameters>");

    } else {
      s.append("<configurationParameters>");
      AnalysisEngineMetaData::TyConfigGroup const & confGroups = md.iv_configurationGroups;
      assert( confGroups.find(md.CONFIG_GROUP_NAME_COMMON_PARMS) == confGroups.end() );
      if (confGroups.size() > 0) {
        assert( confGroups.size() == 1);
        AnalysisEngineMetaData::TyConfigGroup::const_iterator cit = confGroups.find(md.CONFIG_GROUP_NAME_WHEN_NO_GROUPS);
        assert( cit != confGroups.end() );
        appendConfigGroupToXMLBuffer( (*cit).second, s);
      }
      s.append("</configurationParameters>");
    }


    s.append("<configurationParameterSettings>");
    // config param settings
    if (md.hasGroups()) {
      AnalysisEngineMetaData::TyConfigSettings const & confSettings = md.iv_configurationSettings;
      AnalysisEngineMetaData::TyConfigSettings::const_iterator cit;
      for (cit = confSettings.begin(); cit != confSettings.end(); ++cit) {
        icu::UnicodeString const & groupName = (*cit).first;
        SettingsForGroup const & settings = (*cit).second;

        s.append("<settingsForGroup name=\"");
        s.append(groupName);
        s.append("\">");
        appendConfigGroupSettingsToXMLBuffer(settings, s);
        s.append("</settingsForGroup>");
      }

    } else {
      AnalysisEngineMetaData::TyConfigSettings const & confSettings = md.iv_configurationSettings;
      if (confSettings.size() > 0) {
        assert( confSettings.size() == 1);
        AnalysisEngineMetaData::TyConfigSettings::const_iterator cit = confSettings.find(md.CONFIG_GROUP_NAME_WHEN_NO_GROUPS);
        assert( cit != confSettings.end() );
        appendConfigGroupSettingsToXMLBuffer( (*cit).second, s);
      }
    }
    s.append("</configurationParameterSettings>");

    // flow constraints
    if (!isPrimitive()) {
      s.append("<flowConstraints>");
      FlowConstraints const * pFlow = md.getFlowConstraints();
      FlowConstraints * flow = CONST_CAST(FlowConstraints *, pFlow);
      if (flow->getFlowConstraintsType() == FlowConstraints::FIXED) {
        s.append("<fixedFlow>");
      } else if (flow->getFlowConstraintsType() == FlowConstraints::CAPABILITYLANGUAGE) {
        s.append("<capabilityLanguageFlow>");
      }
      vector<icu::UnicodeString> const & v = flow->getNodes();
      for (i=0; i<v.size(); ++i) {
        s.append("<node>");
        s.append(v[i]);
        s.append("</node>");
      }
      if (flow->getFlowConstraintsType() == FlowConstraints::FIXED) {
        s.append("</fixedFlow>");
      }  else if (flow->getFlowConstraintsType() == FlowConstraints::CAPABILITYLANGUAGE) {
        s.append("</capabilityLanguageFlow>");
      }

      s.append("</flowConstraints>");
    }

    //type priorites
    const AnalysisEngineMetaData::TyVecpTypePriorities  & prioDesc =  
                    md.getTypePriorities();
     if (prioDesc.size() > 0) {
      s.append("<typePriorities>");
      for (i=0; i<prioDesc.size() ;++i) {
        s.append("<priorityList>");
        TypePriority * prio = prioDesc[i];
        vector <icu::UnicodeString> vecTypeOrder = prio->getTypeOrder();
        for ( j = 0; j < vecTypeOrder.size();  ++j) {

          s.append("<type>");
          s.append(vecTypeOrder[j]);
          s.append("</type>");
        }
        s.append("</priorityList>");
      }
      s.append("</typePriorities>");
    }

    // type system

    if (isPrimitive()) {
      s.append("<typeSystemDescription>");
      TypeSystemDescription const * typeDesc = md.getTypeSystemDescription();
      if (typeDesc != NULL) {
        TypeSystemDescription::TyVecpImportDescriptions const & importVec = typeDesc->getImportDescriptions();
        s.append("<imports>");
        for (i=0; i<importVec.size(); ++i) {
          ImportDescription const * pImport = importVec[i];
          if ( pImport->getName().length() > 0) {
            s.append("<import name=\"");
            s.append(pImport->getName());
            s.append("\"/>");
          } else {
            s.append("<import location=\"");
            s.append(pImport->getLocation());
            s.append("\"/>");
          }
        }
        s.append("</imports><types>");

        TypeSystemDescription::TyVecpTypeDescriptions const & tdVec = typeDesc->getTypeDescriptions();
        for (i=0; i<tdVec.size(); ++i) {
          TypeDescription const * td = tdVec[i];
          s.append("<typeDescription>");
          s.append("<name>");
          s.append(td->getName());
          s.append("</name>");

          s.append("<description>");
          out.setTo("");
          XMLWriterABase::normalize(UnicodeStringRef(td->getDescription()), out);
          s.append(out);
          s.append("</description>");

          s.append("<supertypeName>");
          s.append(td->getSuperTypeName());
          s.append("</supertypeName>");

          TypeDescription::TyVecpFeatureDescriptions const & fdVec = td->getFeatureDescriptions();
          if (fdVec.size() > 0) {
            s.append("<features>");
            for (j=0; j<fdVec.size(); ++j) {
              FeatureDescription const * fs = fdVec[j];
              s.append("<featureDescription>");
              s.append("<name>");
              s.append(fs->getName());
              s.append("</name>");
              s.append("<description>");
              out.setTo("");
              XMLWriterABase::normalize(UnicodeStringRef(fs->getDescription()), out);
              s.append(out);
              s.append("</description>");
              s.append("<rangeTypeName>");
              s.append(fs->getRangeTypeName());
              s.append("</rangeTypeName>");
              if (0 < fs->getElementType().length() ) {
                s.append("<elementType>");
                s.append(fs->getElementType());
                s.append("</elementType>");
              }
              if (fs->isMultipleReferencesAllowed() ) {
                s.append("<multipleReferencesAllowed>");
                s.append("true");
                s.append("</multipleReferencesAllowed>");
              }
              s.append("</featureDescription>");
            }
            s.append("</features>");
          }

          TypeDescription::TyVecpAllowedValues const & allowVec = td->getAllowedValues();
          if (allowVec.size() > 0) {
            s.append("<allowedValues>");
            for (j=0; j<allowVec.size(); ++j) {
              AllowedValue const * value = allowVec[j];
              s.append("<value>");
              s.append("<string>");
              s.append(value->getName());
              s.append("</string>");
              s.append("<description>");
              out.setTo("");
              XMLWriterABase::normalize(UnicodeStringRef(value->getDescription()), out);
              s.append(out);
              s.append("</description>");
              s.append("</value>");
            }
            s.append("</allowedValues>");
          }

          s.append("</typeDescription>");
        }
      }
      s.append("</types></typeSystemDescription>");
    }

    //fsIndexCollection
    s.append("<fsIndexCollection>");
    //fsIndexCollection -- imports
    AnalysisEngineMetaData::TyVecpFSIndexImportDescriptions const & ixImportVec = md.getFSIndexImportDescriptions();
    if (ixImportVec.size() > 0 ) {
      s.append("<imports>");
      for (size_t i=0; i < ixImportVec.size(); i++) {
        ImportDescription const * pImport = ixImportVec[i];
        if ( pImport->getName().length() > 0) {
          s.append("<import name=\"");
          s.append(pImport->getName());
          s.append("\"/>");
        } else {
          s.append("<import location=\"");
          s.append(pImport->getLocation());
          s.append("\"/>");
        }
      }
      s.append("</imports>");
    }

    // fs indexes
    s.append("<fsIndexes>");
    AnalysisEngineMetaData::TyVecpFSIndexDescriptions const & ixVec = md.getFSIndexDescriptions();
    for (i=0; i<ixVec.size(); ++i) {
      FSIndexDescription const * ixDesc = ixVec[i];
      s.append("<fsIndexDescription>");
      s.append("<label>");
      s.append(ixDesc->getLabel());
      s.append("</label>");
      s.append("<typeName>");
      s.append(ixDesc->getTypeName());
      s.append("</typeName>");
      s.append("<kind>");
      FSIndexDescription::EnIndexKind ixKind = ixDesc->getIndexKind();
      switch (ixKind) {
      case FSIndexDescription::BAG:
        s.append("bag");
        break;
      case FSIndexDescription::SET:
        s.append("set");
        break;
      case FSIndexDescription::SORTED:
        s.append("sorted");
        break;
      default:
        assert(false);
      }
      s.append("</kind>");

      FSIndexDescription::TyVecpFSIndexKeys const & keyVec = ixDesc->getFSIndexKeys();
      if (keyVec.size() > 0) {
        s.append("<keys>");
        for (j=0; j<keyVec.size(); ++j) {
          s.append("<fsIndexKey>");
          FSIndexKeyDescription const * ixKeyDesc = keyVec[j];
          if (ixKeyDesc->isTypePriority() ) {
            s.append("<typePriority/>");
          } else {
            s.append("<featureName>");
            s.append(ixKeyDesc->getFeatureName());
            s.append("</featureName>");

            s.append("<comparator>");
            FSIndexKeyDescription::EnComparatorType comp = ixKeyDesc->getComparator();
            switch (comp) {
            case FSIndexKeyDescription::STANDARD:
              s.append("standard");
              break;
            case FSIndexKeyDescription::REVERSE:
              s.append("reverse");
              break;
            default:
              assert(false);
            }
            s.append("</comparator>");
          }
          s.append("</fsIndexKey>");
        }
        s.append("</keys>");
      }

      s.append("</fsIndexDescription>");
    }

    s.append("</fsIndexes>");

    s.append("</fsIndexCollection>");

    // capabilities
    s.append("<capabilities>");
    AnalysisEngineMetaData::TyVecpCapabilities const & capVec = md.getCapabilites();
    for (i=0; i<capVec.size(); ++i) {
      Capability const * cap = capVec[i];
      s.append("<capability>");
      s.append("<inputs>");
      appendCapabilities( cap->getCapabilityTypes(Capability::INPUT), "type", s);
      appendCapabilities( cap->getCapabilityFeatures(Capability::INPUT), "feature", s);
      s.append("</inputs>");
      s.append("<outputs>");
      appendCapabilities( cap->getCapabilityTypes(Capability::OUTPUT), "type", s);
      appendCapabilities( cap->getCapabilityFeatures(Capability::OUTPUT), "feature", s);
      s.append("</outputs>");

      s.append("<inputSofas>");
      appendCapabilities( cap->getCapabilitySofas(Capability::INPUTSOFA), "sofaName", s);
      s.append("</inputSofas>");

      s.append("<outputSofas>");
      appendCapabilities( cap->getCapabilitySofas(Capability::OUTPUTSOFA), "sofaName", s);
      s.append("</outputSofas>");


      s.append("<languagesSupported>");
      Capability::TyVecCapabilityLanguages const & suppLangVec = cap->getSupportedLanguages();
      for (j=0; j<suppLangVec.size(); ++j) {
        s.append("<language>");
        s.append(suppLangVec[j]);
        s.append("</language>");
      }
      s.append("</languagesSupported>");

      s.append("</capability>");
    }

    s.append("</capabilities>");
    
    if (this->getAnalysisEngineMetaData()->getOperationalProperties() != 0) {
      s.append("<operationalProperties>"); 
      s.append ("<modifiesCas>");
      appendBool(this->getAnalysisEngineMetaData()->getOperationalProperties()->getModifiesCas(), s);
      s.append ("</modifiesCas>");
      s.append ("<multipleDeploymentAllowed>");
      appendBool(this->getAnalysisEngineMetaData()->getOperationalProperties()->isMultipleDeploymentAllowed(), s);
      s.append("</multipleDeploymentAllowed>");
      s.append("<outputsNewCASes>");
      appendBool(this->getAnalysisEngineMetaData()->getOperationalProperties()->getOutputsNewCASes(), s);
      s.append("</outputsNewCASes>");
      s.append("</operationalProperties>");
    } else {
      s.append("<operationalProperties>"); 
      s.append ("<modifiesCas>true</modifiesCas>");
      s.append("<multipleDeploymentAllowed>true</multipleDeploymentAllowed>");
      s.append("<outputsNewCASes>false</outputsNewCASes>");
      s.append("</operationalProperties>");
    }
    if (isCasConsumer) {
      s.append("</processingResourceMetaData>");
    } else s.append("</analysisEngineMetaData>");
	
 }

    
} //namespace



