/** \file taespecifierbuilder.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:

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


-------------------------------------------------------------------------- */


/* ----------------------------------------------------------------------- */
/*       Include dependencies                                              */
/* ----------------------------------------------------------------------- */
#include "uima/pragmas.hpp"

#include <memory>
#include "uima/engine.hpp"
#include "uima/typesystem.hpp"
//#define DEBUG_VERBOSE

#include "xercesc/util/PlatformUtils.hpp"
#include "xercesc/parsers/XercesDOMParser.hpp"
#include "xercesc/parsers/SAXParser.hpp"
#include "xercesc/dom/DOMException.hpp"
#include "xercesc/dom/DOMNamedNodeMap.hpp"
#include "xercesc/dom/DOMDocument.hpp"
#include "xercesc/dom/DOMElement.hpp"
#include "xercesc/dom/DOMNodeList.hpp"

#include "xercesc/sax/ErrorHandler.hpp"
#include "xercesc/sax/AttributeList.hpp"
#include "xercesc/sax/SAXParseException.hpp"
#include "xercesc/framework/LocalFileInputSource.hpp"
#include "xercesc/framework/MemBufInputSource.hpp"

#include "uima/taespecifierbuilder.hpp"
#include "uima/xmlerror_handler.hpp"
#include "uima/strtools.hpp"
#include "uima/stltools.hpp"
#include "uima/err_ids.h"
#include "uima/resmgr.hpp"

#include "uima/location.hpp"
#include "uima/envvar.hpp"

#include "uima/msg.h"
#define MAXXMLCHBUFF 512
using namespace std;
namespace uima {

  UIMA_EXC_CLASSIMPLEMENT(InvalidXMLException, uima::Exception);

  static XMLCh gs_tempXMLChBuffer[ MAXXMLCHBUFF ];

  XMLParser::XMLParser()
      :iv_pXMLErrorHandler(NULL) {}

  XMLParser::~XMLParser() {}

  
  void XMLParser::setErrorHandler(ErrorHandler * pErrorHandler) {
    iv_pXMLErrorHandler = pErrorHandler;
  }

   void XMLParser::parseAnalysisEngineDescription(AnalysisEngineDescription & aeSpec,
      char const * fileName) {
    // convert to unicode using default converter for platform
    icu::UnicodeString ustrFileName(fileName);
    parseAnalysisEngineDescription(aeSpec, ustrFileName );
  }


  void XMLParser::parseAnalysisEngineDescription(AnalysisEngineDescription & taeSpec,
      icu::UnicodeString const & fileName) {

    icu::UnicodeString const & fn = ResourceManager::resolveFilename(fileName, ".");
    size_t uiLen = fn.length();
    auto_array<UChar> arBuffer( new UChar[uiLen + 1] );
    assert( EXISTS(arBuffer.get()));

    fn.extract(0, uiLen, arBuffer.get());
    (arBuffer.get())[uiLen] = 0; // terminate the buffer with 0
    assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");

    // the following try catch block just to trigger an exception.
    // The constructor of LocalFileInputSource throws an exception on the UNIXes if the file does not
    // exist. On Windows, the parser throws this exception.
    try {
      LocalFileInputSource fileISOnlyForException((XMLCh const *) arBuffer.get() );
    } catch (XMLException const & e) {
      ErrorInfo errInfo;
      errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
      ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
      assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
      msg.addParam( arBuffer.get() );
      msg.addParam( 0 );
      msg.addParam( 0 );
      msg.addParam( (UChar const *) e.getMessage());
      errInfo.setMessage(msg);
      errInfo.setSeverity(ErrorInfo::unrecoverable);
      ExcIllFormedInputError exc(errInfo);
      throw exc;
    }

    LocalFileInputSource fileIS((XMLCh const *) arBuffer.get() ); 
    parseAnalysisEngineDescription(taeSpec, fileIS);
  }


  void XMLParser::parseAnalysisEngineDescription(AnalysisEngineDescription & taeSpec, InputSource const & crInputSource) {

    XercesDOMParser parser;
    parser.setValidationScheme(XercesDOMParser::Val_Auto);
    parser.setDoNamespaces(true);
    if ( ResourceManager::getInstance().doSchemaValidation() ) {
      parser.setDoSchema( ResourceManager::getInstance().isSchemaAvailable());
    } else {
      parser.setDoSchema(false);
    }
    parser.setExternalSchemaLocation( ResourceManager::getInstance().getSchemaInfo());
    bool bHasOwnErrorHandler = false;
    
    if (iv_pXMLErrorHandler == NULL) {
      iv_pXMLErrorHandler = new XMLErrorHandler();
      assert( EXISTS(iv_pXMLErrorHandler) );
      bHasOwnErrorHandler = true;
    }

    parser.setErrorHandler(iv_pXMLErrorHandler);
    
    try {
      parser.parse( crInputSource );
    } catch (Exception e){
      if (bHasOwnErrorHandler) {
        delete iv_pXMLErrorHandler;
        iv_pXMLErrorHandler = NULL; 
      }
      throw(e);      
    }
    
    DOMDocument* doc = parser.getDocument();
    assert(EXISTS(doc));

    // get top node
    DOMElement * rootElem = doc->getDocumentElement();
    assert(EXISTS(rootElem));

    buildAnalysisEngineDescription(taeSpec, rootElem, convert(crInputSource.getSystemId()));

    if (bHasOwnErrorHandler) {
      delete iv_pXMLErrorHandler;
      iv_pXMLErrorHandler = NULL;
    }
  }


  void XMLParser::parseTypeSystemDescription(TypeSystemDescription & tsDesc, InputSource const & crInputSource) {

    XercesDOMParser parser;
    parser.setValidationScheme(XercesDOMParser::Val_Auto);
    parser.setDoNamespaces(true);
    parser.setDoSchema( ResourceManager::getInstance().isSchemaAvailable());
    parser.setExternalSchemaLocation( ResourceManager::getInstance().getSchemaInfo());
    bool bHasOwnErrorHandler = false;
    if (iv_pXMLErrorHandler == NULL) {
      iv_pXMLErrorHandler = new XMLErrorHandler();
      assert( EXISTS(iv_pXMLErrorHandler) );
      bHasOwnErrorHandler = true;
    }

    parser.setErrorHandler(iv_pXMLErrorHandler);
    try {
      parser.parse( crInputSource );
    } catch (Exception const & e){
      if (bHasOwnErrorHandler) {
        delete iv_pXMLErrorHandler;
        iv_pXMLErrorHandler = NULL; 
      }
      throw e;
    }


    DOMDocument* doc = parser.getDocument();
    assert(EXISTS(doc));

    // get top node
    DOMElement * rootElem = doc->getDocumentElement();
    assert(EXISTS(rootElem));

    assert( XMLString::compareString(rootElem->getNodeName(), convert(TAG_TYPE_SYSTEM_DESC)) == 0);
    //TypeSystemDescription * tsSpec = buildTypeSystemDesc(rootElem);
    buildTypeSystemDesc(tsDesc, rootElem);
    if (bHasOwnErrorHandler) {
      delete iv_pXMLErrorHandler;
      iv_pXMLErrorHandler = NULL;
    }

  }


  void XMLParser::parseFSIndexDescription(AnalysisEngineMetaData::TyVecpFSIndexDescriptions & fsDesc,
       InputSource const & crInputSource) {
    
    XercesDOMParser parser;
    parser.setValidationScheme(XercesDOMParser::Val_Auto);
    parser.setDoNamespaces(true);
    parser.setDoSchema(false);
    parser.setExternalSchemaLocation(UIMA_XML_NAMESPACE " ");

    bool bHasOwnErrorHandler = false;
    if (iv_pXMLErrorHandler == NULL) {
      iv_pXMLErrorHandler = new XMLErrorHandler();
      assert( EXISTS(iv_pXMLErrorHandler) );
      bHasOwnErrorHandler = true;
    }
    parser.setErrorHandler(iv_pXMLErrorHandler);
    try {
    parser.parse( crInputSource );
    } catch (Exception const & e){
      if (bHasOwnErrorHandler) {
        delete iv_pXMLErrorHandler;
        iv_pXMLErrorHandler = NULL; 
      }
      throw e;
    }

    DOMDocument* doc = parser.getDocument();
    // get top node
    DOMElement * descElem = doc->getDocumentElement();

    assert(EXISTS(descElem));

    if (bHasOwnErrorHandler) {
      delete iv_pXMLErrorHandler;
      iv_pXMLErrorHandler = NULL;
    }
    buildFSIndexes(fsDesc, descElem);
  }

  void XMLParser::parseTypePriorities(AnalysisEngineMetaData::TyVecpTypePriorities  & prioDesc,
      InputSource const & crInputSource) {
	
    XercesDOMParser parser;
    parser.setValidationScheme(XercesDOMParser::Val_Auto);
    parser.setDoNamespaces(true);
    parser.setDoSchema(false);
    parser.setExternalSchemaLocation(UIMA_XML_NAMESPACE " ");

    bool bHasOwnErrorHandler = false;
    if (iv_pXMLErrorHandler == NULL) {
      iv_pXMLErrorHandler = new XMLErrorHandler();
      assert( EXISTS(iv_pXMLErrorHandler) );
      bHasOwnErrorHandler = true;
    }

    parser.setErrorHandler(iv_pXMLErrorHandler);
    try {
      parser.parse( crInputSource );
    } catch (Exception const & e){
      if (bHasOwnErrorHandler) {
        delete iv_pXMLErrorHandler;
        iv_pXMLErrorHandler = NULL; 
      }
      throw e;
    }

    DOMDocument* doc = parser.getDocument();
    // get top node
    DOMElement * descElem = doc->getDocumentElement();

    assert(EXISTS(descElem));

    if (bHasOwnErrorHandler) {
      delete iv_pXMLErrorHandler;
      iv_pXMLErrorHandler = NULL;
    }

    buildTypePriorities(prioDesc, descElem);
  }


  void XMLParser::parseSofaMappings(AnalysisEngineDescription::TyVecpSofaMappings & sofaMapDesc,
      InputSource const & crInputSource) {

    XercesDOMParser parser;
    parser.setValidationScheme(XercesDOMParser::Val_Auto);
    parser.setDoNamespaces(true);
    parser.setDoSchema(false);
    parser.setExternalSchemaLocation(UIMA_XML_NAMESPACE " ");

    bool bHasOwnErrorHandler = false;
    if (iv_pXMLErrorHandler == NULL) {
      iv_pXMLErrorHandler = new XMLErrorHandler();
      assert( EXISTS(iv_pXMLErrorHandler) );
      bHasOwnErrorHandler = true;
    }

    parser.setErrorHandler(iv_pXMLErrorHandler);
    try {
    parser.parse( crInputSource );
    } catch (Exception const & e){
      if (bHasOwnErrorHandler) {
        delete iv_pXMLErrorHandler;
        iv_pXMLErrorHandler = NULL; 
      }
      throw e;
    }

    DOMDocument* doc = parser.getDocument();
    // get top node
    DOMElement * descElem = doc->getDocumentElement();
    assert(EXISTS(descElem));

    if (bHasOwnErrorHandler) {
      delete iv_pXMLErrorHandler;
      iv_pXMLErrorHandler = NULL;
    }

    buildSofaMappings(sofaMapDesc, descElem);
  }


  void XMLParser::buildAnalysisEngineDescription(AnalysisEngineDescription & taeSpec,
      DOMElement * descElem,
      const icu::UnicodeString & xmlFileLoc) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_TAE_DESC)) == 0 ||
            XMLString::compareString(descElem->getNodeName(), convert(TAG_AE_DESC)) == 0 ||
            XMLString::compareString(descElem->getNodeName(), convert(TAG_CASCONSUMER_DESC)) == 0 );
    //save the root node name
    if (XMLString::compareString(descElem->getNodeName(), convert(TAG_CASCONSUMER_DESC)) == 0) {
      taeSpec.setPrimitive(true);
    }
    taeSpec.setXmlRootTag(convert(descElem->getNodeName()));
    DOMNodeList * children = descElem->getChildNodes();
    assert( EXISTS(children) );

    try {
      taeSpec.setXmlFileLocation(xmlFileLoc);

      size_t i;
      for (i=0; i < children->getLength(); i++) {
        if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
          continue;
        }
        const icu::UnicodeString & childTag = convert((children->item(i))->getNodeName());
        if (childTag.compare(TAG_TAE_PRIMITIVE) == 0) {
          taeSpec.setPrimitive(isTrue(getSpannedText(children->item(i))));
        } else if (childTag.compare(TAG_AN_IMPL_NAME) == 0 ||
                   childTag.compare(TAG_IMPL_NAME) == 0) {
          taeSpec.setAnnotatorImpName(getSpannedText(children->item(i)));
        } else if (childTag.compare(TAG_DELEGATE_AES) == 0) {
          DOMNodeList * delegateAEs = ((children->item(i))->getChildNodes());
          if (EXISTS(delegateAEs)) {
            size_t j;
            for (j=0; j < delegateAEs->getLength(); j++) {
              DOMNode * node = delegateAEs->item(j);
              if (node->getNodeType() != DOMNode::ELEMENT_NODE) {
                continue;
              }
              assert(XMLString::compareString(node->getNodeName(), convert(TAG_DELEGATE_AE)) == 0);
              DOMElement * delegateAE =  (DOMElement *)node;
              assert(EXISTS(delegateAE));
              icu::UnicodeString key = convert(delegateAE->getAttribute(convert(ATTR_DELEGATE_AE_KEY)));
              AnalysisEngineDescription * pdelegateTaeSpec = new AnalysisEngineDescription();
              DOMNodeList * childNodes = delegateAE->getChildNodes();

              DOMElement * delegateSpec = (DOMElement *) findFirst(childNodes, TAG_AE_DESC);
              if (delegateSpec == NULL)
                delegateSpec = (DOMElement *) findFirst(childNodes, TAG_TAE_DESC);
              if (delegateSpec == NULL)
                delegateSpec = (DOMElement *) findFirst(childNodes, TAG_CASCONSUMER_DESC);

              if (EXISTS(delegateSpec)) {           //the delegate is explicitly copied into the aggregate xml file
                buildAnalysisEngineDescription(*pdelegateTaeSpec, delegateSpec, xmlFileLoc);
                taeSpec.addDelegate(key, pdelegateTaeSpec);
              } else {
                //import element
                delegateSpec = (DOMElement *) findFirst (childNodes, TAG_IMPORT_DESC);
                if (delegateSpec != NULL) {
                  icu::UnicodeString loc = convert(delegateSpec->getAttribute(convert(ATTR_IMPORT_DESC_LOCATION)));
				  icu::UnicodeString fn = ResourceManager::resolveFilename(loc, xmlFileLoc);
				  if (loc.length() > 0) {			    
					parseAnalysisEngineDescription(*pdelegateTaeSpec, fn);
                    taeSpec.addDelegate(key, pdelegateTaeSpec);
                  } else {
                    //throw exception when import location attribute is not set.
                    ErrorMessage errMsg = ErrorMessage(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
                    errMsg.addParam(childTag);
                    errMsg.addParam(xmlFileLoc);

                    UIMA_EXC_THROW_NEW(InvalidXMLException,
                                       UIMA_ERR_IMPORT_INVALID_XML_ATTRIBUTE,
                                       errMsg,
                                       UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                                       ErrorInfo::unrecoverable);
                  }
                } else {
                  //check for xi:include element, try to get filename
                  DOMElement * delegateInc = (DOMElement *) findFirst(childNodes,
                                             TAG_DELEGATE_AE_INCLUDE);
                  if (EXISTS(delegateInc)) {
                    icu::UnicodeString newFileName = ResourceManager::resolveFilename(getSpannedText(delegateInc),
                                                     xmlFileLoc);
                    parseAnalysisEngineDescription(*pdelegateTaeSpec, newFileName);
                    taeSpec.addDelegate(key, pdelegateTaeSpec);

                  }
                }  //include
              }
            }
          }
        } else if (childTag.compare(TAG_AE_METADATA) == 0  ||
                   childTag.compare(TAG_PROCESSING_RESOURCE_METADATA) == 0 ) {
          taeSpec.setAnalysisEngineMetaData(buildAEMetaData((DOMElement *) (children->item(i)), xmlFileLoc));
          taeSpec.getAnalysisEngineMetaData()->getTypeSystemDescription()->setXmlFileLocation(xmlFileLoc);
          std::vector<icu::UnicodeString> alreadyImportedTypeSystemLocations;
          taeSpec.getAnalysisEngineMetaData()->getTypeSystemDescription()->resolveImports(alreadyImportedTypeSystemLocations);
        } else if (childTag.compare(UIMA_FRAMEWORK_IMP) == 0 ) {
          const icu::UnicodeString & impName = getSpannedText(children->item(i));
          if (impName.compare(FRAMEWORK_IMP_CPLUSPLUS) == 0)
            taeSpec.setFrameworkImplName(AnalysisEngineDescription::CPLUSPLUS);
          else if (impName.compare(FRAMEWORK_IMP_JAVA) == 0)
            taeSpec.setFrameworkImplName(AnalysisEngineDescription::JAVA);

          else {
            /**
            ErrorMessage errMsg = ErrorMessage(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
            errMsg.addParam(impName);
            errMsg.addParam(schemaFileName);

            UIMA_EXC_THROW_NEW(InvalidXMLException,
                              UIMA_ERR_CONFIG_INVALID_XML_TAG,
                              errMsg,
                              UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                              ErrorInfo::unrecoverable);
            **/
          }
        } else if (childTag.compare(TAG_EXTERNAL_RESOURCE_DEPENDENCIES) == 0) {
          /* taph 15.04.2004: we don't directly support ressources yet but we accept them in the XML to pass them to Jedii*/
        } else if (childTag.compare(TAG_EXTERNAL_RESOURCES) == 0) {
          /* taph 15.04.2004: we don't directly support ressources yet but we accept them in the XML to pass them to Jedii*/
        } else if (childTag.compare(TAG_SOFA_MAPPINGS) == 0) {
          buildSofaMappings(taeSpec, (DOMElement *) (children->item(i)) );
        } else if (childTag.compare(TAG_RESMGR_CONFIG_DESC) == 0) {
          //ignored
        }
        else {
          /**
          ErrorMessage errMsg = ErrorMessage(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
          errMsg.addParam(childTag);
          errMsg.addParam(schemaFileName);

          UIMA_EXC_THROW_NEW(InvalidXMLException,
                            UIMA_ERR_CONFIG_INVALID_XML_TAG,
                            errMsg,
                            UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                            ErrorInfo::unrecoverable);
          **/
        }
      }
    } catch (InvalidXMLException & rclException) {
      rclException.getErrorInfo().addContext(ErrorMessage(UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC_FROM_FILE, xmlFileLoc));
      throw rclException;
    } catch (DuplicateConfigElemException & rclException) {
      rclException.getErrorInfo().addContext(ErrorMessage(UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC_FROM_FILE, xmlFileLoc));
      throw rclException;
    }

  }


  void XMLParser::buildTypeSystemSpecifier(TypeSystemDescription & tsDesc,
    DOMElement * descElem,
    const icu::UnicodeString & xmlFileLoc) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_TYPE_SYSTEM_DESC)) == 0);
    
    buildTypeSystemDesc(tsDesc, descElem);
	
  }

  AnalysisEngineMetaData * XMLParser::buildAEMetaData(DOMElement * descElem,
      icu::UnicodeString const & xmlFileLoc) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_AE_METADATA)) == 0 ||
            XMLString::compareString(descElem->getNodeName(), convert(TAG_PROCESSING_RESOURCE_METADATA)) == 0 );

    AnalysisEngineMetaData * aeMetaData = new AnalysisEngineMetaData();

    DOMNodeList * children = descElem->getChildNodes();
    assert( EXISTS(children) );

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_AE_NAME) == 0) {
        aeMetaData->setName(getSpannedText(child));
      } else if (childTag.compare(TAG_AE_DESCRIPTION) == 0) {
        aeMetaData->setDescription(getSpannedText(child));
      } else if (childTag.compare(TAG_AE_VERSION) == 0) {
        aeMetaData->setVersion(getSpannedText(child));
      } else if (childTag.compare(TAG_AE_VENDOR) == 0) {
        aeMetaData->setVendor(getSpannedText(child));
      } else if (childTag.compare(TAG_CONFIG_PARAMS) == 0) {
        buildConfigParams(*aeMetaData, child);
      } else if (childTag.compare(TAG_CONFIG_PARAM_SETTINGS) == 0) {
        buildConfigParamSettings(*aeMetaData, child);
      } else if (childTag.compare(TAG_TYPE_SYSTEM_DESC) == 0) {
		  if (aeMetaData->getTypeSystemDescription() == NULL) {
		    TypeSystemDescription * tsDesc = new TypeSystemDescription();
		    aeMetaData->setTypeSystemDescription(tsDesc);
		  }
          buildTypeSystemDesc( *(aeMetaData->getTypeSystemDescription()), child);
      } else if (childTag.compare(TAG_TYPE_PRIORITIES) == 0) {
        vector <icu::UnicodeString> alreadyImported;
        buildTypePriorities(*aeMetaData, child, xmlFileLoc, alreadyImported);
      } else if (childTag.compare(TAG_FS_INDEXES) == 0) {
        buildFSIndexes(*aeMetaData, child);
      } else if (childTag.compare(TAG_FS_INDEX_COLLECTION) == 0) {
        vector <icu::UnicodeString> alreadyImported;
        buildFSIndexCollection(*aeMetaData, child, alreadyImported, xmlFileLoc);
      } else if (childTag.compare(TAG_CAPABILITIES) == 0) {
        buildCapabilities(*aeMetaData, child);
      } else if (childTag.compare(TAG_FLOW) == 0) {
        aeMetaData->setFlowConstraints(buildFlowConstraints(child));
      } else if (childTag.compare(TAG_OPERATIONAL_PROPERTIES) == 0) {
        aeMetaData->setOperationalProperties(buildOperationalProperties(child));
      } else {
        /**
        ErrorMessage errMsg = ErrorMessage(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);

        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    //aggregate TAEs don't contain a type system description,
    //but we have to ensure that one is set, otherwise merging the type systems will fail
    TypeSystemDescription * tsDesc = aeMetaData->getTypeSystemDescription();
    if (! (EXISTS(tsDesc)) ) {
      aeMetaData->setTypeSystemDescription(new TypeSystemDescription());
    }
    return aeMetaData;
  }

 

  void XMLParser::buildConfigParams(AnalysisEngineMetaData & aeMetaData,
      DOMElement * descElem) {
    //check for default group and search strategy
    const XMLCh* defaultGroup = descElem->getAttribute(convert(ATTR_CONFIG_PARAMS_DEF_GROUP));
    if (isDefined(defaultGroup)) {
      aeMetaData.setDefaultGroupName(convert(defaultGroup));
    }
    const XMLCh * searchStrategy = descElem->getAttribute(convert(ATTR_CONFIG_PARAMS_SEARCH));
    if (isDefined(searchStrategy)) {
      const icu::UnicodeString & strategy = convert(searchStrategy);
      if (strategy.compare(NO_FALLBACK) == 0) {
        aeMetaData.setSearchStrategy(AnalysisEngineMetaData::NONE);
      } else if (strategy.compare(DEFAULT_FALLBACK) == 0) {
        aeMetaData.setSearchStrategy(AnalysisEngineMetaData::DEFAULT_FALLBACK);
      } else if (strategy.compare(LANGUAGE_FALLBACK) == 0) {
        aeMetaData.setSearchStrategy(AnalysisEngineMetaData::LANGUAGE_FALLBACK);
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_CONFIG_XML_ATTRIBUTE_VALUE_NOT_ALLOWED);
        icu::UnicodeString tagName = convert( descElem->getTagName() );
        errMsg.addParam(strategy);
        errMsg.addParam(ATTR_CONFIG_PARAMS_SEARCH);
        errMsg.addParam(tagName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_ATTRIBUTE_VALUE,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }

    DOMNodeList * children = descElem->getChildNodes();
    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }

      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());

      if (childTag.compare(TAG_CONFIG_PARAM_COMMON) == 0) {
        DOMNodeList * commonParms = child->getChildNodes();
        size_t j;
        for (j=0; j < commonParms->getLength(); j++) {
          if ((commonParms->item(j))->getNodeType() != DOMNode::ELEMENT_NODE) {
            continue;
          }
          aeMetaData.addCommonParameter(buildConfigParam((DOMElement *) commonParms->item(j)));
        }
      } else if (childTag.compare(TAG_CONFIG_PARAM) == 0) {
        aeMetaData.addConfigurationParameter(buildConfigParam(child));
      } else if (childTag.compare(TAG_CONFIG_PARAM_GROUP) == 0) {
        //contains the groups as space-separated string
        const icu::UnicodeString & groupNameString = convert(child->getAttribute(convert(ATTR_CONFIG_PARAM_GROUP_NAMES)));
        vector <std::string> groupNames;
        //TBD: change this to true unicode processing
        delimitedString2Vector(groupNames,
                               UnicodeStringRef(groupNameString).asUTF8(),
                               " ", true, false);

        //add the configuration groups, even if they don't define any parameters themselves
        //this way, later assignValue calls will succeed, otherwise, they would fail, as
        //assignValue requires that the configuration group must already exist
        for (size_t m=0; m < groupNames.size(); m++) {
          const icu::UnicodeString & groupName = icu::UnicodeString(groupNames[m].c_str(), "UTF-8");
          aeMetaData.addConfigurationGroup(groupName);
        }

        //get the config params defined for that group
        DOMNodeList * confParmsInGroup = child->getChildNodes();
        size_t k;
        for (k=0; k < confParmsInGroup->getLength(); k++) {
          if ((confParmsInGroup->item(k))->getNodeType() != DOMNode::ELEMENT_NODE) {
            continue;
          }

          //add the config param for each group
          size_t l;
          for (l=0; l < groupNames.size(); l++) {
            //we can't put the same configParam into the groups, as they will delete their
            //member in their destructor
            //tbd: build only once, copy the result, pass the copies into 'add'
            ConfigurationParameter * configParam = buildConfigParam((DOMElement *) confParmsInGroup->item(k));
            aeMetaData.addConfigurationParameter(icu::UnicodeString(groupNames[l].c_str(), "UTF-8"), configParam);
          }
        }
      }
    }
  }

  ConfigurationParameter * XMLParser::buildConfigParam(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_CONFIG_PARAM)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert( EXISTS(children) );

    ConfigurationParameter * configParm = new ConfigurationParameter();

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_CONFIG_PARAM_NAME) == 0) {
        configParm->setName(getSpannedText(child));
      } else if (childTag.compare(TAG_CONFIG_PARAM_DESC) == 0) {
        configParm->setDescription(getSpannedText(child));
      } else if (childTag.compare(TAG_CONFIG_PARAM_TYPE) == 0) {
        const icu::UnicodeString & typeName = getSpannedText(child);
        if (typeName.compare(CONFIG_PARAM_BOOLEAN_TYPE) == 0) {
          configParm->setType(ConfigurationParameter::BOOLEAN);
        } else if (typeName.compare(CONFIG_PARAM_FLOAT_TYPE) == 0) {
          configParm->setType(ConfigurationParameter::FLOAT);
        } else if (typeName.compare(CONFIG_PARAM_INTEGER_TYPE) == 0) {
          configParm->setType(ConfigurationParameter::INTEGER);
        } else if (typeName.compare(CONFIG_PARAM_STRING_TYPE) == 0) {
          configParm->setType(ConfigurationParameter::STRING);
        } else {
          /**
          ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
          errMsg.addParam(typeName);
          errMsg.addParam(schemaFileName);
          UIMA_EXC_THROW_NEW(InvalidXMLException,
                            UIMA_ERR_CONFIG_INVALID_XML_TAG,
                            errMsg,
                            UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                            ErrorInfo::unrecoverable);        
          **/
        }
      } else if (childTag.compare(TAG_CONFIG_PARAM_MANDATORY) == 0) {
        configParm->setMandatory(isTrue(getSpannedText(child)));
      } else if (childTag.compare(TAG_CONFIG_PARAM_MULTIVAL) == 0) {
        configParm->setMultiValued((ConfigurationParameter::EnParameterAggregation)
                                   isTrue(getSpannedText(child)));
      } else if (childTag.compare(TAG_CONFIG_PARAM_RESTRICT) == 0) {
        //contains the AnC keys as space-separated string
        const icu::UnicodeString & ancKeyString = getSpannedText(child);
        vector <std::string> ancKeys;
        //TBD: change this to true unicode processing
        delimitedString2Vector(ancKeys,
                               UnicodeStringRef(ancKeyString).asUTF8(),
                               " ", true, false);

        for (size_t i=0; i < ancKeys.size(); i++) {
          const icu::UnicodeString & key = icu::UnicodeString(ancKeys[i].c_str(), "UTF-8");
          configParm->addRestriction(key);
        }
      } else {  /**
                        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
                        errMsg.addParam(childTag);
                        errMsg.addParam(schemaFileName);
                        UIMA_EXC_THROW_NEW(InvalidXMLException,
                                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                                          errMsg,
                                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                                          ErrorInfo::unrecoverable);
                         **/
      }
    }

    return configParm;
  }

  
 

  void XMLParser::buildConfigParamSettings(AnalysisEngineMetaData & aeMetadata,
      DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_CONFIG_PARAM_SETTINGS)) == 0);
    DOMNodeList * children = descElem->getChildNodes();

    if (! EXISTS(children)) { //there are no settings defined
      return;
    }

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_CONFIG_PARAM_SETTING_GROUP) == 0) {
        //extract the group names
        const icu::UnicodeString & groupNameString = convert(child->getAttribute(convert(ATTR_CONFIG_PARAM_SETTING_GROUP_NAMES)));
        vector <std::string> groupNames;
        //TBD: change this to true unicode processing
        delimitedString2Vector(groupNames,
                               UnicodeStringRef(groupNameString).asUTF8(),
                               " ", true, false);
        DOMNodeList * nvPairsForGroup = child->getChildNodes();
        size_t k;
        for (k=0; k < nvPairsForGroup->getLength(); k++) {
          if ((nvPairsForGroup->item(k))->getNodeType() != DOMNode::ELEMENT_NODE) {
            continue;
          }
          size_t l;
          for (l=0; l < groupNames.size(); l++) {
            //we can't put the same nvPair into the groups, as they will delete their
            //member in their destructor
            //tbd: build only once, copy the result, pass the copies into 'add'
            NameValuePair * nvPair = buildNameValuePair((DOMElement *) nvPairsForGroup->item(k));
            icu::UnicodeString groupName(groupNames[l].c_str(), "UTF-8");
            //check for duplicate name value pairs
            //as a side effect, this also ensures that all name value pairs are defined
            //as configuration parameters
            if (EXISTS(aeMetadata.getNameValuePairNoFallback(groupName, nvPair->getName(), ""))) {
              ErrorMessage msg(UIMA_MSG_ID_EXC_CONFIG_DUPLICATE_NAME_VALUE_PAIR);
              msg.addParam(nvPair->getName());
              UIMA_EXC_THROW_NEW(DuplicateConfigElemException,
                                 UIMA_ERR_CONFIG_DUPLICATE_NAME_VALUE_PAIR,
                                 msg,
                                 UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                                 ErrorInfo::recoverable);
            }
            aeMetadata.addNameValuePair(groupName, nvPair);
          }
        }
      } else if (childTag.compare(TAG_NAME_VALUE_PAIR) == 0) {
        NameValuePair * nvPair = buildNameValuePair(child);
        //check for duplicate name value pairs
        //as a side effect, this also ensures that all name value pairs are defined
        //as configuration parameters
        if (EXISTS(aeMetadata.getNameValuePair(nvPair->getName()))) {
          ErrorMessage msg(UIMA_MSG_ID_EXC_CONFIG_DUPLICATE_NAME_VALUE_PAIR);
          msg.addParam(nvPair->getName());
          UIMA_EXC_THROW_NEW(DuplicateConfigElemException,
                             UIMA_ERR_CONFIG_DUPLICATE_NAME_VALUE_PAIR,
                             msg,
                             UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                             ErrorInfo::recoverable);
        }
        aeMetadata.addNameValuePair(nvPair);
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
  }


  NameValuePair * XMLParser::buildNameValuePair(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_NAME_VALUE_PAIR)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert( EXISTS(children) );

    NameValuePair * nvPair = new NameValuePair();
    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_NAME_VALUE_PAIR_NAME) == 0) {
        nvPair->setName(getSpannedText(child));
      } else if (childTag.compare(TAG_NAME_VALUE_PAIR_VALUE) == 0) {
        buildValue(*nvPair, child);
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    return nvPair;
  }

  void XMLParser::buildValue(NameValuePair & nvPair, DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_NAME_VALUE_PAIR_VALUE)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert( EXISTS(children) );

    //assert( children->getLength() == 1);
    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }

      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());

      if (childTag.compare(TAG_NAME_VALUE_PAIR_VALUE_ARRAY) == 0) {
        DOMNodeList * arrayEntries = child->getChildNodes();
        assert( EXISTS(arrayEntries) );
        //the type must be the same for all elements in the array
        nvPair.define(findTypeForValue(findFirstElementNode(arrayEntries)), ConfigurationParameter::MULTIPLE_VALUES);
        //now iterate over entries, adding the values
        size_t j;
        for (j=0; j < arrayEntries->getLength(); j++) {
          if ((arrayEntries->item(j))->getNodeType() != DOMNode::ELEMENT_NODE) {
            continue;
          }
          nvPair.addValue(getSpannedText(arrayEntries->item(j)));
        }
      } else {
        nvPair.define(findTypeForValue(child), ConfigurationParameter::SINGLE_VALUE); // findFirstElementNode(child->getChildNodes())));
        nvPair.setValue(getSpannedText(child));
      }
    }
  }

  ConfigurationParameter::EnParameterType XMLParser::findTypeForValue(DOMNode * descElem) {
    assert(EXISTS(descElem));
    const icu::UnicodeString & tagName = convert(descElem->getNodeName());
    ConfigurationParameter::EnParameterType type;
    if (tagName.compare(TAG_NAME_VALUE_PAIR_VALUE_STRING) == 0) {
      type = ConfigurationParameter::STRING;
    } else if (tagName.compare(TAG_NAME_VALUE_PAIR_VALUE_INT) == 0) {
      type = ConfigurationParameter::INTEGER;
    } else if (tagName.compare(TAG_NAME_VALUE_PAIR_VALUE_FLOAT) == 0) {
      type = ConfigurationParameter::FLOAT;
    } else if (tagName.compare(TAG_NAME_VALUE_PAIR_VALUE_BOOL) == 0) {
      type = ConfigurationParameter::BOOLEAN;
    } else {
      ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
      errMsg.addParam(tagName);
      errMsg.addParam(ResourceManager::getInstance().getSchemaInfo() );
      UIMA_EXC_THROW_NEW(InvalidXMLException,
                         UIMA_ERR_CONFIG_INVALID_XML_TAG,
                         errMsg,
                         UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                         ErrorInfo::unrecoverable);

    }
    return type;
  }

  void XMLParser::buildTypeSystemDesc(TypeSystemDescription & typeSystemDesc, DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_TYPE_SYSTEM_DESC)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert( EXISTS(children) );
    //assert( children->getLength() == 1); //currently, there's only the 'types' element

    ///TypeSystemDescription * typeSystemDesc = new TypeSystemDescription();

    size_t j;
    for (j=0; j < children->getLength(); j++) {
      if ((children->item(j))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(j);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_TYPES) == 0) {
        DOMNodeList * typeDescs = (children->item(j))->getChildNodes();
        if (EXISTS(typeDescs)) {
          size_t i;
          for (i=0; i < typeDescs->getLength(); i++) {
            if ((typeDescs->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
              continue;
            }
            bool takesMemoryOwnerShip;
            unique_ptr<TypeDescription> desc( buildTypeDesc((DOMElement *) typeDescs->item(i)) );
            typeSystemDesc.addTypeDescription(desc.get(), takesMemoryOwnerShip);
            if (takesMemoryOwnerShip) {
              desc.release();
            }
          }
        }
      } else if (childTag.compare(TAG_IMPORT_DESC) == 0) {
        bool takesMemoryOwnerShip;
        unique_ptr<ImportDescription> desc( buildImportDesc((DOMElement *) children->item(j)) );
        typeSystemDesc.addImportDescription(desc.get(), takesMemoryOwnerShip);
        if (takesMemoryOwnerShip) {
          desc.release();
        }
      } else if (childTag.compare(TAG_IMPORTS) == 0) {
        DOMNodeList * importDescs = (children->item(j))->getChildNodes();
        if (EXISTS(importDescs)) {
          size_t i;
          for (i=0; i < importDescs->getLength(); i++) {
            if ((importDescs->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
              continue;
            }
            bool takesMemoryOwnerShip;
            unique_ptr<ImportDescription> desc( buildImportDesc((DOMElement *) importDescs->item(i)) );
            typeSystemDesc.addImportDescription(desc.get(), takesMemoryOwnerShip);
            if (takesMemoryOwnerShip) {
              desc.release();
            }
          }
        }
      }
    }
    return;
  }

  ImportDescription * XMLParser::buildImportDesc(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_IMPORT_DESC)) == 0);

    ImportDescription * importDesc = new ImportDescription();

    const XMLCh* location = descElem->getAttribute(convert(ATTR_IMPORT_DESC_LOCATION));
    if (isDefined(location)) {
      importDesc->setLocation(convert(location));
    } else {
      const XMLCh* name = descElem->getAttribute(convert(ATTR_IMPORT_DESC_NAME));
      if (isDefined(name)) {
        importDesc->setName(convert(name));
      } else {
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_CONFIG_XML_ATTRIBUTE_VALUE_NOT_ALLOWED);
        icu::UnicodeString tagName = convert( descElem->getTagName() );
        errMsg.addParam(TAG_IMPORT_DESC);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                           UIMA_ERR_CONFIG_INVALID_XML_ATTRIBUTE_VALUE,
                           errMsg,
                           UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                           ErrorInfo::unrecoverable);
      }
    }

    return importDesc;
  }

  TypeDescription * XMLParser::buildTypeDesc(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_TYPE_DESC)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert( EXISTS(children) );

    TypeDescription * typeDesc = new TypeDescription();

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_TYPE_DESC_NAME) == 0) {
        typeDesc->setName(getSpannedText(child));
      } else if (childTag.compare(TAG_TYPE_DESC_SUPER) == 0) {
        typeDesc->setSuperTypeName(getSpannedText(child));
      } else if (childTag.compare(TAG_TYPE_DESC_DESC) == 0) {
        typeDesc->setDescription(getSpannedText(child));
      } else if (childTag.compare(TAG_TYPE_DESC_FEATURES) == 0) {
        DOMNodeList * features = child->getChildNodes();
        if (EXISTS(features)) {
          size_t j;
          for (j=0; j < features->getLength(); j++) {
            if ((features->item(j))->getNodeType() != DOMNode::ELEMENT_NODE) {
              continue;
            }
            unique_ptr<FeatureDescription> desc( buildFeatureDesc((DOMElement *) features->item(j)) );
            bool takesMemoryOwnership;
            typeDesc->addFeatureDescription(desc.get(), takesMemoryOwnership);
            if (takesMemoryOwnership) {
              desc.release();
            }
          }
        }
      } else if (childTag.compare(TAG_TYPE_DESC_ALLOWED_VALS) == 0) {
        DOMNodeList * allowedVals = child->getChildNodes();
        if (EXISTS(allowedVals)) {
          size_t j;
          for (j=0; j< allowedVals->getLength(); j++) {
            if ((allowedVals->item(j))->getNodeType() != DOMNode::ELEMENT_NODE) {
              continue;
            }
            unique_ptr<AllowedValue> desc( buildAllowedValue((DOMElement *) allowedVals->item(j)) );
            bool takesMemoryOwnership;
            typeDesc->addAllowedValue(desc.get(), takesMemoryOwnership);
            if (takesMemoryOwnership) {
              desc.release();
            }
          }
        }
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    return typeDesc;
  }

  FeatureDescription * XMLParser::buildFeatureDesc(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_TYPE_DESC_FEAT_DESC)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert( EXISTS(children) );

    FeatureDescription * featureDesc = new FeatureDescription();
    size_t i;
    for (i=0; i< children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_TYPE_DESC_FEAT_DESC_NAME) == 0) {
        featureDesc->setName(getSpannedText(child));
      } else if (childTag.compare(TAG_TYPE_DESC_FEAT_DESC_RANGE) == 0) {
        featureDesc->setRangeTypeName(getSpannedText(child));
      } else if (childTag.compare(TAG_TYPE_DESC_FEAT_DESC_ELEMENT) == 0) {
        featureDesc->setElementType(getSpannedText(child));
      } else if (childTag.compare(TAG_TYPE_DESC_FEAT_DESC_DESC) == 0) {
        featureDesc->setDescription(getSpannedText(child));
	  } else if (childTag.compare(TAG_TYPE_DESC_FEAT_DESC_MULTREFS) == 0) {
		  if (isTrue(getSpannedText(child))) {
			featureDesc->setMultipleReferencesAllowed(true);
		  }
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    return featureDesc;
  }

  AllowedValue * XMLParser::buildAllowedValue(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_TYPE_DESC_ALLOWED_VALS_VAL)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert( EXISTS(children) );
    AllowedValue * allVal = new AllowedValue();

    size_t i;
    for (i=0; i< children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_TYPE_DESC_ALLOWED_VALS_VAL_STRING) == 0) {
        allVal->setName(getSpannedText(child));
      } else if (childTag.compare(TAG_TYPE_DESC_ALLOWED_VALS_VAL_DESC) == 0) {
        allVal->setDescription(getSpannedText(child));
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    return allVal;
  }


  void XMLParser::buildTypePriorities(AnalysisEngineMetaData::TyVecpTypePriorities & vecpTypePriorities,
      DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_TYPE_PRIORITIES)) == 0);
    DOMNodeList * children = descElem->getChildNodes();

    if (! EXISTS(children)) { // there may be no index descriptions
      return;
    }
    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      TypePriority * prio =  buildTypePriority((DOMElement *)children->item(i));
      vecpTypePriorities.push_back(prio);
    }
  }



  void XMLParser::buildTypePriorities(AnalysisEngineMetaData & aeMetaData,
      DOMElement * descElem,
      icu::UnicodeString const & xmlFileLoc,
      vector<icu::UnicodeString> & alreadyImportedLocations) {

    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_TYPE_PRIORITIES)) == 0);
    DOMNodeList * children = descElem->getChildNodes();

    if (! EXISTS(children)) { // there may be no type priorities
      return;
    }

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }

      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_TYPE_PRIORITY_LIST) == 0) {
        TypePriority * prio =  buildTypePriority((DOMElement *)child);
        aeMetaData.addTypePriority(prio);
      } else if (childTag.compare(TAG_IMPORTS)==0) {
        DOMNodeList * importDescs = child->getChildNodes();
        if (EXISTS(importDescs)) {
          size_t j;
          for (j=0; j < importDescs->getLength(); j++) {
            if ((importDescs->item(j))->getNodeType() != DOMNode::ELEMENT_NODE) {
              continue;
            }
	    icu::UnicodeString location = convert(((DOMElement *) importDescs->item(j))->getAttribute(convert(ATTR_IMPORT_DESC_LOCATION)));
            if (location.length() > 0)
              buildTypePriorityFromImportLocation(aeMetaData, location, xmlFileLoc, alreadyImportedLocations);
            else {
              //throw exception if import location not specified
	      icu::UnicodeString name = convert(((DOMElement *) importDescs->item(j))->getAttribute(convert(ATTR_IMPORT_DESC_NAME)));
              //throw exception if import location not set.
              ErrorMessage errMsg = ErrorMessage(UIMA_MSG_ID_EXC_UNSUPPORTED_XML_ATTRIBUTE);
              errMsg.addParam(xmlFileLoc);
              if (name.length() > 0) {
                errMsg.addParam(ATTR_IMPORT_DESC_NAME);
              }
              UIMA_EXC_THROW_NEW(InvalidXMLException,
                                 UIMA_ERR_IMPORT_INVALID_XML_ATTRIBUTE,
                                 errMsg,
                                 UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                                 ErrorInfo::unrecoverable);

            }
            /**bool takesMemoryOwnerShip;
            auto_ptr<ImportDescription> desc( buildImportDesc((DOMElement *) importDescs->item(j)) );
            aeMetaData.addTypePriorityImportDescription(desc.get(), takesMemoryOwnerShip);
            if (takesMemoryOwnerShip) {
                desc.release();
            }**/
          }
        }
      } //TAG_IMPORT
    }   //for
  }

  TypePriority * XMLParser::buildTypePriority(DOMElement * specElem) {
    assert(EXISTS(specElem));
    assert( XMLString::compareString(specElem->getNodeName(), convert(TAG_TYPE_PRIORITY_LIST)) == 0);
    DOMNodeList * children = specElem->getChildNodes();
    assert(EXISTS(children));

    TypePriority * pPrio = new TypePriority();
    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_TYPE_PRIORITY_LIST_TYPE) == 0) {
        pPrio->addType(getSpannedText(child));
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    return pPrio;
  }


  void XMLParser::buildFSIndexes(AnalysisEngineMetaData::TyVecpFSIndexDescriptions & vecFSIndexDesc,
      DOMElement * descElem) {
    assert(EXISTS(descElem));


	if ( XMLString::compareString(descElem->getNodeName(), convert(TAG_FS_INDEX_COLLECTION)) == 0) {
      DOMNodeList * children = descElem->getChildNodes();
      if (! EXISTS(children)) { // there may be no index descriptions
        return;
      }
	  for (size_t i=0; i < children->getLength(); i++) {
        if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
          continue;
        }
		descElem = (DOMElement*) children->item(i);
		break;
	  }
	}

    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_FS_INDEXES)) == 0);
    DOMNodeList * children = descElem->getChildNodes();

    if (! EXISTS(children)) { // there may be no index descriptions
      return;
    }

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      FSIndexDescription * indexDesc = buildFSIndexDesc((DOMElement *) children->item(i));
      vecFSIndexDesc.push_back(indexDesc);
      //aeMetaData.addFSIndexDescription(buildFSIndexDesc((DOMElement *) children->item(i)));
    }
  }

  void XMLParser::buildFSIndexes(AnalysisEngineMetaData & aeMetaData,
      DOMElement * descElem)   {
    assert(EXISTS(descElem));

    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_FS_INDEXES)) == 0);
    DOMNodeList * children = descElem->getChildNodes();

    if (! EXISTS(children)) { // there may be no index descriptions
      return;
    }

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      aeMetaData.addFSIndexDescription(buildFSIndexDesc((DOMElement *) children->item(i)));
    }
  }


  void XMLParser::buildFSIndexCollection(AnalysisEngineMetaData & aeMetaData,
      DOMElement * descElem,
      vector<icu::UnicodeString> & alreadyImportedLocations,
      icu::UnicodeString const & lastFileName) {

    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_FS_INDEX_COLLECTION)) == 0
            || XMLString::compareString(descElem->getNodeName(), convert(TAG_FS_INDEXES)) == 0);
    DOMNodeList * children = descElem->getChildNodes();

    if (! EXISTS(children)) { // there may be no index descriptions
      return;
    }

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_FS_INDEXES) == 0) {
        buildFSIndexes(aeMetaData, child);
      } else if (childTag.compare(TAG_IMPORTS)==0) {

        DOMNodeList * importDescs = child->getChildNodes();
        if (EXISTS(importDescs)) {
          size_t j;
          for (j=0; j < importDescs->getLength(); j++) {
            if ((importDescs->item(j))->getNodeType() != DOMNode::ELEMENT_NODE) {
              continue;
            }
	    icu::UnicodeString loc = convert(((DOMElement *) importDescs->item(j))->getAttribute(convert(ATTR_IMPORT_DESC_LOCATION)));
            if (loc.length() > 0) {
              buildFSIndexFromImportLocation(aeMetaData,
                                             loc,
                                             alreadyImportedLocations,
                                             lastFileName);
            } else {
	      icu::UnicodeString name = convert(((DOMElement *) importDescs->item(j))->getAttribute(convert(ATTR_IMPORT_DESC_NAME)));
              //throw exception if import location not set.
              ErrorMessage errMsg = ErrorMessage(UIMA_MSG_ID_EXC_UNSUPPORTED_XML_ATTRIBUTE);
              errMsg.addParam(lastFileName);
              if (name.length() > 0) {
                errMsg.addParam(ATTR_IMPORT_DESC_NAME);
              }
              UIMA_EXC_THROW_NEW(InvalidXMLException,
                                 UIMA_ERR_IMPORT_INVALID_XML_ATTRIBUTE,
                                 errMsg,
                                 UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                                 ErrorInfo::unrecoverable);
            }
          }
        }
      }
    }
  }

  FSIndexDescription * XMLParser::buildFSIndexDesc(DOMElement * descElem) {
    assert(EXISTS(descElem));
	//cout << __FILE__ <<  " " << UnicodeString((UChar*)descElem->getNodeName()) << endl;
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_FS_INDEX_DESC)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert(EXISTS(children));

    FSIndexDescription * fsIndexDesc = new FSIndexDescription();

    size_t i;
    for (i=0; i< children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_FS_INDEX_DESC_LABEL) == 0) {
        fsIndexDesc->setLabel(getSpannedText(child));
      } else if (childTag.compare(TAG_FS_INDEX_DESC_TYPE) == 0) {
        fsIndexDesc->setTypeName(getSpannedText(child));
      } else if (childTag.compare(TAG_FS_INDEX_DESC_KEYS) == 0) {
        DOMNodeList * indexKeys = child->getChildNodes();
        assert(EXISTS(indexKeys));
        size_t j;
        for (j=0; j< indexKeys->getLength(); j++ ) {
          if ((indexKeys->item(j))->getNodeType() != DOMNode::ELEMENT_NODE) {
            continue;
          }
          fsIndexDesc->addFSIndexKey(buildFSIndexKeyDesc((DOMElement *) indexKeys->item(j)));
        }
      } else if (childTag.compare(TAG_FS_INDEX_DESC_KIND) == 0) {
        const icu::UnicodeString & kind = getSpannedText(child);
        if (kind.compare(FS_INDEX_KEY_KIND_SORTED) == 0) {
          fsIndexDesc->setIndexKind(FSIndexDescription::SORTED);
        } else if (kind.compare(FS_INDEX_KEY_KIND_BAG) == 0) {
          fsIndexDesc->setIndexKind(FSIndexDescription::BAG);
        } else if (kind.compare(FS_INDEX_KEY_KIND_SET) == 0) {
          fsIndexDesc->setIndexKind(FSIndexDescription::SET);
        } else {
          /**
          ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
          errMsg.addParam(childTag);
          errMsg.addParam(schemaFileName);
          UIMA_EXC_THROW_NEW(InvalidXMLException,
                            UIMA_ERR_CONFIG_INVALID_XML_TAG,
                            errMsg,
                            UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                            ErrorInfo::unrecoverable);
          **/
        }
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    return fsIndexDesc;
  }

  FSIndexKeyDescription * XMLParser::buildFSIndexKeyDesc(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_FS_INDEX_KEY)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert(EXISTS(children));

    FSIndexKeyDescription * indexKeyDesc = new FSIndexKeyDescription();

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());
      if (childTag.compare(TAG_FS_INDEX_KEY_FEAT) == 0) {
        indexKeyDesc->setFeatureName(getSpannedText(child));
      } else if (childTag.compare(TAG_FS_INDEX_KEY_COMP) == 0) {
        const icu::UnicodeString & compType = getSpannedText(child);
        if (compType.compare(FS_INDEX_KEY_COMP_STANDARD) == 0) {
          indexKeyDesc->setComparator(FSIndexKeyDescription::STANDARD);
        } else if (compType.compare(FS_INDEX_KEY_COMP_REVERSE) == 0) {
          indexKeyDesc->setComparator(FSIndexKeyDescription::REVERSE);
        } else {
          /**
          ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
          errMsg.addParam(compType);
          errMsg.addParam(schemaFileName);
          UIMA_EXC_THROW_NEW(InvalidXMLException,
                            UIMA_ERR_CONFIG_INVALID_XML_TAG,
                            errMsg,
                            UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                            ErrorInfo::unrecoverable);
          **/
        }
      } else if (childTag.compare(TAG_FS_INDEX_KEY_TYPE_PRIORITY) == 0) {
        indexKeyDesc->setIsTypePriority();
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    return indexKeyDesc;
  }

  void XMLParser::buildCapabilities(AnalysisEngineMetaData & aeMetaData,
      DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_CAPABILITIES)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert(EXISTS(children));
    assert(children->getLength() > 0);

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      buildCapability(aeMetaData, (DOMElement *) children->item(i));
    }
  }

  /**
  * Builds the capability from <code>descElem</code>. Uses the TypeSystemDescription in
  * aeMetaData to expand types. If these types do not exist in the TypeSystemDescription,
  * no expansion takes place: only they are added to the input/outputtypes.
  **/
  void XMLParser::buildCapability(AnalysisEngineMetaData & aeMetaData,
      DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_CAPABILITY)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert(EXISTS(children));

    Capability * capability = new Capability();
    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());

      if (childTag.compare(TAG_CAP_LANG_SUPP) == 0) {
        DOMNodeList * languages = child->getChildNodes();
        size_t j;
        for (j=0; j < languages->getLength(); j++) {
          if ((languages->item(j))->getNodeType() != DOMNode::ELEMENT_NODE) {
            continue;
          }
          assert(XMLString::compareString((languages->item(j))->getNodeName(), convert(TAG_CAP_LANG)) == 0);
          capability->addSupportedLanguage(getSpannedText(languages->item(j)));
        }
      } else {//it's either input or output capabilities
        Capability::EnTypeStyle typeStyle;
        if (childTag.compare(TAG_CAP_INPUTS) == 0) {
          typeStyle = Capability::INPUT;
        } else if (childTag.compare(TAG_CAP_OUTPUTS) == 0) {
          typeStyle = Capability::OUTPUT;
        }//BSI
        else if (childTag.compare(TAG_CAP_INPUT_SOFAS) == 0) {
          typeStyle = Capability::INPUTSOFA;
        } else if (childTag.compare(TAG_CAP_OUTPUT_SOFAS) == 0) {
          typeStyle = Capability::OUTPUTSOFA;
        } else {

          ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
          errMsg.addParam(childTag);
          errMsg.addParam(ResourceManager::getInstance().getSchemaInfo());
          UIMA_EXC_THROW_NEW(InvalidXMLException,
                             UIMA_ERR_CONFIG_INVALID_XML_TAG,
                             errMsg,
                             UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                             ErrorInfo::unrecoverable);

        }

        DOMNodeList * types = child->getChildNodes();
        size_t j;
        for (j=0; j < types->getLength(); j++) {
          DOMNode * node = types->item(j);
          if (node->getNodeType() != DOMNode::ELEMENT_NODE) {
            continue;
          }
          DOMElement * nodeElem = (DOMElement *) node;
          const icu::UnicodeString & nodeTag = convert(nodeElem->getNodeName());

          if (nodeTag.compare(TAG_CAP_TYPE) == 0) {
            capability->addCapabilityType(getSpannedText(nodeElem), typeStyle);
            bool expand = isTrue(convert(nodeElem->getAttribute(convert(ATTR_CAP_FEATURE_ALL))));
            if (expand) {
              //add all features of this type as well, based on the type information
              //in the current specifier
              icu::UnicodeString typeName(getSpannedText(nodeElem));
              TypeSystemDescription * cpTypeSystemDesc =  aeMetaData.getTypeSystemDescription();
              if (EXISTS(cpTypeSystemDesc)) { //if there's already a type description in place
                const TypeDescription * cpTypeDesc =  cpTypeSystemDesc ->getTypeDescriptionConst(typeName);
                if (EXISTS(cpTypeDesc)) {
                  const TypeDescription::TyVecpFeatureDescriptions & featDescs = cpTypeDesc->getFeatureDescriptions();
                  TypeDescription::TyVecpFeatureDescriptions::const_iterator ite;
                  for (ite = featDescs.begin(); ite != featDescs.end(); ite++) {
		    icu::UnicodeString featName(typeName);
                    featName += UIMA_TYPE_FEATURE_SEPARATOR;
                    featName += (*ite)->getName();
                    capability->addCapabilityFeature(featName, typeStyle);
                  }
                }
              }
            }
          } else if (nodeTag.compare(TAG_CAP_FEATURE) == 0) {
            capability->addCapabilityFeature(getSpannedText(nodeElem), typeStyle);
          }
          //BSI
          else if (nodeTag.compare(TAG_CAP_SOFA_NAME) == 0) {
            capability->addCapabilitySofa(getSpannedText(nodeElem), typeStyle);
          } else {
            /**
            ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
            errMsg.addParam(nodeTag);
            errMsg.addParam(schemaFileName);
            UIMA_EXC_THROW_NEW(InvalidXMLException,
                              UIMA_ERR_CONFIG_INVALID_XML_TAG,
                              errMsg,
                              UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                              ErrorInfo::unrecoverable);
            **/
          }
        }
      }
    }
    aeMetaData.addCapability(capability);
  }


  FlowConstraints * XMLParser::buildFlowConstraints(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString( descElem->getNodeName(), convert(TAG_FLOW) ) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert(EXISTS(children));
    assert(children->getLength() > 0);

    FlowConstraints * flow = NULL;

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());


      if (childTag.compare(TAG_FLOW_FIX) == 0) {
        flow = buildFixedFlow(child);
      } else if (childTag.compare(TAG_FLOW_CAPABILITY_LANG)==0) {
        flow = buildCapabilityLanguageFlow(child);
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    return flow;
  }


  OperationalProperties * XMLParser::buildOperationalProperties(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString( descElem->getNodeName(), convert(TAG_OPERATIONAL_PROPERTIES) ) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert(EXISTS(children));
    assert(children->getLength() > 0);

    OperationalProperties * op = new OperationalProperties();

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());

      if (childTag.compare(TAG_MODIFIES_CAS) == 0) {
        op->setModifiesCas(isTrue(getSpannedText(child)));
      } else if (childTag.compare(TAG_MULTIPLE_DEPLOY_ALLOWED)==0) {
        op->setMultipleDeploymentAllowed(isTrue(getSpannedText(child)));
      } else if (childTag.compare(TAG_OUTPUTS_NEW_CASES)==0) {
        op->setOutputsNewCASes(isTrue(getSpannedText(child)));
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    return op;
  }




  FixedFlow * XMLParser::buildFixedFlow(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_FLOW_FIX)) == 0);
    DOMNodeList * nodes = descElem->getChildNodes();
    assert(EXISTS(nodes));
    assert(nodes->getLength() > 0);

    FixedFlow * flow = new FixedFlow();

    size_t i;
    for (i=0; i < nodes->getLength(); i++) {
      if ((nodes->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      assert(XMLString::compareString((nodes->item(i))->getNodeName(), convert(TAG_FLOW_FIX_NODE)) == 0);
      flow->addNode(getSpannedText(nodes->item(i)));
    }
    return flow;
  }

  CapabilityLanguageFlow * XMLParser::buildCapabilityLanguageFlow(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_FLOW_CAPABILITY_LANG)) == 0);
    DOMNodeList * nodes = descElem->getChildNodes();
    assert(EXISTS(nodes));
    assert(nodes->getLength() > 0);

    CapabilityLanguageFlow * flow = new CapabilityLanguageFlow();

    size_t i;
    for (i=0; i < nodes->getLength(); i++) {
      if ((nodes->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      assert(XMLString::compareString((nodes->item(i))->getNodeName(), convert(TAG_FLOW_CAPABILITY_LANG_NODE)) == 0);
      flow->addNode(getSpannedText(nodes->item(i)));
    }
    return flow;
  }


  void XMLParser::buildSofaMappings(AnalysisEngineDescription::TyVecpSofaMappings & sofaMappings,
      DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_SOFA_MAPPINGS)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert(EXISTS(children));
    assert(children->getLength() > 0);

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      SofaMapping * pSofaMapping = buildSofaMapping( (DOMElement *) children->item(i));
      sofaMappings.push_back(pSofaMapping);
      ;
    }
  }

  void XMLParser::buildSofaMappings(AnalysisEngineDescription & taeSpec,
      DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_SOFA_MAPPINGS)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert(EXISTS(children));
    assert(children->getLength() > 0);

    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      SofaMapping * pSofaMapping = buildSofaMapping( (DOMElement *) children->item(i));
      taeSpec.addSofaMapping(pSofaMapping);
    }

  }

  /**
  * Builds the capability from <code>descElem</code>. Uses the TypeSystemDescription in
  * aeMetaData to expand types. If these types do not exist in the TypeSystemDescription,
  * no expansion takes place: only they are added to the input/outputtypes.
  **/
  SofaMapping * XMLParser::buildSofaMapping(DOMElement * descElem) {
    assert(EXISTS(descElem));
    assert( XMLString::compareString(descElem->getNodeName(), convert(TAG_SOFA_MAPPING)) == 0);
    DOMNodeList * children = descElem->getChildNodes();
    assert(EXISTS(children));

    SofaMapping * sofamapping = new SofaMapping();
    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if ((children->item(i))->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }
      DOMElement * child = (DOMElement *) children->item(i);
      const icu::UnicodeString & childTag = convert(child->getNodeName());


      if (childTag.compare(TAG_SOFAMAP_COMPONENT_KEY) == 0) {
        sofamapping->setComponentKey(getSpannedText(child));
      } else if (childTag.compare(TAG_SOFAMAP_COMPONENT_SOFA_NAME) == 0) {
        sofamapping->setComponentSofaName(getSpannedText(child));
      } else if (childTag.compare(TAG_SOFAMAP_AGGREGATE_SOFA_NAME) == 0) {
        sofamapping->setAggregateSofaName(getSpannedText(child));
      } else {
        /**
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
        errMsg.addParam(childTag);
        errMsg.addParam(schemaFileName);
        UIMA_EXC_THROW_NEW(InvalidXMLException,
                          UIMA_ERR_CONFIG_INVALID_XML_TAG,
                          errMsg,
                          UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                          ErrorInfo::unrecoverable);
        **/
      }
    }
    return sofamapping;
  }

void XMLParser::buildFSIndexFromImportLocation(AnalysisEngineMetaData& fsDesc,
      icu::UnicodeString const & fileName,
      vector<icu::UnicodeString> & alreadyImportedLocations,
      icu::UnicodeString const & lastFileName) {

    icu::UnicodeString importfn = ResourceManager::resolveFilename(fileName, lastFileName);

    for (size_t i=0; i < alreadyImportedLocations.size() ;i++) {
      if (importfn.compare(alreadyImportedLocations[i]) == 0 )  {
        return;
      }
    }

    alreadyImportedLocations.push_back(importfn);
    size_t uiLen = importfn.length();
    auto_array<UChar> arBuffer( new UChar[uiLen + 1] );
    assert( EXISTS(arBuffer.get()));

    importfn.extract(0, uiLen, arBuffer.get());
    (arBuffer.get())[uiLen] = 0; // terminate the buffer with 0
    assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");

    // the following try catch block just to trigger an exception.
    // The constructor of LocalFileInputSource throws an exception on the UNIXes if the file does not
    // exist. On Windows, the parser throws this exception.
    try {
      LocalFileInputSource fileISOnlyForException((XMLCh const *) arBuffer.get() );
    } catch (XMLException const & e) {
      ErrorInfo errInfo;
      errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
      ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
      assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
      msg.addParam( arBuffer.get() );
      msg.addParam( 0 );
      msg.addParam( 0 );
      msg.addParam( (UChar const *) e.getMessage());
      errInfo.setMessage(msg);
      errInfo.setSeverity(ErrorInfo::unrecoverable);
      ExcIllFormedInputError exc(errInfo);
      throw exc;
    }

    LocalFileInputSource fileIS((XMLCh const *) arBuffer.get() );

    XercesDOMParser parser;
    parser.setValidationScheme(XercesDOMParser::Val_Auto);
    parser.setDoNamespaces(true);
    parser.setDoSchema(false);
    parser.setExternalSchemaLocation(UIMA_XML_NAMESPACE " ");

    bool bHasOwnErrorHandler = false;
    if (iv_pXMLErrorHandler == NULL) {
      iv_pXMLErrorHandler = new XMLErrorHandler();
      assert( EXISTS(iv_pXMLErrorHandler) );
      bHasOwnErrorHandler = true;
    }

    parser.setErrorHandler(iv_pXMLErrorHandler);
    try {
      parser.parse( fileIS );
    } catch (Exception e) {
      if (bHasOwnErrorHandler) {
        delete iv_pXMLErrorHandler;
        iv_pXMLErrorHandler=NULL;
      }
      throw  e;
    }
    DOMDocument* doc = parser.getDocument();
    // get top node
    DOMElement * descElem = doc->getDocumentElement();

    assert(EXISTS(descElem));

    if (bHasOwnErrorHandler ) {
      delete iv_pXMLErrorHandler;
      iv_pXMLErrorHandler =  NULL;
    }
    buildFSIndexCollection(fsDesc, descElem, alreadyImportedLocations, importfn);
  }

  void XMLParser::buildTypePriorityFromImportLocation(AnalysisEngineMetaData  & aeDesc,
      icu::UnicodeString const & fileName,
      icu::UnicodeString const & lastFileName,
      vector<icu::UnicodeString> & alreadyImportedLocations) {



    icu::UnicodeString importfn = ResourceManager::resolveFilename(fileName, lastFileName);

    for (size_t i=0; i < alreadyImportedLocations.size(); i++) {
      if (importfn.compare(alreadyImportedLocations[i]) == 0 )  {
        return;
      }
    }
    alreadyImportedLocations.push_back(importfn);

    size_t uiLen = importfn.length();
    auto_array<UChar> arBuffer( new UChar[uiLen + 1] );
    assert( EXISTS(arBuffer.get()));

    importfn.extract(0, uiLen, arBuffer.get());
    (arBuffer.get())[uiLen] = 0; // terminate the buffer with 0
    assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");

    // the following try catch block just to trigger an exception.
    // The constructor of LocalFileInputSource throws an exception on the UNIXes if the file does not
    // exist. On Windows, the parser throws this exception.
    try {
      LocalFileInputSource fileISOnlyForException((XMLCh const *) arBuffer.get() );
    } catch (XMLException const & e) {
      ErrorInfo errInfo;
      errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
      ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
      assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
      msg.addParam( arBuffer.get() );
      msg.addParam( 0 );
      msg.addParam( 0 );
      msg.addParam( (UChar const *) e.getMessage());
      errInfo.setMessage(msg);
      errInfo.setSeverity(ErrorInfo::unrecoverable);
      ExcIllFormedInputError exc(errInfo);
      throw exc;
    }

    LocalFileInputSource fileIS((XMLCh const *) arBuffer.get() );

    XercesDOMParser parser;
    parser.setValidationScheme(XercesDOMParser::Val_Auto);
    parser.setDoNamespaces(true);
    parser.setDoSchema(false);
    parser.setExternalSchemaLocation(UIMA_XML_NAMESPACE " ");

    bool bHasOwnErrorHandler = false;
    if (iv_pXMLErrorHandler == NULL) {
      iv_pXMLErrorHandler = new XMLErrorHandler();
      assert( EXISTS(iv_pXMLErrorHandler) );
      bHasOwnErrorHandler = true;
    }
    parser.setErrorHandler(iv_pXMLErrorHandler);
    try {
      parser.parse( fileIS );
    } catch (Exception e) {
      if (bHasOwnErrorHandler) {
        delete iv_pXMLErrorHandler;
        iv_pXMLErrorHandler = NULL;
      }
      throw e;
    }
    DOMDocument* doc = parser.getDocument();
    // get top node
    DOMElement * descElem = doc->getDocumentElement();

    assert(EXISTS(descElem));

    if (bHasOwnErrorHandler) {
      delete iv_pXMLErrorHandler;
      iv_pXMLErrorHandler = NULL;
    }

    buildTypePriorities(aeDesc, descElem, importfn, alreadyImportedLocations);
  }



  //--------------------------------------------------------------------
  //
  //TextAnalysisEngineSpecifierBuilder implementation
  //
  //--------------------------------------------------------------------
  TextAnalysisEngineSpecifierBuilder::TextAnalysisEngineSpecifierBuilder()
      :XMLParser(){}

  TextAnalysisEngineSpecifierBuilder::~TextAnalysisEngineSpecifierBuilder() {}
  void TextAnalysisEngineSpecifierBuilder::buildTae(AnalysisEngineDescription & taeSpec, DOMElement * specElem,
	  const icu::UnicodeString & xmlFileLoc) {
		buildAnalysisEngineDescription(taeSpec, specElem, xmlFileLoc);
  }

  void TextAnalysisEngineSpecifierBuilder::buildTaeFromMemory(AnalysisEngineDescription & taeSpec,
      char const * cpszXMLString) {
    MemBufInputSource memIS((XMLByte const *) cpszXMLString, strlen(cpszXMLString), "sysID");
    parseAnalysisEngineDescription(taeSpec, memIS);
  }


  void TextAnalysisEngineSpecifierBuilder::buildTaeFromMemory(AnalysisEngineDescription & taeSpec,
      icu::UnicodeString const & xmlString) {
	UnicodeStringRef uref(xmlString);
    MemBufInputSource memIS((XMLByte const *) uref.asUTF8().c_str(), uref.asUTF8().length(), "sysID");
    parseAnalysisEngineDescription(taeSpec, memIS);
  }

  void TextAnalysisEngineSpecifierBuilder::buildTaeFromFile(AnalysisEngineDescription & aeDesc,
      char const * fileName) {
	parseAnalysisEngineDescription(aeDesc, fileName);
  }


  void TextAnalysisEngineSpecifierBuilder::buildTaeFromFile(AnalysisEngineDescription & aeDesc,
      icu::UnicodeString const & fileName) {
	parseAnalysisEngineDescription(aeDesc, fileName);
  }

  TypeSystemDescription * TextAnalysisEngineSpecifierBuilder::buildTypeSystemSpecifierFromFile(
    char const * fileName) {
    // convert to unicode using default converter for platform
    icu::UnicodeString ustrFileName(fileName);
    return buildTypeSystemSpecifierFromFile(ustrFileName);
  }


  TypeSystemDescription * TextAnalysisEngineSpecifierBuilder::buildTypeSystemSpecifierFromFile(
    icu::UnicodeString const & fileName) {
    size_t uiLen = fileName.length();
    auto_array<UChar> arBuffer( new UChar[uiLen + 1] );
    assert( EXISTS(arBuffer.get()));

    fileName.extract(0, uiLen, arBuffer.get());
    (arBuffer.get())[uiLen] = 0; // terminate the buffer with 0
    assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");

    // the following try catch block just to trigger an exception.
    // The constructor of LocalFileInputSource throws an exception on the UNIXes if the file does not
    // exist. On Windows, the parser throws this exception.
    try {
      LocalFileInputSource fileISOnlyForException((XMLCh const *) arBuffer.get() );
    } catch (XMLException const & e) {
      ErrorInfo errInfo;
      errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
      ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
      assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
      msg.addParam( arBuffer.get() );
      msg.addParam( 0 );
      msg.addParam( 0 );
      msg.addParam( (UChar const *) e.getMessage());
      errInfo.setMessage(msg);
      errInfo.setSeverity(ErrorInfo::unrecoverable);
      ExcIllFormedInputError exc(errInfo);
      throw exc;
    }

    LocalFileInputSource fileIS((XMLCh const *) arBuffer.get() );
    TypeSystemDescription*  pDesc = new TypeSystemDescription();
	if ( !(EXISTS(pDesc)) ) {
		//TODO
		return NULL;
	}

    pDesc->setXmlFileLocation(fileName);
    parseTypeSystemDescription(*pDesc, fileIS);
    return pDesc;
  }


  TypeSystemDescription * TextAnalysisEngineSpecifierBuilder::buildTypeSystemSpecifierFromMemory(icu::UnicodeString const & xmlString) {

    std::string cpszXMLString = UnicodeStringRef(xmlString).asUTF8();
    return buildTypeSystemSpecifierFromXMLBuffer(cpszXMLString.c_str());
  }

  TypeSystemDescription * TextAnalysisEngineSpecifierBuilder::buildTypeSystemSpecifierFromXMLBuffer(char const * xmlString) {

    MemBufInputSource memIS((XMLByte const *) xmlString, strlen(xmlString), "sysID");
    TypeSystemDescription * tsDesc = new TypeSystemDescription();
	if (!EXISTS(tsDesc)) {
		//TODO: log error
		return NULL;
	}
	parseTypeSystemDescription(*tsDesc, memIS);
    return tsDesc;	
  }

  
  void TextAnalysisEngineSpecifierBuilder::buildTypePriorities(AnalysisEngineMetaData & aeMetaData,
												DOMElement * descElem,
												icu::UnicodeString const & xmlFileLoc,
												vector<icu::UnicodeString> & alreadyImportedLocations) {
	XMLParser::buildTypePriorities(aeMetaData, descElem, xmlFileLoc, alreadyImportedLocations);
  }


  void TextAnalysisEngineSpecifierBuilder::buildTypePriorities(AnalysisEngineMetaData::TyVecpTypePriorities & vecpTypePriorities,
												DOMElement * descElem) {
	XMLParser::buildTypePriorities(vecpTypePriorities, descElem);
  } 


  void TextAnalysisEngineSpecifierBuilder::buildFSIndexes(AnalysisEngineMetaData & aeMetaData,
												DOMElement * descElem)   {
	XMLParser::buildFSIndexes(aeMetaData, descElem);
  }
     

  void TextAnalysisEngineSpecifierBuilder::buildFSIndexes(AnalysisEngineMetaData::TyVecpFSIndexDescriptions & vecFSIndexDesc,
												DOMElement * descElem) {
	XMLParser::buildFSIndexes(vecFSIndexDesc, descElem);
  }


  void TextAnalysisEngineSpecifierBuilder::buildSofaMappings(AnalysisEngineDescription::TyVecpSofaMappings & sofaMappings,
												DOMElement * descElem) {
	XMLParser::buildSofaMappings(sofaMappings, descElem);
  }


  void TextAnalysisEngineSpecifierBuilder::buildConfigParams(AnalysisEngineMetaData & aeMetaData,
												DOMElement * descElem) {
	XMLParser::buildConfigParams(aeMetaData, descElem);
  }


  void TextAnalysisEngineSpecifierBuilder::buildConfigParamSettings(AnalysisEngineMetaData & aeMetadata,
												DOMElement * descElem) {
	XMLParser::buildConfigParamSettings(aeMetadata, descElem);
  }


  void TextAnalysisEngineSpecifierBuilder::appendToXMLBuffer(AnalysisEngineMetaData::TyVecpFSIndexDescriptions const & fsDesc,
												icu::UnicodeString &  xmlString) {
    AnalysisEngineDescription taeSpec;
    taeSpec.appendToXMLBuffer(fsDesc,xmlString);
  }


  void TextAnalysisEngineSpecifierBuilder::appendToXMLBuffer(AnalysisEngineMetaData::TyVecpTypePriorities const & prioDesc,
												icu::UnicodeString & xmlString) {
    AnalysisEngineDescription taeSpec;
    taeSpec.appendToXMLBuffer(prioDesc,xmlString);
  }


  void TextAnalysisEngineSpecifierBuilder::appendToXMLBuffer(AnalysisEngineDescription::TyVecpSofaMappings const & sofaMapDesc,
												icu::UnicodeString &  xmlString) {
    AnalysisEngineDescription taeSpec;
    taeSpec.appendToXMLBuffer(sofaMapDesc,xmlString);
  }


  void TextAnalysisEngineSpecifierBuilder::buildFromXMLBuffer(AnalysisEngineMetaData::TyVecpFSIndexDescriptions & fsDesc,
												icu::UnicodeString const & xmlString) {
    std::string xmlStr = UnicodeStringRef(xmlString).asUTF8();
    MemBufInputSource memIS((XMLByte const *) xmlStr.c_str(), xmlStr.length(), "sysID");
    parseFSIndexDescription(fsDesc, memIS);
  }

  void TextAnalysisEngineSpecifierBuilder::buildFromXMLBuffer(AnalysisEngineMetaData::TyVecpTypePriorities  & prioDesc,
												icu::UnicodeString const & xmlString) {
	std::string xmlStr = UnicodeStringRef(xmlString).asUTF8();
    MemBufInputSource memIS((XMLByte const *) xmlStr.c_str(), xmlStr.length(), "sysID");   
    parseTypePriorities(prioDesc, memIS);
  }


  void TextAnalysisEngineSpecifierBuilder::buildFromXMLBuffer(AnalysisEngineDescription::TyVecpSofaMappings & sofaMapDesc,
												icu::UnicodeString const & xmlString) {
	std::string xmlStr = UnicodeStringRef(xmlString).asUTF8();
    MemBufInputSource memIS((XMLByte const *) xmlStr.c_str(), xmlStr.length(), "sysID");
    parseSofaMappings(sofaMapDesc, memIS);
  }


  

 
  //----------------------------------------------------
  //
  //XMLParser private methods.
  //----------------------------------------------------
  bool XMLParser::isTrue(const icu::UnicodeString & value) const {
    /*       cout << "Buffer:" << convert(cpUCBuf) << endl;                       */
    /*       return(XMLString::compareString(cpUCBuf, convert(TRUE_VALUE)) == 0); */
    return(value.compare(TRUE_VALUE) == 0);
  }

  XMLCh const * XMLParser::convert(char const * cpBuf) const {
    bool bTranscodeSuccess = XMLString::transcode( cpBuf, gs_tempXMLChBuffer, MAXXMLCHBUFF -1 );
    assert( bTranscodeSuccess );
    return gs_tempXMLChBuffer;
  }

  icu::UnicodeString XMLParser::convert( XMLCh const * cpUCBuf ) const {
    assertWithMsg( sizeof(XMLCh) == sizeof(UChar), "Port required!");
    if (EXISTS(cpUCBuf)) {
      unsigned int uiLen = XMLString::stringLen( cpUCBuf );
      return icu::UnicodeString( (UChar const *) cpUCBuf, uiLen);
    } else {
      return "";
    }
  }

  icu::UnicodeString XMLParser::getSpannedText(DOMNode * node) {
    assert(EXISTS(node));
    DOMNodeList * children = node->getChildNodes();
    assert(EXISTS(children));
    icu::UnicodeString spannedText;
    size_t i;
    for (i=0; i < children->getLength(); i++) {
      if (children->item(i)->getNodeType() == DOMNode::TEXT_NODE) {
        spannedText.append(convert(children->item(i)->getNodeValue()));
      } else {
        const icu::UnicodeString & childTag = convert((children->item(i))->getNodeName());
        if (childTag.compare(TAG_ENV_VAR_REF) == 0) {
          icu::UnicodeString envVarName(convert(children->item(i)->getFirstChild()->getNodeValue()));
          util::EnvironmentVariableQueryOnly clEnvVar(UnicodeStringRef(envVarName).asUTF8().c_str());
          spannedText.append(clEnvVar.getValue());
        } else {
          /**
          ErrorMessage errMsg(UIMA_MSG_ID_EXC_UNKNOWN_CONFIG_XML_TAG);
          errMsg.addParam(childTag);
          errMsg.addParam(schemaFileName);
          UIMA_EXC_THROW_NEW(InvalidXMLException,
                            UIMA_ERR_CONFIG_INVALID_XML_TAG,
                            errMsg,
                            UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                            ErrorInfo::unrecoverable);
          **/
        }
      }
    }
    spannedText.trim();
    return spannedText;
  }

  DOMNode * XMLParser::findFirst(DOMNodeList * nodes,
      char const * tagName) {
    assert(EXISTS(nodes));
    DOMNode * found = NULL;
    size_t i;
    for (i=0; i < nodes->getLength(); i++) {
      if (nodes->item(i)->getNodeType() != DOMNode::ELEMENT_NODE) {
        continue;
      }

      if (XMLString::compareString((nodes->item(i))->getNodeName(), convert(tagName)) == 0) {
        found = nodes->item(i);
        break;
      }
    }
    return found;
  }

  DOMElement * XMLParser::findFirstElementNode(DOMNodeList * nodes) {
    assert(EXISTS(nodes));
    DOMElement * found = NULL;
    size_t i;
    for (i=0; i < nodes->getLength() && (! EXISTS(found)) ; i++) {
      if (nodes->item(i)->getNodeType() == DOMNode::ELEMENT_NODE) {
        found = (DOMElement *) nodes->item(i);
      }
    }
    return found;
  }

  /**
   * If an attribute doesn't exist, xerces doesn't return a null pointer,
   * but an empty string
  **/
  bool XMLParser::isDefined(const XMLCh * attrVal) const {
    return(EXISTS(attrVal) && (XMLString::compareString(attrVal, convert("")) != 0));
  }

  char const * XMLParser::TAG_AE_DESC="analysisEngineDescription";
  char const * XMLParser::TAG_TAE_DESC="taeDescription";
  char const * XMLParser::TAG_CAS_DESC="casDescription";

  char const * XMLParser::TAG_RESMGR_CONFIG_DESC="resourceManagerConfiguration";
  char const * XMLParser::TAG_CASCONSUMER_DESC="casConsumerDescription";
  char const * XMLParser::TAG_PROCESSING_RESOURCE_METADATA="processingResourceMetaData";
  char const * XMLParser::TAG_IMPL_NAME="implementationName";

  char const * XMLParser::TAG_TAE_PRIMITIVE="primitive";
  char const * XMLParser::TAG_DELEGATE_AES="delegateAnalysisEngineSpecifiers";
  char const * XMLParser::TAG_DELEGATE_AE="delegateAnalysisEngine";

  char const * XMLParser::TAG_DELEGATE_AE_INCLUDE="includeFile";
  char const * XMLParser::TAG_AN_IMPL_NAME="annotatorImplementationName";
  char const * XMLParser::UIMA_FRAMEWORK_IMP="frameworkImplementation";

  char const * XMLParser::TAG_EXTERNAL_RESOURCE_DEPENDENCIES="externalResourceDependencies";
  char const * XMLParser::TAG_EXTERNAL_RESOURCES="externalResources";

  char const * XMLParser::TAG_AE_METADATA="analysisEngineMetaData";
  char const * XMLParser::TAG_AE_NAME="name";
  char const * XMLParser::TAG_AE_DESCRIPTION="description";
  char const * XMLParser::TAG_AE_VERSION="version";
  char const * XMLParser::TAG_AE_VENDOR="vendor";

  char const * XMLParser::TAG_CONFIG_PARAMS="configurationParameters";

  char const * XMLParser::TAG_CONFIG_PARAM_GROUP="configurationGroup";
  char const * XMLParser::TAG_CONFIG_PARAM_COMMON="commonParameters";

  char const * XMLParser::TAG_CONFIG_PARAM="configurationParameter";
  char const * XMLParser::TAG_CONFIG_PARAM_NAME="name";
  char const * XMLParser::TAG_CONFIG_PARAM_DESC="description";
  char const * XMLParser::TAG_CONFIG_PARAM_TYPE="type";
  char const * XMLParser::TAG_CONFIG_PARAM_MULTIVAL="multiValued";
  char const * XMLParser::TAG_CONFIG_PARAM_MANDATORY="mandatory";
  char const * XMLParser::TAG_CONFIG_PARAM_RESTRICT="restrictOverrideTo";

  char const * XMLParser::TAG_CONFIG_PARAM_SETTINGS="configurationParameterSettings";

  char const * XMLParser::TAG_CONFIG_PARAM_SETTING_GROUP="settingsForGroup";
  char const * XMLParser::TAG_NAME_VALUE_PAIR="nameValuePair";
  char const * XMLParser::TAG_NAME_VALUE_PAIR_NAME="name";
  char const * XMLParser::TAG_NAME_VALUE_PAIR_VALUE="value";
  char const * XMLParser::TAG_NAME_VALUE_PAIR_VALUE_STRING="string";
  char const * XMLParser::TAG_NAME_VALUE_PAIR_VALUE_INT="integer";
  char const * XMLParser::TAG_NAME_VALUE_PAIR_VALUE_FLOAT="float";
  char const * XMLParser::TAG_NAME_VALUE_PAIR_VALUE_BOOL="boolean";
  char const * XMLParser::TAG_NAME_VALUE_PAIR_VALUE_ARRAY="array";

  char const * XMLParser::TAG_ENV_VAR_REF="envVarRef";

  char const * XMLParser::TAG_IMPORTS="imports";
  char const * XMLParser::TAG_IMPORT_DESC="import";
  char const * XMLParser::ATTR_IMPORT_DESC_NAME="name";
  char const * XMLParser::ATTR_IMPORT_DESC_LOCATION="location";

  char const * XMLParser::TAG_TYPE_SYSTEM_DESC="typeSystemDescription";

  char const * XMLParser::TAG_TYPES="types";
  char const * XMLParser::TAG_TYPE_DESC="typeDescription";
  char const * XMLParser::TAG_TYPE_DESC_NAME="name";
  char const * XMLParser::TAG_TYPE_DESC_SUPER="supertypeName";
  char const * XMLParser::TAG_TYPE_DESC_DESC="description";
  char const * XMLParser::TAG_TYPE_DESC_ALLOWED_VALS="allowedValues";
  char const * XMLParser::TAG_TYPE_DESC_ALLOWED_VALS_VAL="value";
  char const * XMLParser::TAG_TYPE_DESC_ALLOWED_VALS_VAL_STRING="string";
  char const * XMLParser::TAG_TYPE_DESC_ALLOWED_VALS_VAL_DESC="description";
  char const * XMLParser::TAG_TYPE_DESC_FEATURES="features";
  char const * XMLParser::TAG_TYPE_DESC_FEAT_DESC="featureDescription";
  char const * XMLParser::TAG_TYPE_DESC_FEAT_DESC_NAME="name";
  char const * XMLParser::TAG_TYPE_DESC_FEAT_DESC_RANGE="rangeTypeName";
  char const * XMLParser::TAG_TYPE_DESC_FEAT_DESC_ELEMENT="elementType";
  char const * XMLParser::TAG_TYPE_DESC_FEAT_DESC_DESC="description";
  char const * XMLParser::TAG_TYPE_DESC_FEAT_DESC_MULTREFS="multipleReferencesAllowed";

  char const * XMLParser::TAG_TYPE_PRIORITIES="typePriorities";
  char const * XMLParser::TAG_TYPE_PRIORITY_LIST="priorityList";
  char const * XMLParser::TAG_TYPE_PRIORITY_LIST_TYPE="type";

  char const * XMLParser::TAG_FS_INDEXES="fsIndexes";
  char const * XMLParser::TAG_FS_INDEX_COLLECTION="fsIndexCollection";


  char const * XMLParser::TAG_FS_INDEX_DESC="fsIndexDescription";
  char const * XMLParser::TAG_FS_INDEX_DESC_LABEL="label";
  char const * XMLParser::TAG_FS_INDEX_DESC_TYPE="typeName";
  char const * XMLParser::TAG_FS_INDEX_DESC_KIND="kind";
  char const * XMLParser::TAG_FS_INDEX_DESC_KEYS="keys";
  char const * XMLParser::TAG_FS_INDEX_KEY="fsIndexKey";
  char const * XMLParser::TAG_FS_INDEX_KEY_FEAT="featureName";
  char const * XMLParser::TAG_FS_INDEX_KEY_COMP="comparator";
  char const * XMLParser::TAG_FS_INDEX_KEY_TYPE_PRIORITY="typePriority";

  char const * XMLParser::TAG_CAPABILITIES="capabilities";

  char const * XMLParser::TAG_CAPABILITY="capability";
  char const * XMLParser::TAG_CAP_INPUTS="inputs";
  char const * XMLParser::TAG_CAP_OUTPUTS="outputs";
  char const * XMLParser::TAG_CAP_TYPE="type";
  /*    char const * XMLParser::TAG_CAP_FEATURES="features"; */
  char const * XMLParser::TAG_CAP_FEATURE="feature";
  char const * XMLParser::TAG_CAP_LANG_SUPP="languagesSupported";
  char const * XMLParser::TAG_CAP_LANG="language";

  char const * XMLParser::TAG_CAP_INPUT_SOFAS="inputSofas";
  char const * XMLParser::TAG_CAP_OUTPUT_SOFAS="outputSofas";
  char const * XMLParser::TAG_CAP_SOFA_NAME="sofaName";
  char const * XMLParser::TAG_SOFA_MAPPINGS="sofaMappings";
  char const * XMLParser::TAG_SOFA_MAPPING="sofaMapping";
  char const * XMLParser::TAG_SOFAMAP_COMPONENT_KEY="componentKey";
  char const * XMLParser::TAG_SOFAMAP_COMPONENT_SOFA_NAME="componentSofaName";
  char const * XMLParser::TAG_SOFAMAP_AGGREGATE_SOFA_NAME="aggregateSofaName";

  char const * XMLParser::TAG_FLOW="flowConstraints";
  char const * XMLParser::TAG_FLOW_FIX="fixedFlow";
  char const * XMLParser::TAG_FLOW_FIX_NODE="node";

  char const * XMLParser::TAG_FLOW_CAPABILITY_LANG="capabilityLanguageFlow";
  char const * XMLParser::TAG_FLOW_CAPABILITY_LANG_NODE="node";

  char const * XMLParser::ATTR_DELEGATE_AE_KEY="key";
  char const * XMLParser::ATTR_DELEGATE_AE_INCLUDE_FILE="href";

  char const * XMLParser::ATTR_CONFIG_PARAMS_DEF_GROUP="defaultGroup";
  char const * XMLParser::ATTR_CONFIG_PARAMS_SEARCH="searchStrategy";

  char const * XMLParser::ATTR_CONFIG_PARAM_GROUP_NAMES="names";

  char const * XMLParser::ATTR_CONFIG_PARAM_SETTING_GROUP_NAMES="name";

  /*    char const * XMLParser::ATTR_CAP_TYPE_NAME="name";    */
  /*    char const * XMLParser::ATTR_CAP_FEATURE_NAME="name"; */

  char const * XMLParser::ATTR_CAP_FEATURE_ALL="allAnnotatorFeatures";

  char const * XMLParser::TRUE_VALUE="true";

  char const *  XMLParser::FRAMEWORK_IMP_CPLUSPLUS="org.apache.uima.cpp";
  char const *  XMLParser::FRAMEWORK_IMP_JAVA="org.apache.uima.java";

  char const * XMLParser::NO_FALLBACK="none";
  char const * XMLParser::DEFAULT_FALLBACK="default_fallback";
  char const * XMLParser::LANGUAGE_FALLBACK="language_fallback";

  char const * XMLParser::CONFIG_PARAM_STRING_TYPE="String";
  char const * XMLParser::CONFIG_PARAM_INTEGER_TYPE="Integer";
  char const * XMLParser::CONFIG_PARAM_FLOAT_TYPE="Float";
  char const * XMLParser::CONFIG_PARAM_BOOLEAN_TYPE="Boolean";

  char const * XMLParser::FS_INDEX_KEY_COMP_STANDARD="standard";
  char const * XMLParser::FS_INDEX_KEY_COMP_REVERSE="reverse";

  char const * XMLParser::FS_INDEX_KEY_KIND_SORTED="sorted";
  char const * XMLParser::FS_INDEX_KEY_KIND_BAG="bag";
  char const * XMLParser::FS_INDEX_KEY_KIND_SET="set";

  char const * XMLParser::TAG_OPERATIONAL_PROPERTIES="operationalProperties";
  char const * XMLParser::TAG_MODIFIES_CAS="modifiesCas";
  char const * XMLParser::TAG_MULTIPLE_DEPLOY_ALLOWED="multipleDeploymentAllowed";
  char const * XMLParser::TAG_OUTPUTS_NEW_CASES="outputsNewCASes";



  
}
