in uimaj-core/src/main/java/org/apache/uima/cas/impl/FeatureValuePathImpl.java [839:995]
public void typeSystemInit(int fsType, LowLevelTypeSystem ts) throws CASRuntimeException {
if (this.typeNameInSnippet != null) { // if the feature path snippet
// defines
// its own
// type,
// we use that one instead of the one that's passed in
fsType = ts.ll_getCodeForTypeName(this.typeNameInSnippet);
}
if (fsType == LowLevelTypeSystem.UNKNOWN_TYPE_CODE) {
throw new CASRuntimeException(CASRuntimeException.INVALID_FEATURE_PATH,
this.typeNameInSnippet);
}
// the range type denotes what type of FSes (or
// built-in type) is contained in this feature
int rangeTypeCode = LowLevelTypeSystem.UNKNOWN_TYPE_CODE;
if (!(isBuiltInFeature() || this.isBracketsOnly)) {
// find the feature in fsType that corresponds to this path snippet
int[] features = ts.ll_getAppropriateFeatures(fsType);
boolean found = false;
int i = 0;
for (; i < features.length && (!found); i++) {
Feature feature = ts.ll_getFeatureForCode(features[i]);
found = feature.getShortName().equals(this.featureName);
}
if (found) {
// store the feature code that corresponds to this path snippet
this.featureCode = features[i - 1];
rangeTypeCode = ts.ll_getRangeType(this.featureCode);
} else {
Type type = ts.ll_getTypeForCode(fsType);
throw new CASRuntimeException(CASRuntimeException.INAPPROP_FEAT, this.featureName,
type.getName());
}
}
if (this.isBracketsOnly) {
rangeTypeCode = fsType;
}
this.typeCode = fsType;
// TODO: check mismatch between isArray and the actual rangeTypeCode
// find out whether the type is a "simple" type that may only be used in
// the last snippet of a path
Type type = ts.ll_getTypeForCode(rangeTypeCode);
this.featureRangeType = rangeTypeCode;
if (isBuiltInFeature()) {
this.isSimpleRangeType = true;
} else {
this.isSimpleRangeType = Arrays.binarySearch(SIMPLE_VAL_TYPES, type.getName()) >= 0;
}
if (this.isArrayOrList) {
int arrayType = ts.ll_getCodeForTypeName(CAS.TYPE_NAME_ARRAY_BASE);
this.isArrayType = ((TypeSystemImpl) ts).subsumes(arrayType, rangeTypeCode);
if (!this.isArrayType) {
// check whether the feature points to a list
for (int i = 0; i < LIST_TYPE_NAMES.length && !this.isListType; i++) {
int candidateType = ts.ll_getCodeForTypeName(LIST_TYPE_NAMES[i]);
this.isListType = ((TypeSystemImpl) ts).subsumes(candidateType, rangeTypeCode);
if (this.isListType) {
// determine the type class of the list
this.listType = i;
}
}
// determine the right head and tail feature, depending on the
// list type
switch (this.listType) {
case TYPE_CLASS_FSLIST:
this.headFeature = ts.ll_getCodeForFeatureName(CAS.FEATURE_FULL_NAME_FS_LIST_HEAD);
this.tailFeature = ts.ll_getCodeForFeatureName(CAS.FEATURE_FULL_NAME_FS_LIST_TAIL);
break;
case TYPE_CLASS_STRINGLIST:
this.headFeature = ts.ll_getCodeForFeatureName(CAS.FEATURE_FULL_NAME_STRING_LIST_HEAD);
this.tailFeature = ts.ll_getCodeForFeatureName(CAS.FEATURE_FULL_NAME_STRING_LIST_TAIL);
break;
case TYPE_CLASS_INTEGERLIST:
this.headFeature = ts.ll_getCodeForFeatureName(CAS.FEATURE_FULL_NAME_INTEGER_LIST_HEAD);
this.tailFeature = ts.ll_getCodeForFeatureName(CAS.FEATURE_FULL_NAME_INTEGER_LIST_TAIL);
break;
case TYPE_CLASS_FLOATLIST:
this.headFeature = ts.ll_getCodeForFeatureName(CAS.FEATURE_FULL_NAME_FLOAT_LIST_HEAD);
this.tailFeature = ts.ll_getCodeForFeatureName(CAS.FEATURE_FULL_NAME_FLOAT_LIST_TAIL);
break;
default:
break;
}
this.emptyListTypes = new Type[EMPTY_LIST_TYPE_NAMES.length];
for (int i = 0; i < EMPTY_LIST_TYPE_NAMES.length; i++) {
this.emptyListTypes[i] = ts
.ll_getTypeForCode(ts.ll_getCodeForTypeName(EMPTY_LIST_TYPE_NAMES[i]));
}
}
}
if (this.childPath != null) {
// for simple range types, only [] and fsId() are allowed as child
// path
if (this.isSimpleRangeType
&& !(this.childPath.isBracketsOnly() || this.childPath.isFsIdFeature)) {
throw new CASRuntimeException(CASRuntimeException.INVALID_FEATURE_PATH, this.featureName);
}
// continue with the child path
this.childPath.typeSystemInit(rangeTypeCode, ts);
} else if (this.isCoveredTextFeature) {
// make sure that the type is a subtype of annotation
int annotationType = ts.ll_getCodeForTypeName(CAS.TYPE_NAME_ANNOTATION);
if (!((TypeSystemImpl) ts).subsumes(annotationType, fsType)) {
throw new CASRuntimeException(CASRuntimeException.INVALID_FEATURE_PATH, this.featureName);
}
this.valueTypeName = SIMPLE_VAL_TYPES[Arrays.binarySearch(SIMPLE_VAL_TYPES,
CAS.TYPE_NAME_STRING)];
} else if (this.isFsIdFeature) {
this.valueTypeName = SIMPLE_VAL_TYPES[Arrays.binarySearch(SIMPLE_VAL_TYPES,
CAS.TYPE_NAME_INTEGER)];
} else if (this.isUniqueIdFeature) {
this.valueTypeName = SIMPLE_VAL_TYPES[Arrays.binarySearch(SIMPLE_VAL_TYPES,
CAS.TYPE_NAME_INTEGER)];
} else if (this.isTypeNameFeature) {
this.valueTypeName = SIMPLE_VAL_TYPES[Arrays.binarySearch(SIMPLE_VAL_TYPES,
CAS.TYPE_NAME_STRING)];
} else {
if (!this.isSimpleRangeType) {
CASRuntimeException exception = new CASRuntimeException(
CASRuntimeException.NO_PRIMITIVE_TAIL);
throw exception;
}
if (this.isArrayOrList && (this.arrayIndex != USE_ALL_ENTRIES)) {
// in the case of, say, authornames[0], the feature is of type
// string array, but it will evaluate to a string.
this.valueTypeName = CONTAINER_TO_ELEMENTYPE_MAP.get(type.getName());
} else if (this.isListType) { // here, we can assume that
// arrayIndex =
// USE_ALL_ENTRIES
// we don't return lists, but arrays, so we need to map the type
// accordingly
this.valueTypeName = LIST_TO_ARRAYTYPE_MAP.get(type.getName());
} else {
this.valueTypeName = SIMPLE_VAL_TYPES[Arrays.binarySearch(SIMPLE_VAL_TYPES,
type.getName())];
}
}
}