| /** \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()); |
| } |
| } |
| } |
| |
| |
| |
| |
| } |
| |