org.seasar.framework.util.GenericUtil Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2004-2015 the Seasar Foundation and the Others.
*
* 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 org.seasar.framework.util;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* genericsを扱うためのユーティリティ・クラスです。
*
* @author koichik
*/
public abstract class GenericUtil {
/**
* インスタンスを構築します。
*/
protected GenericUtil() {
}
/**
* type
の原型がclazz
に代入可能であればtrue
を、
* それ以外の場合はfalse
を返します。
*
* @param type
* タイプ
* @param clazz
* クラス
* @return type
の原型がclazz
に代入可能であればtrue
*/
public static boolean isTypeOf(final Type type, final Class> clazz) {
if (Class.class.isInstance(type)) {
return clazz.isAssignableFrom(Class.class.cast(type));
}
if (ParameterizedType.class.isInstance(type)) {
final ParameterizedType parameterizedType = ParameterizedType.class
.cast(type);
return isTypeOf(parameterizedType.getRawType(), clazz);
}
return false;
}
/**
* type
の原型を返します。
*
* type
がClass
の場合はそのまま返します。
* type
がパラメータ化された型の場合はその原型を返します。
* type
がワイルドカード型の場合は(最初の)上限境界を返します。
* type
が配列の場合はその要素の実際の型の配列を返します。
* - その他の場合は
null
を返します。
*
*
* @param type
* タイプ
* @return type
の原型
*/
public static Class> getRawClass(final Type type) {
if (Class.class.isInstance(type)) {
return Class.class.cast(type);
}
if (ParameterizedType.class.isInstance(type)) {
final ParameterizedType parameterizedType = ParameterizedType.class
.cast(type);
return getRawClass(parameterizedType.getRawType());
}
if (WildcardType.class.isInstance(type)) {
final WildcardType wildcardType = WildcardType.class.cast(type);
final Type[] types = wildcardType.getUpperBounds();
return getRawClass(types[0]);
}
if (GenericArrayType.class.isInstance(type)) {
final GenericArrayType genericArrayType = GenericArrayType.class
.cast(type);
final Class> rawClass = getRawClass(genericArrayType
.getGenericComponentType());
return Array.newInstance(rawClass, 0).getClass();
}
return null;
}
/**
* type
の型引数の配列を返します。
*
* type
がパラメータ化された型でない場合はnull
を返します。
*
*
* @param type
* タイプ
* @return type
の型引数の配列
*/
public static Type[] getGenericParameter(final Type type) {
if (ParameterizedType.class.isInstance(type)) {
return ParameterizedType.class.cast(type).getActualTypeArguments();
}
if (GenericArrayType.class.isInstance(type)) {
return getGenericParameter(GenericArrayType.class.cast(type)
.getGenericComponentType());
}
return null;
}
/**
* 指定された位置のtype
の型引数を返します。
*
* type
がパラメータ化された型でない場合はnull
を返します。
*
*
* @param type
* タイプ
* @param index
* 位置
* @return 指定された位置のtype
の型引数
*/
public static Type getGenericParameter(final Type type, final int index) {
if (!ParameterizedType.class.isInstance(type)) {
return null;
}
final Type[] genericParameter = getGenericParameter(type);
if (genericParameter == null) {
return null;
}
return genericParameter[index];
}
/**
* パラメータ化された型を要素とする配列の要素型を返します。
*
* type
がパラメータ化された型の配列でない場合はnull
を返します。
*
*
* @param type
* パラメータ化された型を要素とする配列
* @return パラメータ化された型を要素とする配列の要素型
*/
public static Type getElementTypeOfArray(final Type type) {
if (!GenericArrayType.class.isInstance(type)) {
return null;
}
return GenericArrayType.class.cast(type).getGenericComponentType();
}
/**
* パラメータ化された{@link Collection}の要素型を返します。
*
* type
がパラメータ化された{@link List}でない場合はnull
を返します。
*
*
* @param type
* パラメータ化された{@link List}
* @return パラメータ化された{@link List}の要素型
*/
public static Type getElementTypeOfCollection(final Type type) {
if (!isTypeOf(type, Collection.class)) {
return null;
}
return getGenericParameter(type, 0);
}
/**
* パラメータ化された{@link List}の要素型を返します。
*
* type
がパラメータ化された{@link List}でない場合はnull
を返します。
*
*
* @param type
* パラメータ化された{@link List}
* @return パラメータ化された{@link List}の要素型
*/
public static Type getElementTypeOfList(final Type type) {
if (!isTypeOf(type, List.class)) {
return null;
}
return getGenericParameter(type, 0);
}
/**
* パラメータ化された{@link Set}の要素型を返します。
*
* type
がパラメータ化された{@link Set}でない場合はnull
を返します。
*
*
* @param type
* パラメータ化された{@link Set}
* @return パラメータ化された{@link Set}の要素型
*/
public static Type getElementTypeOfSet(final Type type) {
if (!isTypeOf(type, Set.class)) {
return null;
}
return getGenericParameter(type, 0);
}
/**
* パラメータ化された{@link Map}のキーの型を返します。
*
* type
がパラメータ化された{@link Map}でない場合はnull
を返します。
*
*
* @param type
* パラメータ化された{@link Map}
* @return パラメータ化された{@link Map}のキーの型
*/
public static Type getKeyTypeOfMap(final Type type) {
if (!isTypeOf(type, Map.class)) {
return null;
}
return getGenericParameter(type, 0);
}
/**
* パラメータ化された{@link Map}の値の型を返します。
*
* type
がパラメータ化された{@link Map}でない場合はnull
を返します。
*
*
* @param type
* パラメータ化された{@link Map}
* @return パラメータ化された{@link Map}の値の型
*/
public static Type getValueTypeOfMap(final Type type) {
if (!isTypeOf(type, Map.class)) {
return null;
}
return getGenericParameter(type, 1);
}
/**
* パラメータ化された型(クラスまたはインタフェース)が持つ型変数をキー、型引数を値とする{@link Map}を返します。
*
* @param clazz
* パラメータ化された型(クラスまたはインタフェース)
* @return パラメータ化された型が持つ型変数をキー、型引数を値とする{@link Map}
*/
public static Map, Type> getTypeVariableMap(
final Class> clazz) {
final Map, Type> map = CollectionsUtil
.newLinkedHashMap();
final TypeVariable>[] typeParameters = clazz.getTypeParameters();
for (TypeVariable> typeParameter : typeParameters) {
map.put(typeParameter, getActualClass(typeParameter.getBounds()[0],
map));
}
final Class> superClass = clazz.getSuperclass();
final Type superClassType = clazz.getGenericSuperclass();
if (superClass != null) {
gatherTypeVariables(superClass, superClassType, map);
}
final Class>[] interfaces = clazz.getInterfaces();
final Type[] interfaceTypes = clazz.getGenericInterfaces();
for (int i = 0; i < interfaces.length; ++i) {
gatherTypeVariables(interfaces[i], interfaceTypes[i], map);
}
return map;
}
/**
* パラメータ化された型(クラスまたはインタフェース)が持つ型変数および型引数を集めてmap
に追加します。
*
* @param clazz
* クラス
* @param type
* 型
* @param map
* パラメータ化された型が持つ型変数をキー、型引数を値とする{@link Map}
*/
protected static void gatherTypeVariables(final Class> clazz,
final Type type, final Map, Type> map) {
if (clazz == null) {
return;
}
gatherTypeVariables(type, map);
final Class> superClass = clazz.getSuperclass();
final Type superClassType = clazz.getGenericSuperclass();
if (superClass != null) {
gatherTypeVariables(superClass, superClassType, map);
}
final Class>[] interfaces = clazz.getInterfaces();
final Type[] interfaceTypes = clazz.getGenericInterfaces();
for (int i = 0; i < interfaces.length; ++i) {
gatherTypeVariables(interfaces[i], interfaceTypes[i], map);
}
}
/**
* パラメータ化された型(クラスまたはインタフェース)が持つ型変数および型引数を集めてmap
に追加します。
*
* @param type
* 型
* @param map
* パラメータ化された型が持つ型変数をキー、型引数を値とする{@link Map}
*/
protected static void gatherTypeVariables(final Type type,
final Map, Type> map) {
if (ParameterizedType.class.isInstance(type)) {
final ParameterizedType parameterizedType = ParameterizedType.class
.cast(type);
final TypeVariable>[] typeVariables = GenericDeclaration.class
.cast(parameterizedType.getRawType()).getTypeParameters();
final Type[] actualTypes = parameterizedType
.getActualTypeArguments();
for (int i = 0; i < actualTypes.length; ++i) {
map.put(typeVariables[i], actualTypes[i]);
}
}
}
/**
* type
の実際の型を返します。
*
* type
がClass
の場合はそのまま返します。
* type
がパラメータ化された型の場合はその原型を返します。
* type
がワイルドカード型の場合は(最初の)上限境界を返します。
* type
が型変数で引数{@code map}のキーとして含まれている場合はその変数の実際の型引数を返します。
* type
が型変数で引数{@code map}のキーとして含まれていない場合は(最初の)上限境界を返します。
* type
が配列の場合はその要素の実際の型の配列を返します。
* - その他の場合は
null
を返します。
*
*
* @param type
* タイプ
* @param map
* パラメータ化された型が持つ型変数をキー、型引数を値とする{@link Map}
* @return type
の実際の型
*/
public static Class> getActualClass(final Type type,
final Map, Type> map) {
if (Class.class.isInstance(type)) {
return Class.class.cast(type);
}
if (ParameterizedType.class.isInstance(type)) {
return getActualClass(ParameterizedType.class.cast(type)
.getRawType(), map);
}
if (WildcardType.class.isInstance(type)) {
return getActualClass(WildcardType.class.cast(type)
.getUpperBounds()[0], map);
}
if (TypeVariable.class.isInstance(type)) {
final TypeVariable> typeVariable = TypeVariable.class.cast(type);
if (map.containsKey(typeVariable)) {
return getActualClass(map.get(typeVariable), map);
}
return getActualClass(typeVariable.getBounds()[0], map);
}
if (GenericArrayType.class.isInstance(type)) {
final GenericArrayType genericArrayType = GenericArrayType.class
.cast(type);
final Class> componentClass = getActualClass(genericArrayType
.getGenericComponentType(), map);
return Array.newInstance(componentClass, 0).getClass();
}
return null;
}
/**
* パラメータ化された型を要素とする配列の実際の要素型を返します。
*
* type
がパラメータ化された型の配列でない場合はnull
を返します。
* type
がClass
の場合はそのまま返します。
* type
がパラメータ化された型の場合はその原型を返します。
* type
がワイルドカード型の場合は(最初の)上限境界を返します。
* type
が型変数の場合はその変数の実際の型引数を返します。
* type
が配列の場合はその要素の実際の型の配列を返します。
* - その他の場合は
null
を返します。
*
*
* @param type
* パラメータ化された型を要素とする配列
* @param map
* パラメータ化された型が持つ型変数をキー、型引数を値とする{@link Map}
* @return パラメータ化された型を要素とする配列の実際の要素型
*/
public static Class> getActualElementClassOfArray(final Type type,
final Map, Type> map) {
if (!GenericArrayType.class.isInstance(type)) {
return null;
}
return getActualClass(GenericArrayType.class.cast(type)
.getGenericComponentType(), map);
}
/**
* パラメータ化された{@link Collection}の実際の要素型を返します。
*
* type
がパラメータ化された{@link Collection}でない場合はnull
* を返します。
* type
がClass
の場合はそのまま返します。
* type
がパラメータ化された型の場合はその原型を返します。
* type
がワイルドカード型の場合は(最初の)上限境界を返します。
* type
が型変数の場合はその変数の実際の型引数を返します。
* type
が配列の場合はその要素の実際の型の配列を返します。
* - その他の場合は
null
を返します。
*
*
* @param type
* パラメータ化された{@link Collection}
* @param map
* パラメータ化された型が持つ型変数をキー、型引数を値とする{@link Map}
* @return パラメータ化された{@link Collection}の実際の要素型
*/
public static Class> getActualElementClassOfCollection(final Type type,
final Map, Type> map) {
if (!isTypeOf(type, Collection.class)) {
return null;
}
return getActualClass(getGenericParameter(type, 0), map);
}
/**
* パラメータ化された{@link List}の実際の要素型を返します。
*
* type
がパラメータ化された{@link List}でない場合はnull
を返します。
* type
がClass
の場合はそのまま返します。
* type
がパラメータ化された型の場合はその原型を返します。
* type
がワイルドカード型の場合は(最初の)上限境界を返します。
* type
が型変数の場合はその変数の実際の型引数を返します。
* type
が配列の場合はその要素の実際の型の配列を返します。
* - その他の場合は
null
を返します。
*
*
* @param type
* パラメータ化された{@link List}
* @param map
* パラメータ化された型が持つ型変数をキー、型引数を値とする{@link Map}
* @return パラメータ化された{@link List}の実際の要素型
*/
public static Class> getActualElementClassOfList(final Type type,
final Map, Type> map) {
if (!isTypeOf(type, List.class)) {
return null;
}
return getActualClass(getGenericParameter(type, 0), map);
}
/**
* パラメータ化された{@link Set}の実際の要素型を返します。
*
* type
がパラメータ化された{@link Set}でない場合はnull
を返します。
* type
がClass
の場合はそのまま返します。
* type
がパラメータ化された型の場合はその原型を返します。
* type
がワイルドカード型の場合は(最初の)上限境界を返します。
* type
が型変数の場合はその変数の実際の型引数を返します。
* type
が配列の場合はその要素の実際の型の配列を返します。
* - その他の場合は
null
を返します。
*
*
* @param type
* パラメータ化された{@link Set}
* @param map
* パラメータ化された型が持つ型変数をキー、型引数を値とする{@link Map}
* @return パラメータ化された{@link Set}の実際の要素型
*/
public static Class> getActualElementClassOfSet(final Type type,
final Map, Type> map) {
if (!isTypeOf(type, Set.class)) {
return null;
}
return getActualClass(getGenericParameter(type, 0), map);
}
/**
* パラメータ化された{@link Map}のキーの実際の型を返します。
*
* - キー型がパラメータ化された{@link Map}でない場合は
null
を返します。
* type
がClass
の場合はそのまま返します。
* type
がパラメータ化された型の場合はその原型を返します。
* type
がワイルドカード型の場合は(最初の)上限境界を返します。
* type
が型変数の場合はその変数の実際の型引数を返します。
* type
が配列の場合はその要素の実際の型の配列を返します。
* - その他の場合は
null
を返します。
*
*
* @param type
* パラメータ化された{@link Map}
* @param map
* パラメータ化された型が持つ型変数をキー、型引数を値とする{@link Map}
* @return パラメータ化された{@link Map}のキーの実際の型
*/
public static Class> getActualKeyClassOfMap(final Type type,
final Map, Type> map) {
if (!isTypeOf(type, Map.class)) {
return null;
}
return getActualClass(getGenericParameter(type, 0), map);
}
/**
* パラメータ化された{@link Map}の値の実際の型を返します。
*
* type
がパラメータ化された{@link Map}でない場合はnull
を返します。
* type
がClass
の場合はそのまま返します。
* type
がパラメータ化された型の場合はその原型を返します。
* type
がワイルドカード型の場合は(最初の)上限境界を返します。
* type
が型変数の場合はその変数の実際の型引数を返します。
* type
が配列の場合はその要素の実際の型の配列を返します。
* - その他の場合は
null
を返します。
*
*
* @param type
* パラメータ化された{@link Map}
* @param map
* パラメータ化された型が持つ型変数をキー、型引数を値とする{@link Map}
* @return パラメータ化された{@link Map}の値の実際の型
*/
public static Class> getActualValueClassOfMap(final Type type,
final Map, Type> map) {
if (!isTypeOf(type, Map.class)) {
return null;
}
return getActualClass(getGenericParameter(type, 1), map);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy