/** \file typesystemdescription.cpp .
-----------------------------------------------------------------------------

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

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

   Description: Resource Specifier Classes for Text Analysis Engines

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

   02/05/2003  Initial creation

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

#include "uima/typesystemdescription.hpp"
#include "uima/taespecifierbuilder.hpp"
#include <memory>
#include "uima/msg.h"
using namespace std;
namespace uima {

  TypeDescription::TypeDescription(const TypeDescription & crOther) {
    iv_typeName = crOther.getName();
    iv_superTypeName = crOther.getSuperTypeName();
    iv_description = crOther.getDescription();

    TyVecpFeatureDescriptions otherDescs = crOther.getFeatureDescriptions();
    TyVecpFeatureDescriptions::iterator ite;
    for (ite = otherDescs.begin(); ite != otherDescs.end(); ite++) {
      bool takesMemoryOwnership;
      auto_ptr<FeatureDescription> desc ( new FeatureDescription(**ite) );
      addFeatureDescription(desc.get(), takesMemoryOwnership);
      if (takesMemoryOwnership) {
        desc.release();
      }
    }

    TyVecpAllowedValues otherAllowedValues = crOther.getAllowedValues();
    TyVecpAllowedValues::iterator ite1;
    for (ite1 = otherAllowedValues.begin(); ite1 != otherAllowedValues.end(); ite1++) {
      bool takesMemoryOwnership;
      auto_ptr<AllowedValue> allowedval ( new AllowedValue(**ite1) );
      addAllowedValue(allowedval.get(), takesMemoryOwnership);
      if (takesMemoryOwnership) {
        allowedval.release();
      }
    }

  }

  TyErrorId TypeDescription::addFeatureDescription(FeatureDescription * feature, bool & takesMemoryOwnership) {
    takesMemoryOwnership = false;
    if (! isModifiable()) {
      return UIMA_ERR_CONFIG_OBJECT_COMITTED;
    }
    FeatureDescription * pMyFeat = getFeatureDescription(feature->getName());
    if (pMyFeat != NULL) {
      ErrorMessage msg(UIMA_MSG_ID_EXC_DUPLICATE_FEATURE_NAME, getName());
      msg.addParam(feature->getName());
      UIMA_EXC_THROW_NEW(DuplicateConfigElemException,
                         UIMA_ERR_CONFIG_DUPLICATE_FEATURE_NAME,
                         msg,
                         UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                         ErrorInfo::unrecoverable);
    } else {
      takesMemoryOwnership = true;
      iv_vecpFeatureDescriptions.push_back(feature);
    }
    return UIMA_ERR_NONE;
  }

  FeatureDescription * TypeDescription::getFeatureDescription(const icu::UnicodeString & featureName) const {
    bool found = false;
    size_t i=0;
    while ((! found) && i < iv_vecpFeatureDescriptions.size()) {
      found = (featureName.compare(iv_vecpFeatureDescriptions[i]->getName()) == 0);
      i++;
    }
    if (found) {
      return(iv_vecpFeatureDescriptions[i-1]);
    } else {
      return NULL;
    }
  }

  void TypeDescription::mergeFeatureDescriptions(const TyVecpFeatureDescriptions & descs) {
    size_t i;
    for (i=0; i < descs.size(); i++) {
      FeatureDescription * pOtherFeatDesc = descs[i]; // *ite;
      FeatureDescription * pMyFeatDesc = getFeatureDescription(pOtherFeatDesc->getName());
      if (pMyFeatDesc != NULL) {
        //the feature already exists
        //check the rangetype
        if (pMyFeatDesc->getRangeTypeName().compare(pOtherFeatDesc->getRangeTypeName()) == 0) {
          //it's the same feature, we don't have to add it
        } else {
          bool takesMemoryOwnership;
          //error: same name, different range. Will be raised during validation
          //we have to add a copy of FeatureDescription, as we have to get memory ownership
          FeatureDescription * pCopyFeatDesc = new FeatureDescription(*pOtherFeatDesc);
          addFeatureDescription(pCopyFeatDesc, takesMemoryOwnership);
          if (!takesMemoryOwnership) {
            delete pCopyFeatDesc;
          }
        }
      } else {
        //add the feature
        bool takesMemoryOwnership;
        FeatureDescription * pCopyFeatDesc = new FeatureDescription(*pOtherFeatDesc);
        addFeatureDescription(pCopyFeatDesc, takesMemoryOwnership);
        assert( takesMemoryOwnership);
      }
    }
  }

  TyErrorId TypeSystemDescription::addTypeDescription(TypeDescription * pDesc, bool & takesMemoryOwnership) {
    takesMemoryOwnership = false;
    if (! isModifiable()) {
      return UIMA_ERR_CONFIG_OBJECT_COMITTED;
    }

    TypeDescription * pMyTypeDesc = getTypeDescription(pDesc->getName());
    if (pMyTypeDesc != NULL) {
      //the type already exists
      vector<TypeDescription*> v;
      v.push_back(pDesc);
      mergeTypeDescriptions(v);
    } else {
      iv_vecpTypeDescriptions.push_back(pDesc);
      takesMemoryOwnership = true;
    }

    return UIMA_ERR_NONE;
  }

  TypeDescription * TypeSystemDescription::getTypeDescription(const icu::UnicodeString & typeName) const {
    bool found = false;
    size_t i=0;
    while ( (! found) && i<iv_vecpTypeDescriptions.size()) {
      found = (typeName.compare(iv_vecpTypeDescriptions[i]->getName()) == 0);
      i++;
    }
    if (found) {
      return(iv_vecpTypeDescriptions[i-1]);
    } else {
      return NULL;
    }
  }

  void TypeSystemDescription::mergeTypeDescriptions(const TyVecpTypeDescriptions & descs) {
    size_t i;
    for (i=0; i < descs.size(); i++) {
      TypeDescription * pOtherTypeDesc = descs[i];
      TypeDescription * pMyTypeDesc = getTypeDescription(pOtherTypeDesc->getName());
      if (EXISTS(pMyTypeDesc)) {
        //the type already exists
        //check the supertype name
        if (pMyTypeDesc->getSuperTypeName().compare(pOtherTypeDesc->getSuperTypeName()) == 0) {
          //it's the same type
          //merge the feature descriptions
          pMyTypeDesc->mergeFeatureDescriptions(pOtherTypeDesc->getFeatureDescriptions());
          pMyTypeDesc->mergeAllowedValues(pOtherTypeDesc->getAllowedValues());
        } else {
          //error: same name and different supertype name
          UIMA_EXC_THROW_NEW(DuplicateConfigElemException,
                             UIMA_ERR_CONFIG_DUPLICATE_TYPE_NAME,
                             ErrorMessage(UIMA_MSG_ID_EXC_DUPLICATE_TYPE_NAME, pOtherTypeDesc->getName()),
                             UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                             ErrorInfo::unrecoverable);
        }
      } else {
        //it's a new type description, add it
        bool takesMemoryOwnerShip;
        addTypeDescription(new TypeDescription(*pOtherTypeDesc), takesMemoryOwnerShip);
        assert( takesMemoryOwnerShip );
      }
    }
  }


  TyErrorId TypeSystemDescription::addImportDescription(ImportDescription * pDesc,
      bool & takesMemoryOwnerShip)  {
    takesMemoryOwnerShip=false;
    if (! isModifiable()) {
      return UIMA_ERR_CONFIG_OBJECT_COMITTED;
    }

    iv_vecpImportDescriptions.push_back(pDesc);
    takesMemoryOwnerShip=true;
    return UIMA_ERR_NONE;
  }


  TyErrorId TypeSystemDescription::resolveImports(vector<icu::UnicodeString> & alreadyImportedTypeSystemLocations) {

    //holds the import by name descriptors.
    vector<uima::ImportDescription *> vecpImportByNameDescriptions;

    //process each import description
    for (size_t i=0; i < iv_vecpImportDescriptions.size(); i++) {
      ImportDescription * pImport = iv_vecpImportDescriptions[i];
      //only handle import by 'location'.
      //we do not handle import by 'name' which requires looking into
      //classpath and needs to be handle in Java.
      if (pImport->getLocation().length() > 0) {
        const UnicodeString & fileLocation = pImport->findAbsoluteUrl(iv_xmlFileLoc);
        //check it is not in already Imported list
		bool needsToBeResolved=true;
        for (size_t j=0; j < alreadyImportedTypeSystemLocations.size() ;j++) {
          if (fileLocation.compare(alreadyImportedTypeSystemLocations[j]) == 0 )  {
			  needsToBeResolved=false;
			  break;
		  }
        }

		if (needsToBeResolved) {
          //resolve import
          resolveImport(fileLocation,
                      alreadyImportedTypeSystemLocations,
                      iv_vecpTypeDescriptions);
		}
		//delete this import description
        delete iv_vecpImportDescriptions[i];
        iv_vecpImportDescriptions[i] = 0;
      } else {
        // save the import descriptor.
        // will be passed to Java if calling Java
        vecpImportByNameDescriptions.push_back(iv_vecpImportDescriptions[i]);
		iv_vecpImportDescriptions[i] = 0;
      }
	  
    }
    iv_vecpImportDescriptions.clear();
	
    //add back the import by name descriptors
    for (size_t i=0; i < vecpImportByNameDescriptions.size(); i++) {
      iv_vecpImportDescriptions.push_back(vecpImportByNameDescriptions[i]);
    }
    return UIMA_ERR_NONE;
  }

  TyErrorId TypeSystemDescription::resolveImport(const icu::UnicodeString & fileLocation,
      vector<icu::UnicodeString> & alreadyImportedTypeSystemLocations,
      TyVecpTypeDescriptions & result) {

    //build typesystem description
    TextAnalysisEngineSpecifierBuilder builder;
    TypeSystemDescription * pDesc = builder.buildTypeSystemSpecifierFromFile(fileLocation);
    if (EXISTS(pDesc)) {
      //add this file to already imported list
      alreadyImportedTypeSystemLocations.push_back(fileLocation);

      //resolve imports within this descriptor
      pDesc->resolveImports(alreadyImportedTypeSystemLocations);

      //add type descriptions to result
      const TyVecpTypeDescriptions & importedTypes = pDesc->getTypeDescriptions();
      for (size_t i=0; i < importedTypes.size() ; i++) {
        TypeDescription * pOtherTypeDesc = importedTypes[i];
        bool takesMemoryOwnerShip;
        TypeDescription * pType = new TypeDescription(*pOtherTypeDesc);
        addTypeDescription(pType, takesMemoryOwnerShip);
        if (!takesMemoryOwnerShip) {
          delete pType;
        }
      }
      delete pDesc;
      return UIMA_ERR_NONE;
    } else {
      return UIMA_ERR_RESOURCE_CORRUPTED;
    }

  }


  void TypeSystemDescription::validate() {

    size_t i=0;

    TypeSystemDescription::TyVecpTypeDescriptions typeDescs = getTypeDescriptions();

    vector < icu::UnicodeString > typeNames;

    for (i=0; i<typeDescs.size(); i++) {
      typeNames.push_back(typeDescs[i]->getName());
    }

    //ensure that there are no two type descriptions with the same name
    for (i=0; i < typeNames.size(); i++) {
      if (countValues(typeNames.begin(), typeNames.end(), typeNames[i])  > 1) {
        UIMA_EXC_THROW_NEW(ValidationException,
                           UIMA_ERR_CONFIG_DUPLICATE_TYPE_NAME,
                           ErrorMessage(UIMA_MSG_ID_EXC_DUPLICATE_TYPE_NAME, typeNames[i]),
                           UIMA_MSG_ID_EXCON_VALIDATE_TAE_SPEC,
                           ErrorInfo::unrecoverable);

      }
    }

    //ensure that the type descriptions are valid
    for (i=0; i<typeDescs.size(); i++) {
		typeDescs[i]->validate();
    }
  }



  //allowed values
  TyErrorId TypeDescription::addAllowedValue(AllowedValue * allowed, bool & takesMemoryOwnership) {
    takesMemoryOwnership = false;
    if (! isModifiable()) {
      return UIMA_ERR_CONFIG_OBJECT_COMITTED;
    }
    AllowedValue * pMy = getAllowedValue(allowed->getName());
    if (pMy != NULL) {
      ErrorMessage errMsg = ErrorMessage(UIMA_MSG_ID_EXC_DUPLICATE_ALLOWED_VALUE);
      errMsg.addParam(getName());
      errMsg.addParam(allowed->getName());

      UIMA_EXC_THROW_NEW(DuplicateConfigElemException,
                         UIMA_ERR_CONFIG_DUPLICATE_ALLOWED_VALUE,
                         errMsg,
                         //ErrorMessage(UIMA_MSG_ID_EXC_DUPLICATE_ALLOWED_VALUE, allowed->getName()),
                         UIMA_MSG_ID_EXCON_BUILD_TAE_SPEC,
                         ErrorInfo::unrecoverable);

    } else {
      takesMemoryOwnership = true;
      iv_vecpAllowedValues.push_back(allowed);
    }
    return UIMA_ERR_NONE;
  }

  AllowedValue * TypeDescription::getAllowedValue(const icu::UnicodeString & name) const {
    bool found = false;
    size_t i=0;
    while ((! found) && i < iv_vecpAllowedValues.size()) {
      found = (name.compare(iv_vecpAllowedValues[i]->getName()) == 0);
      i++;
    }
    if (found) {
      return(iv_vecpAllowedValues[i-1]);
    } else {
      return NULL;
    }
  }

  void TypeDescription::mergeAllowedValues(const TyVecpAllowedValues & descs) {
    size_t i;
    for (i=0; i < descs.size(); i++) {
      AllowedValue * pOtherDesc = descs[i]; // *ite;
      AllowedValue * pMyDesc = getAllowedValue(pOtherDesc->getName());
      if (pMyDesc != NULL) {
        //already exists
      } else {
        //add
        bool takesMemoryOwnership;
        AllowedValue * pCopyDesc = new AllowedValue(*pOtherDesc);
        addAllowedValue(pCopyDesc, takesMemoryOwnership);
        assert( takesMemoryOwnership);
      }
    }
  }


  void TypeDescription::validate() {

    // if there are allowed values
    if (getAllowedValues().size() != 0) {
      if (getSuperTypeName() != "uima.cas.String") {
        UIMA_EXC_THROW_NEW(ValidationException,
                           UIMA_ERR_CONFIG_ALLOWED_VALUES_DEFINED_FOR_NON_STRING_TYPE,
                           ErrorMessage( UIMA_MSG_ID_EXC_ALLOWEDVAL_DEF_FOR_NONSTRINGTYPE,getName()),
                           UIMA_MSG_ID_EXCON_VALIDATE_TAE_SPEC,
                           ErrorInfo::unrecoverable);
      }
    }

    size_t i=0;
    TypeDescription::TyVecpFeatureDescriptions featDescs = getFeatureDescriptions();
    vector<icu::UnicodeString> featureNames;

    //ensure that there are no two feature descriptions with the same name
    for (i=0; i<featDescs.size(); i++) {
      if (countValues(featureNames.begin(), featureNames.end(), featDescs[i]->getName()) != 0) {
        ErrorMessage errMsg(UIMA_MSG_ID_EXC_DUPLICATE_FEATURE_NAME);
        errMsg.addParam(getName());
        errMsg.addParam(featureNames[i]);
        UIMA_EXC_THROW_NEW(ValidationException,
                           UIMA_ERR_CONFIG_DUPLICATE_FEATURE_NAME,
                           errMsg,
                           UIMA_MSG_ID_EXCON_VALIDATE_TAE_SPEC,
                           ErrorInfo::unrecoverable);

      } else {
        featureNames.push_back(featDescs[i]->getName());
      }
    }
  }




}

