private TOP getTargetFs()

in uimaj-core/src/main/java/org/apache/uima/cas/impl/FeaturePathImpl.java [541:644]


  private TOP getTargetFs(TOP fs) {

    if (null == fs) {
      return FEATURE_PATH_FAILED;
    }

    if (this.featurePathElementNames.size() == 0) {
      targetType = fs._getTypeImpl();
      return fs;
    }

    // we have a feature path that must be evaluated

    if (boundBaseType == null || !boundBaseType.subsumes(fs._getTypeImpl())) {
      boundFeatures.clear(); // reset if supplied FS not the one the features were calculated for.
      boundBaseType = fs._getTypeImpl();
    }

    // set current FS values
    TOP currentFs = fs;

    TypeImpl rangeType = null;
    int rangeTypeClass = -1;

    // resolve feature path value
    for (int i = 0; i < this.featurePathElementNames.size(); i++) {
      if (currentFs == null) {
        return FEATURE_PATH_FAILED;
      }

      if (i < this.boundFeatures.size()) {
        targetFeature = this.boundFeatures.get(i);
        /*
         * It is possible that the previously bound feature isn't valid for this FS. This can happen
         * if a type hierarchy defines 2 different features for two different subtypes of type Tt
         * with the same feature name.
         * 
         * So we check if this bound feature is appropriate for the current FS
         */
        if (!((TypeImpl) targetFeature.getDomain()).subsumes(currentFs._getTypeImpl())) {
          setTargetFeature(currentFs, i);
        }
      } else {
        setTargetFeature(currentFs, i);
      }

      // switch feature type class
      // currentRangeTypeCode = llCas.ll_getTypeSystem().ll_getRangeType(targetFeatureCode);
      targetType = rangeType = targetFeature.getRangeImpl();
      rangeTypeClass = TypeSystemImpl.getTypeClass(rangeType);

      switch (rangeTypeClass) {
        case LowLevelCAS.TYPE_CLASS_STRING:
        case LowLevelCAS.TYPE_CLASS_INT:
        case LowLevelCAS.TYPE_CLASS_BOOLEAN:
        case LowLevelCAS.TYPE_CLASS_BYTE:
        case LowLevelCAS.TYPE_CLASS_DOUBLE:
        case LowLevelCAS.TYPE_CLASS_FLOAT:
        case LowLevelCAS.TYPE_CLASS_LONG:
        case LowLevelCAS.TYPE_CLASS_SHORT:
        case LowLevelCAS.TYPE_CLASS_INVALID:
          return currentFs; // is the fs which has the feature which is the primitive value

        case LowLevelCAS.TYPE_CLASS_BOOLEANARRAY:
        case LowLevelCAS.TYPE_CLASS_BYTEARRAY:
        case LowLevelCAS.TYPE_CLASS_DOUBLEARRAY:
        case LowLevelCAS.TYPE_CLASS_FLOATARRAY:
        case LowLevelCAS.TYPE_CLASS_FSARRAY:
        case LowLevelCAS.TYPE_CLASS_INTARRAY:
        case LowLevelCAS.TYPE_CLASS_LONGARRAY:
        case LowLevelCAS.TYPE_CLASS_SHORTARRAY:
        case LowLevelCAS.TYPE_CLASS_STRINGARRAY:
          return currentFs.getFeatureValue(targetFeature);

        case LowLevelCAS.TYPE_CLASS_FS:
          currentFs = currentFs.getFeatureValue(targetFeature);
          if (currentFs == null) {
            if (i == (this.featurePathElementNames.size() - 1)) {
              // at the last element, keep targetType == to the range type
            } else {
              //@formatter:off
            /*
             * not at the last element, so terminating the feature path prematurely.
             * There are 2 cases:
             *   - the PathValid is POSSIBLE 
             *   - the PathValid is ALWAYS 
             */
              //@formatter:on
              PathValid pathValid = TypeSystemUtils.isPathValid(this.boundBaseType,
                      this.featurePathElementNames);
              if (pathValid == PathValid.POSSIBLE) {
                targetType = null; // following v2 design here
              }
            }
            return null;
          }
          break;
        default:
          throw new CASRuntimeException(UIMARuntimeException.INTERNAL_ERROR);
      } // end of switch
    } // end of loop over all items in feature path

    return currentFs;
  }