@Nullable protected TypeInformation<?> doGetComponentType() { Class<S> rawType = getType(); if (rawType.isArray()) { return createInfo(rawType.getComponentType()); } if (isMap()) { return getTypeArgument(getBaseType(MAP_TYPES), 0); } if (Iterable.class.isAssignableFrom(rawType)) { return getTypeArgument(Iterable.class, 0); } List<TypeInformation<?>> arguments = getTypeArguments(); return arguments.size() > 0 ? arguments.get(0) : null; }
@Override public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } if (!this.getClass().equals(obj.getClass())) { return false; } ParentTypeAwareTypeInformation<?> that = (ParentTypeAwareTypeInformation<?>) obj; return this.parent == null ? that.parent == null : this.parent.equals(that.parent); }
@Nullable public TypeInformation<?> getActualType() { if (isMap()) { return getMapValueType(); } if (isCollectionLike()) { return getComponentType(); } return this; }
public TypeInformation<?> getMapValueType() { if (isMap()) { return getTypeArgument(getType(), Map.class, 1); } List<TypeInformation<?>> arguments = getTypeArguments(); if (arguments.size() > 1) { return arguments.get(1); } return null; }
@Override protected TypeInformation<?> createInfo(Type fieldType) { if (parent.getType().equals(fieldType)) { return parent; } return super.createInfo(fieldType); }
@Nullable protected TypeInformation<?> doGetMapValueType() { return isMap() ? getTypeArgument(getBaseType(MAP_TYPES), 1) : getTypeArguments().stream().skip(1).findFirst().orElse(null); }
/** * Returns the {@link TypeInformation} for the given atomic field. Will inspect fields first and return the type of a * field if available. Otherwise it will fall back to a {@link PropertyDescriptor}. * * @see #getGenericType(PropertyDescriptor) * @param fieldname * @return */ @SuppressWarnings("null") private Optional<TypeInformation<?>> getPropertyInformation(String fieldname) { Class<?> rawType = getType(); Field field = ReflectionUtils.findField(rawType, fieldname); if (field != null) { return Optional.of(createInfo(field.getGenericType())); } return findPropertyDescriptor(rawType, fieldname).map(it -> createInfo(getGenericType(it))); }
/** * Returns the {@link TypeInformation} for the given atomic field. Will inspect fields first and return the type of a * field if available. Otherwise it will fall back to a {@link PropertyDescriptor}. * * @see #getGenericType(PropertyDescriptor) * @param fieldname * @return */ private TypeInformation<?> getPropertyInformation(String fieldname) { Class<?> type = getType(); Field field = ReflectionUtils.findField(type, fieldname); if (field != null) { return createInfo(field.getGenericType()); } PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(type, fieldname); return descriptor == null ? null : createInfo(getGenericType(descriptor)); }
@Override @SuppressWarnings("unchecked") public TypeInformation<? extends S> specialize(ClassTypeInformation<?> type) { Assert.isTrue(getType().isAssignableFrom(type.getType()), String.format("%s must be assignable from %s", getType(), type.getType())); List<TypeInformation<?>> arguments = getTypeArguments(); return (TypeInformation<? extends S>) (arguments.isEmpty() ? type : createInfo(new SyntheticParamterizedType(type, arguments))); }
@Nullable private TypeInformation<?> getTypeArgument(Class<?> bound, int index) { Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(getType(), bound); if (arguments == null) { return getSuperTypeInformation(bound) instanceof ParameterizedTypeInformation ? ClassTypeInformation.OBJECT : null; } return createInfo(arguments[index]); }
public boolean isMap() { Class<S> type = getType(); for (Class<?> mapType : MAP_TYPES) { if (mapType.isAssignableFrom(type)) { return true; } } return false; }
public TypeInformation<?> getReturnType(Method method) { Assert.notNull(method); return createInfo(method.getGenericReturnType()); }
/** * Resolves the type variables to be used. Uses the parent's type variable map but overwrites variables locally * declared. * * @param type must not be {@literal null}. * @param parent must not be {@literal null}. * @return will never be {@literal null}. */ private static Map<TypeVariable<?>, Type> calculateTypeVariables(ParameterizedType type, TypeDiscoverer<?> parent) { Class<?> resolvedType = parent.resolveType(type); TypeVariable<?>[] typeParameters = resolvedType.getTypeParameters(); Type[] arguments = type.getActualTypeArguments(); Map<TypeVariable<?>, Type> localTypeVariables = new HashMap<>(parent.getTypeVariableMap()); IntStream.range(0, typeParameters.length) // .mapToObj(it -> Pair.of(typeParameters[it], flattenTypeVariable(arguments[it], localTypeVariables))) // .forEach(it -> localTypeVariables.put(it.getFirst(), it.getSecond())); return localTypeVariables; }
Map<TypeVariable, Type> variableMap = GenericTypeResolver.getTypeVariableMap(resolveType(fieldType)); return createInfo(bounds[0]); return createInfo(bounds[0]);
/** * Considers the parent's type variable map before invoking the super class method. * * @return */ @SuppressWarnings("rawtypes") protected Map<TypeVariable, Type> getTypeVariableMap() { return parent == null ? super.getTypeVariableMap() : parent.getTypeVariableMap(); }
@Override protected TypeInformation<?> createInfo(Type fieldType) { if (parent.getType().equals(fieldType)) { return parent; } return super.createInfo(fieldType); }
public boolean isMap() { return Map.class.isAssignableFrom(getType()); }
public TypeInformation<?> getReturnType(Method method) { Assert.notNull(method, "Method must not be null!"); return createInfo(method.getGenericReturnType()); }
/** * Creates a new {@link GenericArrayTypeInformation} for the given {@link GenericArrayTypeInformation} and * {@link TypeDiscoverer}. * * @param type * @param parent */ protected GenericArrayTypeInformation(GenericArrayType type, TypeDiscoverer<?> parent) { super(type, parent, parent.getTypeVariableMap()); this.type = type; }