/** \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

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;
            auto_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;
        auto_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;
            auto_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;
            }
            auto_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;
            }
            auto_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;
            }
            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
              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,
      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;
            }
            UnicodeString loc = convert(((DOMElement *) importDescs->item(j))->getAttribute(convert(ATTR_IMPORT_DESC_LOCATION)));
            if (loc.length() > 0) {
              buildFSIndexFromImportLocation(aeMetaData,
                                             loc,
                                             alreadyImportedLocations,
                                             lastFileName);
            } else {
              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++) {
                    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) {

    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) {



    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;
  }

  UnicodeString XMLParser::convert( XMLCh const * cpUCBuf ) const {
    assertWithMsg( sizeof(XMLCh) == sizeof(UChar), "Port required!");
    if (EXISTS(cpUCBuf)) {
      unsigned int uiLen = XMLString::stringLen( cpUCBuf );
      return 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";



  
}
