Exemple #1
0
 /** @return 对象提炼类型数组。从对象自身的类型到 Object,中间的继承关系中最有特点的几个类型 */
 public Class<?>[] extractTypes() {
   return typeExtractor.extract(this);
 }
  @SuppressWarnings({"rawtypes", "unchecked"})
  private static TypeInformation<?> parse(StringBuilder sb) throws ClassNotFoundException {
    String infoString = sb.toString();
    final Matcher tupleMatcher = tuplePattern.matcher(infoString);

    final Matcher writableMatcher = writablePattern.matcher(infoString);
    final Matcher enumMatcher = enumPattern.matcher(infoString);

    final Matcher basicTypeMatcher = basicTypePattern.matcher(infoString);
    final Matcher basicTypeDateMatcher = basicTypeDatePattern.matcher(infoString);

    final Matcher primitiveTypeMatcher = primitiveTypePattern.matcher(infoString);

    final Matcher valueTypeMatcher = valueTypePattern.matcher(infoString);

    final Matcher pojoGenericMatcher = pojoGenericObjectPattern.matcher(infoString);

    if (infoString.length() == 0) {
      return null;
    }

    TypeInformation<?> returnType = null;
    boolean isPrimitiveType = false;

    // tuples
    if (tupleMatcher.find()) {
      boolean isGenericTuple = true;
      String className = tupleMatcher.group(3);
      if (className == null) { // matched Tuple0
        isGenericTuple = false;
        className = tupleMatcher.group(2);
        sb.delete(0, className.length());
      } else {
        sb.delete(0, className.length() + 1); // +1 for "<"
      }

      if (infoString.startsWith(TUPLE_PACKAGE)) {
        sb.delete(0, TUPLE_PACKAGE.length() + 1); // +1 for trailing "."
      }

      int arity = Integer.parseInt(className.replaceAll("\\D", ""));
      Class<?> clazz = loadClass(TUPLE_PACKAGE + "." + className);

      TypeInformation<?>[] types = new TypeInformation<?>[arity];
      for (int i = 0; i < arity; i++) {
        types[i] = parse(sb);
        if (types[i] == null) {
          throw new IllegalArgumentException("Tuple arity does not match given parameters.");
        }
      }
      if (isGenericTuple) {
        if (sb.charAt(0) != '>') {
          throw new IllegalArgumentException("Tuple arity does not match given parameters.");
        }
        // remove '>'
        sb.deleteCharAt(0);
      }
      returnType = new TupleTypeInfo(clazz, types);
    }
    // writable types
    else if (writableMatcher.find()) {
      String className = writableMatcher.group(1);
      String fullyQualifiedName = writableMatcher.group(3);
      sb.delete(0, className.length() + 1 + fullyQualifiedName.length() + 1);
      Class<?> clazz = loadClass(fullyQualifiedName);
      returnType = WritableTypeInfo.getWritableTypeInfo((Class) clazz);
    }
    // enum types
    else if (enumMatcher.find()) {
      String className = enumMatcher.group(1);
      String fullyQualifiedName = enumMatcher.group(3);
      sb.delete(0, className.length() + 1 + fullyQualifiedName.length() + 1);
      Class<?> clazz = loadClass(fullyQualifiedName);
      returnType = new EnumTypeInfo(clazz);
    }
    // basic types
    else if (basicTypeMatcher.find()) {
      String className = basicTypeMatcher.group(1);
      sb.delete(0, className.length());
      Class<?> clazz;
      // check if fully qualified
      if (className.startsWith("java.lang")) {
        clazz = loadClass(className);
      } else {
        clazz = loadClass("java.lang." + className);
      }
      returnType = BasicTypeInfo.getInfoFor(clazz);
    }
    // special basic type "Date"
    else if (basicTypeDateMatcher.find()) {
      String className = basicTypeDateMatcher.group(1);
      sb.delete(0, className.length());
      Class<?> clazz;
      // check if fully qualified
      if (className.startsWith("java.util")) {
        clazz = loadClass(className);
      } else {
        clazz = loadClass("java.util." + className);
      }
      returnType = BasicTypeInfo.getInfoFor(clazz);
    }
    // primitive types
    else if (primitiveTypeMatcher.find()) {
      String keyword = primitiveTypeMatcher.group(1);
      sb.delete(0, keyword.length());

      Class<?> clazz = null;
      if (keyword.equals("int")) {
        clazz = int.class;
      } else if (keyword.equals("byte")) {
        clazz = byte.class;
      } else if (keyword.equals("short")) {
        clazz = short.class;
      } else if (keyword.equals("char")) {
        clazz = char.class;
      } else if (keyword.equals("double")) {
        clazz = double.class;
      } else if (keyword.equals("float")) {
        clazz = float.class;
      } else if (keyword.equals("long")) {
        clazz = long.class;
      } else if (keyword.equals("boolean")) {
        clazz = boolean.class;
      } else if (keyword.equals("void")) {
        clazz = void.class;
      }
      returnType = BasicTypeInfo.getInfoFor(clazz);
      isPrimitiveType = true;
    }
    // values
    else if (valueTypeMatcher.find()) {
      String className = valueTypeMatcher.group(1);
      sb.delete(0, className.length() + 5);

      Class<?> clazz;
      // check if fully qualified
      if (className.startsWith(VALUE_PACKAGE)) {
        clazz = loadClass(className + "Value");
      } else {
        clazz = loadClass(VALUE_PACKAGE + "." + className + "Value");
      }
      returnType = ValueTypeInfo.getValueTypeInfo((Class<Value>) clazz);
    }
    // pojo objects or generic types
    else if (pojoGenericMatcher.find()) {
      String fullyQualifiedName = pojoGenericMatcher.group(1);
      sb.delete(0, fullyQualifiedName.length());

      boolean isPojo = pojoGenericMatcher.group(2) != null;

      // pojo
      if (isPojo) {
        sb.deleteCharAt(0);
        Class<?> clazz = loadClass(fullyQualifiedName);

        ArrayList<PojoField> fields = new ArrayList<PojoField>();
        while (sb.charAt(0) != '>') {
          final Matcher fieldMatcher = fieldPattern.matcher(sb);
          if (!fieldMatcher.find()) {
            throw new IllegalArgumentException("Field name missing.");
          }
          String fieldName = fieldMatcher.group(1);
          sb.delete(0, fieldName.length() + 1);

          Field field = TypeExtractor.getDeclaredField(clazz, fieldName);
          if (field == null) {
            throw new IllegalArgumentException("Field '" + fieldName + "'could not be accessed.");
          }
          fields.add(new PojoField(field, parse(sb)));
        }
        sb.deleteCharAt(0); // remove '>'
        returnType = new PojoTypeInfo(clazz, fields);
      }
      // generic type
      else {
        returnType = new GenericTypeInfo(loadClass(fullyQualifiedName));
      }
    }

    if (returnType == null) {
      throw new IllegalArgumentException("Error at '" + infoString + "'");
    }

    // arrays
    int arrayDimensionCount = 0;
    while (sb.length() > 1 && sb.charAt(0) == '[' && sb.charAt(1) == ']') {
      arrayDimensionCount++;
      sb.delete(0, 2);
    }

    if (sb.length() > 0 && sb.charAt(0) == '[') {
      throw new IllegalArgumentException("Closing square bracket missing.");
    }

    // construct multidimension array
    if (arrayDimensionCount > 0) {
      TypeInformation<?> arrayInfo = null;

      // first dimension
      // primitive array
      if (isPrimitiveType) {
        if (returnType == BasicTypeInfo.INT_TYPE_INFO) {
          arrayInfo = PrimitiveArrayTypeInfo.INT_PRIMITIVE_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.BYTE_TYPE_INFO) {
          arrayInfo = PrimitiveArrayTypeInfo.BYTE_PRIMITIVE_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.SHORT_TYPE_INFO) {
          arrayInfo = PrimitiveArrayTypeInfo.SHORT_PRIMITIVE_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.CHAR_TYPE_INFO) {
          arrayInfo = PrimitiveArrayTypeInfo.CHAR_PRIMITIVE_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.DOUBLE_TYPE_INFO) {
          arrayInfo = PrimitiveArrayTypeInfo.DOUBLE_PRIMITIVE_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.FLOAT_TYPE_INFO) {
          arrayInfo = PrimitiveArrayTypeInfo.FLOAT_PRIMITIVE_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.LONG_TYPE_INFO) {
          arrayInfo = PrimitiveArrayTypeInfo.LONG_PRIMITIVE_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.BOOLEAN_TYPE_INFO) {
          arrayInfo = PrimitiveArrayTypeInfo.BOOLEAN_PRIMITIVE_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.VOID_TYPE_INFO) {
          throw new IllegalArgumentException("Can not create an array of void.");
        }
      }
      // basic array
      else if (returnType instanceof BasicTypeInfo && returnType != BasicTypeInfo.DATE_TYPE_INFO) {
        if (returnType == BasicTypeInfo.INT_TYPE_INFO) {
          arrayInfo = BasicArrayTypeInfo.INT_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.BYTE_TYPE_INFO) {
          arrayInfo = BasicArrayTypeInfo.BYTE_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.SHORT_TYPE_INFO) {
          arrayInfo = BasicArrayTypeInfo.SHORT_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.CHAR_TYPE_INFO) {
          arrayInfo = BasicArrayTypeInfo.CHAR_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.DOUBLE_TYPE_INFO) {
          arrayInfo = BasicArrayTypeInfo.DOUBLE_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.FLOAT_TYPE_INFO) {
          arrayInfo = BasicArrayTypeInfo.FLOAT_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.LONG_TYPE_INFO) {
          arrayInfo = BasicArrayTypeInfo.LONG_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.BOOLEAN_TYPE_INFO) {
          arrayInfo = BasicArrayTypeInfo.BOOLEAN_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.STRING_TYPE_INFO) {
          arrayInfo = BasicArrayTypeInfo.STRING_ARRAY_TYPE_INFO;
        } else if (returnType == BasicTypeInfo.VOID_TYPE_INFO) {
          throw new IllegalArgumentException("Can not create an array of void.");
        }
      }
      // object array
      else {
        arrayInfo =
            ObjectArrayTypeInfo.getInfoFor(
                loadClass("[L" + returnType.getTypeClass().getName() + ";"), returnType);
      }

      // further dimensions
      if (arrayDimensionCount > 1) {
        String arrayPrefix = "[";
        for (int i = 1; i < arrayDimensionCount; i++) {
          arrayPrefix += "[";
          arrayInfo =
              ObjectArrayTypeInfo.getInfoFor(
                  loadClass(arrayPrefix + "L" + returnType.getTypeClass().getName() + ";"),
                  arrayInfo);
        }
      }
      returnType = arrayInfo;
    }

    // remove possible ','
    if (sb.length() > 0 && sb.charAt(0) == ',') {
      sb.deleteCharAt(0);
    }

    // check if end
    return returnType;
  }