org.javers.core.metamodel.type.JaversType Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javers-core Show documentation
Show all versions of javers-core Show documentation
JaVers - object auditing and diff framework for Java
package org.javers.core.metamodel.type;
import java.util.*;
import org.javers.common.reflection.ReflectionUtil;
import org.javers.common.string.PrettyPrintBuilder;
import org.javers.common.string.ToStringBuilder;
import org.javers.common.validation.Validate;
import org.javers.core.metamodel.annotation.TypeName;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Managed property type
*
*
* This is the convenient abstraction layer awkward
* java.lang.reflect.Type and java.lang.Class
*
* @author bartosz walacik
*/
public abstract class JaversType {
public static final Class DEFAULT_TYPE_PARAMETER = Object.class;
private final Type baseJavaType;
private final List concreteTypeArguments;
private final String name;
JaversType(Type baseJavaType) {
this(baseJavaType, Optional.empty(), 0);
}
JaversType(Type baseJavaType, Optional name, int expectedArgs) {
Validate.argumentsAreNotNull(baseJavaType, name);
this.baseJavaType = baseJavaType;
this.name = name.orElse(baseJavaType.getTypeName());
this.concreteTypeArguments = Collections.unmodifiableList(
buildListOfConcreteTypeArguments(baseJavaType, expectedArgs));
}
/**
* Factory method, delegates to self constructor
*/
JaversType spawn(Type baseJavaType) {
try {
Constructor c = this.getClass().getConstructor(Type.class);
return (JaversType)c.newInstance(new Object[]{baseJavaType});
} catch (ReflectiveOperationException exception) {
throw new RuntimeException("error calling Constructor for " + this.getClass().getName(), exception);
}
}
public boolean isGenericType() {
return (baseJavaType instanceof ParameterizedType);
}
public Type getBaseJavaType() {
return baseJavaType;
}
/**
* JaversType name, clientsClass.name by default
* or value of {@link TypeName} annotation.
*/
public String getName() {
return name;
}
public abstract boolean isInstance(Object cdo);
public abstract boolean canBePrototype();
/**
* Used for comparing as Values
*/
public boolean equals(Object left, Object right) {
return Objects.equals(left, right);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof JaversType)) return false;
JaversType that = (JaversType) o;
return baseJavaType.equals(that.baseJavaType);
}
@Override
public String toString() {
return ToStringBuilder.toString(this, "baseType", baseJavaType);
}
@Override
public int hashCode() {
return baseJavaType.hashCode();
}
/**
* For generic types, returns a list of actual Class arguments.
* For example, for Set<String>, returns String.
* Non-concrete (like ?) or missing type arguments like are defaulted to Object.
*
*
* For array, returns List with {@link Class#getComponentType()}
*/
public List getConcreteClassTypeArguments() {
return concreteTypeArguments;
}
/**
* Prints this object to String
*/
public final String prettyPrint(){
return prettyPrintBuilder().build();
}
protected PrettyPrintBuilder prettyPrintBuilder(){
return new PrettyPrintBuilder(this)
.addField("baseType", baseJavaType)
.addField("typeName", getName());
}
private static List buildListOfConcreteTypeArguments(Type baseJavaType, int expectedSize) {
List allTypeArguments = ReflectionUtil.getAllTypeArguments(baseJavaType);
List concreteTypeArguments = new ArrayList<>(expectedSize);
for (int i=0; i concreteType = ReflectionUtil.isConcreteType(existingArgument);
if (concreteType.isPresent()) {
return concreteType.get();
} else {
return DEFAULT_TYPE_PARAMETER;
}
}
}