blob: 4ce8158d6b69671b9661029acbc9a39ef99d84d4 [file] [log] [blame]
/** \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());
}
}
}
}