com.linkedin.restli.internal.server.util.ReflectionUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of restli-server Show documentation
Show all versions of restli-server Show documentation
Pegasus is a framework for building robust, scalable service architectures using dynamic discovery and simple asychronous type-checked REST + JSON APIs.
/*
Copyright (c) 2012 LinkedIn Corp.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.linkedin.restli.internal.server.util;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author dellamag
*/
public class ReflectionUtils
{
/**
* Get the underlying class for a type, or null if the type is a variable type.
*
* @param type the type
* @return the underlying class
*/
public static Class> getClass(final Type type)
{
if (type instanceof Class)
{
return (Class) type;
}
else if (type instanceof ParameterizedType)
{
return getClass(((ParameterizedType) type).getRawType());
}
else if (type instanceof GenericArrayType)
{
Type componentType = ((GenericArrayType) type).getGenericComponentType();
Class> componentClass = getClass(componentType);
if (componentClass != null)
{
return Array.newInstance(componentClass, 0).getClass();
}
else
{
return null;
}
}
else
{
return null;
}
}
private static Type walkParentsTypeChain(final Class> target,
final Class> rawType,
final Map resolvedTypes)
{
Type result;
result = walkTypeChain(target, rawType.getGenericSuperclass(), resolvedTypes);
if (result != null)
{
return result;
}
for (Type t : rawType.getGenericInterfaces())
{
result = walkTypeChain(target, t, resolvedTypes);
if (result != null)
{
return result;
}
}
return null;
}
private static Type walkTypeChain(final Class> target,
final Type type,
final Map resolvedTypes)
{
if (type == null)
{
return null;
}
Type result;
if (type instanceof Class)
{
// there is no useful information for us in raw types, so just keep going.
result = walkParentsTypeChain(target, (Class) type, resolvedTypes);
if (result != null)
{
return result;
}
}
else
{
mapTypeParameters((ParameterizedType) type, resolvedTypes);
Class> rawType = (Class) ((ParameterizedType) type).getRawType();
if (rawType.equals(target))
{
return type;
}
else
{
result = walkParentsTypeChain(target, rawType, resolvedTypes);
if (result != null)
{
return result;
}
}
}
return null;
}
private static void mapTypeParameters(final ParameterizedType type,
final Map resolvedTypes)
{
Class> rawType = (Class) type.getRawType();
Type[] actualTypeArguments = type.getActualTypeArguments();
TypeVariable>[] typeParameters = rawType.getTypeParameters();
for (int i = 0; i < actualTypeArguments.length; i++)
{
resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
}
}
/**
* Get the actual type arguments a child class has used to extend a generic base class.
*
* @param baseClass the base class
* @param childClass the child class
* @return a list of the raw classes for the actual type arguments.
*/
public static List> getTypeArguments(final Class baseClass,
final Class extends T> childClass)
{
List typeArguments = getTypeArgumentsParametrized(baseClass, childClass);
List> rawTypeArguments = null;
if (typeArguments != null)
{
rawTypeArguments = new ArrayList>();
for (Type type : typeArguments)
{
rawTypeArguments.add(getClass(type));
}
}
return rawTypeArguments;
}
/**
* Get the actual type arguments a child class has used to extend a generic base class.
*
* @param baseClass the base class
* @param childClass the child class
* @return a list of the raw classes for the actual type arguments.
*/
public static List getTypeArgumentsParametrized(final Class baseClass,
final Class extends T> childClass)
{
Map resolvedTypes = new HashMap();
Type type = walkTypeChain(baseClass, childClass, resolvedTypes);
if (type == null)
{
return null;
}
// finally, for each actual type argument provided to baseClass, determine (if
// possible)
// the raw class for that type argument.
Type[] typeArguments;
if (type instanceof Class)
{
typeArguments = ((Class) type).getTypeParameters();
}
else
{
typeArguments = ((ParameterizedType) type).getActualTypeArguments();
}
List typeArgumentsAsClasses = new ArrayList();
// resolve types by chasing down type variables.
for (Type baseType : typeArguments)
{
while (resolvedTypes.containsKey(baseType))
{
baseType = resolvedTypes.get(baseType);
}
typeArgumentsAsClasses.add(baseType);
}
return typeArgumentsAsClasses;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy