public void typeSystemInit()

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())];
      }
    }
  }