com.iopipe.generic.ObjectTranslator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of iopipe Show documentation
Show all versions of iopipe Show documentation
This project provides analytics and distributed tracing for event-driven
applications running on AWS Lambda using the IOpipe service.
The newest version!
package com.iopipe.generic;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.MalformedParameterizedTypeException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.List;
/**
* This class manages converters to the target type.
*
* @since 2018/08/20
*/
public abstract class ObjectTranslator
{
/** The type to convert from. */
protected final Type from;
/** The type to convert to. */
protected final Type to;
/**
* Initializes a translator to the given type.
*
* @param __f The from type.
* @param __t The target type
* @throws NullPointerException On null arguments.
* @since 2018/08/20
*/
ObjectTranslator(Type __f, Type __t)
throws NullPointerException
{
if (__f == null || __t == null)
throw new NullPointerException();
this.from = __f;
this.to = __t;
}
/**
* Translates from the given object to the destination object.
*
* @param __f The object to translate, if this is null then no object
* is translated and null is returned.
* @return The result of the translation, if {@code __f} is null then this
* will return null.
* @since 2018/08/20
*/
public abstract Object translate(Object __f);
/**
* {@inheritDoc}
* @since 2018/08/20
*/
@Override
public final boolean equals(Object __o)
{
if (this == __o)
return true;
if (!(__o instanceof ObjectTranslator))
return false;
ObjectTranslator o = (ObjectTranslator)__o;
return this.from.equals(o.from) &&
this.to.equals(o.to);
}
/**
* Returns the from type.
*
* @return The from type.
* @since 2018/08/22
*/
public final Type from()
{
return this.from;
}
/**
* {@inheritDoc}
* @since 2018/08/20
*/
@Override
public final int hashCode()
{
return this.from.hashCode() ^ this.to.hashCode();
}
/**
* Returns the to type.
*
* @return The to type.
* @since 2018/08/22
*/
public final Type to()
{
return this.to;
}
/**
* Creates a translator for converting objects to the given type.
*
* @param __f The from type.
* @param __t The to class.
* @return A translator to translate from one class to the other.
* @since 2018/08/20
*/
public static final ObjectTranslator translator(Type __f, Type __t)
throws NullPointerException
{
if (__f == null || __t == null)
throw new NullPointerException();
// Identity conversion or any type to Object (which does no
// conversion at all)
if (__f.equals(__t) || __t.equals(Object.class))
return new __IdentityConvert__(__f, __t);
// Conversion of string to other type, construct or valueOf
MethodHandles.Lookup lookup = MethodHandles.lookup();
if (__f.equals(String.class) && (__t instanceof Class))
{
Class> tcl = (Class>)__t;
// Try valueOf() first
try
{
return new __StringToConvert__(__f, __t,
lookup.findStatic(tcl, "valueOf",
MethodType.methodType(tcl, String.class)));
}
catch (IllegalAccessException|NoSuchMethodException e)
{
}
// Try a constructor
try
{
return new __StringToConvert__(__f, __t,
lookup.findConstructor(tcl,
MethodType.methodType(void.class, String.class)));
}
catch (IllegalAccessException|NoSuchMethodException e)
{
}
}
// The source is a number type
if ((__f instanceof Class) && Number.class.isAssignableFrom(((Class>)__f)))
{
// To int
if (__t.equals(Integer.class))
return new __FunctionConvert__(__f, __t,
(__o) -> Integer.valueOf(((Number)__o).intValue()));
// To long
else if (__t.equals(Long.class))
return new __FunctionConvert__(__f, __t,
(__o) -> Long.valueOf(((Number)__o).longValue()));
// To float
else if (__t.equals(Float.class))
return new __FunctionConvert__(__f, __t,
(__o) -> Float.valueOf(((Number)__o).floatValue()));
// To double
else if (__t.equals(Double.class))
return new __FunctionConvert__(__f, __t,
(__o) -> Double.valueOf(((Number)__o).doubleValue()));
}
// The source and target are array/list compatible
Type sl = ObjectTranslator.__getListComponent(__f, true),
tl = ObjectTranslator.__getListComponent(__t, false);
if (sl != null && tl != null)
return new __ListyConvert__(__f, __t,
ObjectTranslator.translator(sl, tl));
// Could not setup a well known basic conversion so fall back to a
// generic conversion
return new __JacksonConvert__(__f, __t);
}
/**
* Returns the type that is used for anything that can contain a list type
* or an array.
*
* @param __t The type to check.
* @param __anylist Can any list type be used?
* @return If the type is a list or array then this returns the component
* type.
* @throws NullPointerException On null arguments.
* @since 2018/08/27
*/
static final Type __getListComponent(Type __t, boolean __anylist)
throws NullPointerException
{
if (__t == null)
throw new NullPointerException();
// This represents a raw list?
if (__t instanceof Class)
{
Class> t = (Class>)__t;
// Target is an array, use the component type
if (t.isArray())
return t.getComponentType();
// Is kind of list
else if (__anylist && List.class.isAssignableFrom(t))
return Object.class;
// Just the base list
else if (!__anylist && List.class.equals(t))
return Object.class;
// Not one
return null;
}
// Could be a list
else if (__t instanceof ParameterizedType)
{
ParameterizedType t = (ParameterizedType)__t;
// Check if the base raw type is a list
Class> raw = ObjectTranslator.__rawClass(t);
if (__anylist && !List.class.isAssignableFrom(raw))
return null;
else if (!__anylist && !List.class.equals(raw))
return null;
// Only use the first argument if it is valid
Type[] args = t.getActualTypeArguments();
if (args.length == 1)
return args[0];
// Otherwise do not consider this type
return null;
}
// Is an array
else if (__t instanceof GenericArrayType)
return ((GenericArrayType)__t).getGenericComponentType();
// Not a list type
return null;
}
/**
* Returns the raw class.
*
* @param __t The type to get the raw type from.
* @return The raw type
* @throw NullPointerException On null arguments.
* @since 2018/08/27
*/
static final Class> __rawClass(Type __t)
throws NullPointerException
{
if (__t == null)
throw new NullPointerException();
// Just a normal class
if (__t instanceof Class)
return (Class>)__t;
// Parameterized type
else if (__t instanceof ParameterizedType)
return ObjectTranslator.__rawClass(((ParameterizedType)__t).getRawType());
// Type variable, use its bound
else if (__t instanceof TypeVariable)
return ObjectTranslator.__rawClass(ObjectTranslator.__unbound(((TypeVariable)__t)));
// Unknown, lets just call it object
return Object.class;
}
/**
* Unbounds the type variable.
*
* @param __tv The type variable to unbound.
* @return The unbound type.
* @throws NullPointerException On null arguments.
* @since 2018/09/04
*/
static Type __unbound(TypeVariable __tv)
throws NullPointerException
{
if (__tv == null)
throw new NullPointerException();
// The bounds might not exist or may not even be valid
try
{
Type[] bounds = __tv.getBounds();
// No bounds, just use object
if (bounds.length <= 0)
return Object.class;
// Just use the first bound
return bounds[0];
}
// If these happen just use Object
catch (TypeNotPresentException|MalformedParameterizedTypeException e)
{
return Object.class;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy