Polishing for full type information on RepositoryMetadata.
Avoid leaking internals from TypeInformation by exposing a ….toTypeDescriptor() method in TypeInformation directly. This causes the ResolvableType handling to become an implementation detail within ClassTypeInformation and avoid client code to manually deal with both ResolvableType and TypeDescriptor creation. Changed MethodLookups back to use the resolved domain types as the advanced generics resolutions seems not to be needed here and we can avoid Fixes #2518.
This commit is contained in:
@@ -31,27 +31,6 @@ import org.springframework.data.util.TypeInformation;
|
||||
*/
|
||||
public interface RepositoryMetadata {
|
||||
|
||||
/**
|
||||
* Returns the id {@link TypeInformation} the given class is declared for.
|
||||
*
|
||||
* @return the {@link TypeInformation} class of the entity managed by the repository.
|
||||
*/
|
||||
TypeInformation<?> getIdTypeInformation();
|
||||
|
||||
/**
|
||||
* Returns the domain {@link TypeInformation} the repository is declared for.
|
||||
*
|
||||
* @return the domain class the repository is handling.
|
||||
*/
|
||||
TypeInformation<?> getDomainTypeInformation();
|
||||
|
||||
/**
|
||||
* Returns the repository interface.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Class<?> getRepositoryInterface();
|
||||
|
||||
/**
|
||||
* Returns the raw id class the given class is declared for.
|
||||
*
|
||||
@@ -60,7 +39,7 @@ public interface RepositoryMetadata {
|
||||
default Class<?> getIdType() {
|
||||
return getIdTypeInformation().getType();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the raw domain class the repository is declared for.
|
||||
*
|
||||
@@ -70,6 +49,31 @@ public interface RepositoryMetadata {
|
||||
return getDomainTypeInformation().getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link TypeInformation} of the id type of the repository.
|
||||
*
|
||||
* @return the {@link TypeInformation} class of the identifier of the entity managed by the repository. Will never be
|
||||
* {@literal null}.
|
||||
* @since 2.7
|
||||
*/
|
||||
TypeInformation<?> getIdTypeInformation();
|
||||
|
||||
/**
|
||||
* Returns the {@link TypeInformation}of the domain type the repository is declared to manage. Will never be
|
||||
* {@literal null}.
|
||||
*
|
||||
* @return the domain class the repository is handling.
|
||||
* @since 2.7
|
||||
*/
|
||||
TypeInformation<?> getDomainTypeInformation();
|
||||
|
||||
/**
|
||||
* Returns the repository interface.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Class<?> getRepositoryInterface();
|
||||
|
||||
/**
|
||||
* Returns the type {@link Method} return type as it is declared in the repository. Considers suspended methods and
|
||||
* does not unwrap component types but leaves those for further inspection.
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.repository.core.support;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.repository.RepositoryDefinition;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
@@ -52,8 +54,8 @@ public class AnnotationRepositoryMetadata extends AbstractRepositoryMetadata {
|
||||
Assert.isTrue(AnnotationUtils.findAnnotation(repositoryInterface, RepositoryDefinition.class) != null,
|
||||
() -> String.format(NO_ANNOTATION_FOUND, repositoryInterface.getName()));
|
||||
|
||||
this.idType = resolveIdType(repositoryInterface);
|
||||
this.domainType = resolveDomainType(repositoryInterface);
|
||||
this.idType = resolveType(repositoryInterface, RepositoryDefinition::idClass);
|
||||
this.domainType = resolveType(repositoryInterface, RepositoryDefinition::domainClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,25 +68,15 @@ public class AnnotationRepositoryMetadata extends AbstractRepositoryMetadata {
|
||||
return this.domainType;
|
||||
}
|
||||
|
||||
private TypeInformation<?> resolveIdType(Class<?> repositoryInterface) {
|
||||
private static TypeInformation<?> resolveType(Class<?> repositoryInterface,
|
||||
Function<RepositoryDefinition, Class<?>> extractor) {
|
||||
|
||||
RepositoryDefinition annotation = AnnotationUtils.findAnnotation(repositoryInterface, RepositoryDefinition.class);
|
||||
|
||||
if (annotation == null || annotation.idClass() == null) {
|
||||
throw new IllegalArgumentException(String.format("Could not resolve id type of %s!", repositoryInterface));
|
||||
}
|
||||
|
||||
return ClassTypeInformation.from(annotation.idClass());
|
||||
}
|
||||
|
||||
private TypeInformation<?> resolveDomainType(Class<?> repositoryInterface) {
|
||||
|
||||
RepositoryDefinition annotation = AnnotationUtils.findAnnotation(repositoryInterface, RepositoryDefinition.class);
|
||||
|
||||
if (annotation == null || annotation.domainClass() == null) {
|
||||
if ((annotation == null) || (extractor.apply(annotation) == null)) {
|
||||
throw new IllegalArgumentException(String.format("Could not resolve domain type of %s!", repositoryInterface));
|
||||
}
|
||||
|
||||
return ClassTypeInformation.from(annotation.domainClass());
|
||||
return ClassTypeInformation.from(extractor.apply(annotation));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,26 +56,28 @@ public class DefaultRepositoryMetadata extends AbstractRepositoryMetadata {
|
||||
|
||||
this.domainType = resolveTypeParameter(arguments, 0,
|
||||
() -> String.format("Could not resolve domain type of %s!", repositoryInterface));
|
||||
|
||||
|
||||
this.idType = resolveTypeParameter(arguments, 1,
|
||||
() -> String.format("Could not resolve id type of %s!", repositoryInterface));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInformation<?> getIdTypeInformation() {
|
||||
return this.idType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInformation<?> getDomainTypeInformation() {
|
||||
return this.domainType;
|
||||
}
|
||||
|
||||
private static TypeInformation<?> resolveTypeParameter(List<TypeInformation<?>> arguments, int index,
|
||||
Supplier<String> exceptionMessage) {
|
||||
|
||||
if (arguments.size() <= index || arguments.get(index) == null) {
|
||||
if ((arguments.size() <= index) || (arguments.get(index) == null)) {
|
||||
throw new IllegalArgumentException(exceptionMessage.get());
|
||||
}
|
||||
|
||||
return arguments.get(index).getGenericTypeInformation();
|
||||
}
|
||||
|
||||
public TypeInformation<?> getIdTypeInformation() {
|
||||
return this.idType;
|
||||
}
|
||||
|
||||
public TypeInformation<?> getDomainTypeInformation() {
|
||||
return this.domainType;
|
||||
return arguments.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,8 +121,8 @@ interface MethodLookups {
|
||||
|
||||
Assert.notNull(repositoryMetadata, "Repository metadata must not be null!");
|
||||
|
||||
this.entityType = ResolvableType.forType(repositoryMetadata.getDomainTypeInformation().getGenericType());
|
||||
this.idType = ResolvableType.forType(repositoryMetadata.getIdTypeInformation().getGenericType());
|
||||
this.entityType = repositoryMetadata.getDomainTypeInformation().toTypeDescriptor().getResolvableType();
|
||||
this.idType = repositoryMetadata.getIdTypeInformation().toTypeDescriptor().getResolvableType();
|
||||
this.repositoryInterface = repositoryMetadata.getRepositoryInterface();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.Set;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
@@ -30,7 +29,6 @@ import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -104,12 +102,6 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr
|
||||
return repositories;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static TypeDescriptor getIdTypeDescriptor(RepositoryInformation information) {
|
||||
TypeInformation<?> idType = information.getIdTypeInformation();
|
||||
return new TypeDescriptor(ResolvableType.forType(idType.getGenericType()), null, idType.getType().getAnnotations());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converter to create domain types from any source that can be converted into the domain types identifier type.
|
||||
@@ -157,7 +149,7 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr
|
||||
Class<?> domainType = targetType.getType();
|
||||
RepositoryInvoker invoker = repositoryInvokerFactory.getInvokerFor(domainType);
|
||||
RepositoryInformation information = repositories.getRequiredRepositoryInformation(domainType);
|
||||
TypeDescriptor idTypeDescriptor = getIdTypeDescriptor(information);
|
||||
TypeDescriptor idTypeDescriptor = information.getIdTypeInformation().toTypeDescriptor();
|
||||
|
||||
Object id = conversionService.convert(source, sourceType, idTypeDescriptor);
|
||||
|
||||
@@ -181,7 +173,7 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr
|
||||
|
||||
return repositoryInformation.map(it -> {
|
||||
|
||||
TypeDescriptor idTypeDescriptor = getIdTypeDescriptor(it);
|
||||
TypeDescriptor idTypeDescriptor = it.getIdTypeInformation().toTypeDescriptor();
|
||||
|
||||
return sourceType.equals(idTypeDescriptor)
|
||||
|| conversionService.canConvert(sourceType, idTypeDescriptor);
|
||||
@@ -249,7 +241,7 @@ public class DomainClassConverter<T extends ConversionService & ConverterRegistr
|
||||
|
||||
return information.map(it -> {
|
||||
|
||||
TypeDescriptor idTypeDescriptor = getIdTypeDescriptor(it);
|
||||
TypeDescriptor idTypeDescriptor = it.getIdTypeInformation().toTypeDescriptor();
|
||||
|
||||
return targetType.equals(idTypeDescriptor)
|
||||
|| conversionService.canConvert(idTypeDescriptor, targetType);
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
@@ -74,7 +73,7 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker {
|
||||
this.repository = repository;
|
||||
this.methods = metadata.getCrudMethods();
|
||||
TypeInformation<?> idType = metadata.getIdTypeInformation();
|
||||
this.idTypeDescriptor = new TypeDescriptor(ResolvableType.forType(idType.getGenericType()), null, idType.getType().getAnnotations());
|
||||
this.idTypeDescriptor = idType.toTypeDescriptor();
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@@ -249,7 +248,7 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker {
|
||||
protected Object convertId(Object id) {
|
||||
|
||||
Assert.notNull(id, "Id must not be null!");
|
||||
TypeDescriptor idDescriptor = TypeDescriptor.forObject(id);
|
||||
TypeDescriptor idDescriptor = TypeDescriptor.forObject(id);
|
||||
|
||||
if (idDescriptor.isAssignableTo(idTypeDescriptor)) {
|
||||
return id;
|
||||
@@ -259,7 +258,8 @@ class ReflectionRepositoryInvoker implements RepositoryInvoker {
|
||||
|
||||
if (result == null) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Identifier conversion of %s to %s unexpectedly returned null!", id, idTypeDescriptor.getType()));
|
||||
String.format("Identifier conversion of %s to %s unexpectedly returned null!", id,
|
||||
idTypeDescriptor.getType()));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType;
|
||||
@@ -55,6 +56,7 @@ public class ClassTypeInformation<S> extends TypeDiscoverer<S> {
|
||||
}
|
||||
|
||||
private final Class<S> type;
|
||||
private final Lazy<TypeDescriptor> descriptor;
|
||||
|
||||
/**
|
||||
* Simple factory method to easily create new instances of {@link ClassTypeInformation}.
|
||||
@@ -89,8 +91,11 @@ public class ClassTypeInformation<S> extends TypeDiscoverer<S> {
|
||||
* @param type
|
||||
*/
|
||||
ClassTypeInformation(Class<S> type) {
|
||||
|
||||
super(type, getTypeVariableMap(type));
|
||||
|
||||
this.type = type;
|
||||
this.descriptor = Lazy.of(() -> TypeDescriptor.valueOf(type));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,6 +157,11 @@ public class ClassTypeInformation<S> extends TypeDiscoverer<S> {
|
||||
return (TypeInformation<? extends S>) type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeDescriptor toTypeDescriptor() {
|
||||
return descriptor.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type.getName();
|
||||
|
||||
@@ -19,6 +19,8 @@ import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -29,6 +31,7 @@ import org.springframework.lang.Nullable;
|
||||
public abstract class ParentTypeAwareTypeInformation<S> extends TypeDiscoverer<S> {
|
||||
|
||||
private final TypeDiscoverer<?> parent;
|
||||
private final Lazy<TypeDescriptor> descriptor;
|
||||
private int hashCode;
|
||||
|
||||
/**
|
||||
@@ -44,7 +47,14 @@ public abstract class ParentTypeAwareTypeInformation<S> extends TypeDiscoverer<S
|
||||
protected ParentTypeAwareTypeInformation(Type type, TypeDiscoverer<?> parent, Map<TypeVariable<?>, Type> map) {
|
||||
|
||||
super(type, map);
|
||||
|
||||
this.parent = parent;
|
||||
this.descriptor = Lazy.of(() -> new TypeDescriptor(toResolvableType(), null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeDescriptor toTypeDescriptor() {
|
||||
return descriptor.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,6 +67,11 @@ public abstract class ParentTypeAwareTypeInformation<S> extends TypeDiscoverer<S
|
||||
return super.createInfo(fieldType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResolvableType toResolvableType() {
|
||||
return ResolvableType.forType(getType(), parent.toResolvableType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
||||
@@ -80,7 +95,7 @@ public abstract class ParentTypeAwareTypeInformation<S> extends TypeDiscoverer<S
|
||||
public int hashCode() {
|
||||
|
||||
if (this.hashCode == 0) {
|
||||
this.hashCode = super.hashCode() + 31 * parent.hashCode();
|
||||
this.hashCode = super.hashCode() + (31 * parent.hashCode());
|
||||
}
|
||||
|
||||
return this.hashCode;
|
||||
|
||||
@@ -25,21 +25,14 @@ import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -112,7 +105,7 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
this.componentType = Lazy.of(this::doGetComponentType);
|
||||
this.valueType = Lazy.of(this::doGetMapValueType);
|
||||
this.typeVariableMap = typeVariableMap;
|
||||
this.hashCode = 17 + 31 * type.hashCode() + 31 * typeVariableMap.hashCode();
|
||||
this.hashCode = 17 + (31 * type.hashCode()) + (31 * typeVariableMap.hashCode());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,18 +284,14 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
return parameterTypes.length == 0 ? null : parameterTypes[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<S> getType() {
|
||||
return resolvedType.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getGenericType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInformation<?> getGenericTypeInformation() {
|
||||
return createInfo(type);
|
||||
public TypeDescriptor toTypeDescriptor() {
|
||||
return new TypeDescriptor(toResolvableType(), getType(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -499,6 +488,10 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
return getSuperTypeWithin(MAP_TYPES);
|
||||
}
|
||||
|
||||
protected ResolvableType toResolvableType() {
|
||||
return ResolvableType.forType(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
||||
@@ -656,7 +649,7 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ObjectUtils.nullSafeHashCode(typeInformation);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(typeParameters);
|
||||
result = (31 * result) + ObjectUtils.nullSafeHashCode(typeParameters);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ package org.springframework.data.util;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -150,15 +150,6 @@ public interface TypeInformation<S> {
|
||||
* @return
|
||||
*/
|
||||
Class<S> getType();
|
||||
|
||||
/**
|
||||
* Returns the type of the property with all resolvable generics applied
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
default Type getGenericType() {
|
||||
return getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user type of the property if proxied.
|
||||
@@ -181,13 +172,6 @@ public interface TypeInformation<S> {
|
||||
*/
|
||||
ClassTypeInformation<?> getRawTypeInformation();
|
||||
|
||||
/**
|
||||
* Returns a {@link TypeInformation} to represent the {@link TypeInformation} of the type of the current instance with all the generics parameters resolved.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
TypeInformation<?> getGenericTypeInformation();
|
||||
|
||||
/**
|
||||
* Transparently returns the {@link java.util.Map} value type if the type is a {@link java.util.Map}, returns the
|
||||
* component type if the type {@link #isCollectionLike()} or the simple type if none of this applies.
|
||||
@@ -305,4 +289,11 @@ public interface TypeInformation<S> {
|
||||
return !type.equals(getType()) && type.isAssignableFrom(getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link TypeDescriptor} equivalent of this {@link TypeInformation}.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
* @since 2.7
|
||||
*/
|
||||
TypeDescriptor toTypeDescriptor();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import static org.springframework.util.ObjectUtils.*;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -33,6 +34,7 @@ import org.springframework.util.Assert;
|
||||
class TypeVariableTypeInformation<T> extends ParentTypeAwareTypeInformation<T> {
|
||||
|
||||
private final TypeVariable<?> variable;
|
||||
private final Lazy<List<TypeInformation<?>>> parameters;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TypeVariableTypeInformation} for the given {@link TypeVariable} owning {@link Type} and parent
|
||||
@@ -49,11 +51,18 @@ class TypeVariableTypeInformation<T> extends ParentTypeAwareTypeInformation<T> {
|
||||
Assert.notNull(variable, "TypeVariable must not be null!");
|
||||
|
||||
this.variable = variable;
|
||||
this.parameters = Lazy.of(() -> {
|
||||
return createInfo(getTypeVariableMap().getOrDefault(variable, Object.class)).getTypeArguments();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.util.TypeDiscoverer#getTypeArguments()
|
||||
*/
|
||||
@Override
|
||||
public TypeInformation<?> getGenericTypeInformation() {
|
||||
return createInfo(getTypeVariableMap().getOrDefault(variable, Object.class));
|
||||
public List<TypeInformation<?>> getTypeArguments() {
|
||||
return parameters.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user