public static T getFeature()

in uimafit-core/src/main/java/org/apache/uima/fit/util/FSUtil.java [329:545]


  public static <T> T getFeature(FeatureStructure aFS, Feature aFeature, Class<T> aClazz) {
    if (aFeature.getRange().isPrimitive()) {
      switch (aFeature.getRange().getName()) {
        case CAS.TYPE_NAME_BOOLEAN:
          return aClazz.cast(aFS.getBooleanValue(aFeature));
        case CAS.TYPE_NAME_BYTE:
          return aClazz.cast(aFS.getByteValue(aFeature));
        case CAS.TYPE_NAME_DOUBLE:
          return aClazz.cast(aFS.getDoubleValue(aFeature));
        case CAS.TYPE_NAME_FLOAT:
          return aClazz.cast(aFS.getFloatValue(aFeature));
        case CAS.TYPE_NAME_INTEGER:
          return aClazz.cast(aFS.getIntValue(aFeature));
        case CAS.TYPE_NAME_LONG:
          return aClazz.cast(aFS.getLongValue(aFeature));
        case CAS.TYPE_NAME_SHORT:
          return aClazz.cast(aFS.getShortValue(aFeature));
        case CAS.TYPE_NAME_STRING:
          return aClazz.cast(aFS.getStringValue(aFeature));
        default:
          throw new IllegalArgumentException(
                  "Unable to coerce value of feature [" + aFeature.getName() + "] with type ["
                          + aFeature.getRange().getName() + "] into [" + aClazz.getName() + "]");
      }
    }

    FeatureStructure value = aFS.getFeatureValue(aFeature);

    // "null" case
    if (value == null) {
      return null;
    }

    // Here we store the values before we coerce them into the final target type
    // "target" is actually an array
    Object target;
    int length;

    // Handle case where feature is an array
    if (value instanceof CommonArrayFS) {
      // Shortcut if the user explicitly requests an array type
      if (!Object.class.equals(aClazz) && aClazz.isAssignableFrom(value.getClass())) {
        return (T) value;
      }

      CommonArrayFS source = (CommonArrayFS) value;
      length = source.size();
      if (value instanceof BooleanArrayFS) {
        target = new boolean[length];
        ((BooleanArrayFS) source).copyToArray(0, (boolean[]) target, 0, length);
      } else if (value instanceof ByteArrayFS) {
        target = new byte[length];
        ((ByteArrayFS) source).copyToArray(0, (byte[]) target, 0, length);
      } else if (value instanceof DoubleArrayFS) {
        target = new double[length];
        ((DoubleArrayFS) source).copyToArray(0, (double[]) target, 0, length);
      } else if (value instanceof FloatArrayFS) {
        target = new float[length];
        ((FloatArrayFS) source).copyToArray(0, (float[]) target, 0, length);
      } else if (value instanceof IntArrayFS) {
        target = new int[length];
        ((IntArrayFS) source).copyToArray(0, (int[]) target, 0, length);
      } else if (value instanceof LongArrayFS) {
        target = new long[length];
        ((LongArrayFS) source).copyToArray(0, (long[]) target, 0, length);
      } else if (value instanceof ShortArrayFS) {
        target = new short[length];
        ((ShortArrayFS) source).copyToArray(0, (short[]) target, 0, length);
      } else if (value instanceof StringArrayFS) {
        target = new String[length];
        ((StringArrayFS) source).copyToArray(0, (String[]) target, 0, length);
      } else {
        if (aClazz.isArray()) {
          target = Array.newInstance(aClazz.getComponentType(), length);
        } else {
          target = new FeatureStructure[length];
        }
        ((ArrayFS) source).copyToArray(0, (FeatureStructure[]) target, 0, length);
      }
    }
    // Handle case where feature is a list
    else if (isListType(aFS.getCAS().getTypeSystem(), aFeature.getRange())) {
      // Shortcut if the user explicitly requests a list type
      if (!Object.class.equals(aClazz) && aClazz.isAssignableFrom(value.getClass())) {
        return (T) value;
      }

      // Get length of list
      length = 0;
      {
        FeatureStructure cur = value;
        // We assume to by facing a non-empty element if it has a "head" feature
        while (cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD) != null) {
          length++;
          cur = cur.getFeatureValue(cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_TAIL));
        }
      }

      switch (aFeature.getRange().getName()) {
        case CAS.TYPE_NAME_FLOAT_LIST: {
          float[] floatTarget = new float[length];
          int i = 0;
          FeatureStructure cur = value;
          // We assume to by facing a non-empty element if it has a "head" feature
          while (cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD) != null) {
            floatTarget[i] = cur
                    .getFloatValue(cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD));
            cur = cur.getFeatureValue(
                    cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_TAIL));
          }
          target = floatTarget;
          break;
        }
        case CAS.TYPE_NAME_INTEGER_LIST: {
          int[] intTarget = new int[length];
          int i = 0;
          FeatureStructure cur = value;
          // We assume to by facing a non-empty element if it has a "head" feature
          while (cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD) != null) {
            intTarget[i] = cur
                    .getIntValue(cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD));
            cur = cur.getFeatureValue(
                    cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_TAIL));
          }
          target = intTarget;
          break;
        }
        case CAS.TYPE_NAME_STRING_LIST: {
          String[] stringTarget = new String[length];
          int i = 0;
          FeatureStructure cur = value;
          // We assume to by facing a non-empty element if it has a "head" feature
          while (cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD) != null) {
            stringTarget[i] = cur
                    .getStringValue(cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD));
            cur = cur.getFeatureValue(
                    cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_TAIL));
          }
          target = stringTarget;
          break;
        }
        default: {
          if (aClazz.isArray()) {
            target = Array.newInstance(aClazz.getComponentType(), length);
          } else {
            target = new FeatureStructure[length];
          }
          int i = 0;
          FeatureStructure cur = value;
          // We assume to by facing a non-empty element if it has a "head" feature
          while (cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD) != null) {
            Array.set(target, i, cur.getFeatureValue(
                    cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_HEAD)));
            i++;
            cur = cur.getFeatureValue(
                    cur.getType().getFeatureByBaseName(CAS.FEATURE_BASE_NAME_TAIL));
          }
          break;
        }
      }
    } else if (aClazz.isAssignableFrom(value.getClass())) {
      return (T) value;
    } else if (aFS.getCAS().getTypeSystem().subsumes(CasUtil.getType(aFS.getCAS(), aClazz),
            aFeature.getRange())) {
      return (T) value;
    } else {
      throw new IllegalArgumentException(
              "Unable to coerce value of feature [" + aFeature.getName() + "] with type ["
                      + aFeature.getRange().getName() + "] into [" + aClazz.getName() + "]");
    }

    // Handle case where return value is an array
    if (aClazz.isArray()) {
      return aClazz.cast(target);
    }

    // Handle case where return value is Object
    Class targetClass = aClazz;
    if (Object.class.equals(aClazz)) {
      targetClass = List.class;
    }

    // Handle case where return value is a collection
    if (Collection.class.isAssignableFrom(targetClass)) {
      Collection targetCollection;

      if (targetClass.isInterface()) {
        // If the target is an interface, try using a default implementation;
        if (List.class.isAssignableFrom(targetClass)) {
          targetCollection = new ArrayList(length);
        } else if (Set.class.isAssignableFrom(targetClass)) {
          targetCollection = new HashSet(length);
        } else {
          throw new IllegalArgumentException("Unable to coerce value of feature ["
                  + aFeature.getName() + "] with type [" + aFeature.getRange().getName()
                  + "] into [" + targetClass.getName() + "]");
        }
      } else {
        // Try to instantiate using 0-args constructor
        try {
          targetCollection = (Collection) targetClass.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
          throw new IllegalArgumentException("Unable to coerce value of feature ["
                  + aFeature.getName() + "] with type [" + aFeature.getRange().getName()
                  + "] into [" + targetClass.getName() + "]", e);
        }
      }
      for (int i = 0; i < length; i++) {
        targetCollection.add(Array.get(target, i));
      }
      return (T) targetClass.cast(targetCollection);
    }

    throw new IllegalArgumentException(
            "Unable to coerce value of feature [" + aFeature.getName() + "] with type ["
                    + aFeature.getRange().getName() + "] into [" + targetClass.getName() + "]");
  }