Java tutorial
/* * Copyright (c) 2007 NTT DATA Corporation * * 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 jp.terasoluna.fw.util; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * <code>JavaBean</code>?? <code>Generics</code>???? */ public class GenericPropertyUtil { /** * */ private static final Log log = LogFactory.getLog(GenericPropertyUtil.class); /** * <code>JavaBean</code>? <code>Collection</code>????? * <p> * <h5>?</h5> * * <pre> * <code> * public class Bean { * private List<String> list; * public List<String> getList() { * return this.list; * } * } * </code> * </pre> * * ???<code>Bean</code>?????????? String.class???? * * <pre> * <code> * Bean bean = new Bean(); * Class elementType = * GenericCollectionUtil.resolveCollectionType( * bean, "list"); * </code> * </pre> * * @param bean <code>JavaBean</code> * @param name <code>Collection</code>???? * @return <code>Collection</code>??? ???????<code>Object</code>??? * @throws IllegalArgumentException <code>bean</code>? <code>null</code>??<code>name</code>? <code>null</code> * ???? <code>JavaBean</code>?? ?????????? * @throws IllegalStateException ???<code>Collection</code> ????? */ public static Class<?> resolveCollectionType(Object bean, String name) throws IllegalArgumentException, IllegalStateException { return resolveType(bean, name, Collection.class, 0); } /** * <code>JavaBean</code>? <code>Generics</code>????? * <p> * <h5>?</h5> * * <pre> * <code> * public class Bean { * private Map<String, Boolean> map; * public Map<String, Boolean> getMap() { * return this.map; * } * } * </code> * </pre> * * ???<code>Bean</code>?????????? String.class???? * * <pre> * <code> * Bean bean = new Bean(); * Class keyType = * GenericCollectionUtil.resolveType( * bean, "map", Map.class, 0); * </code> * </pre> * * @param bean <code>JavaBean</code> * @param name <code>Generics</code>???? * @param genericClass <code>Generics</code>? ??? * @param index ?? * @return <code>Generics</code>??? ???????<code>Object</code>??? * @throws IllegalArgumentException <code>bean</code>? <code>null</code>??<code>name</code>? <code>null</code> * ???? <code>genericClass</code>?<code>null</code>?? <code>index</code>?<code>0</code> * ???????? ???? <code>JavaBean</code>?? ?????????? * @throws IllegalStateException ?<code>WildCardType</code>??? */ public static Class<?> resolveType(Object bean, String name, Class<?> genericClass, int index) throws IllegalArgumentException, IllegalStateException { if (bean == null) { throw new IllegalArgumentException("Argument 'bean' (" + Object.class.getName() + " is null"); } if (StringUtils.isBlank(name)) { throw new IllegalArgumentException("Argument 'name' (" + String.class.getName() + " is empty"); } Method method = getMethod(bean, name); return resolveType(genericClass, method.getReturnType(), method.getGenericReturnType(), index); } /** * <code>JavaBean</code>??? ?? * @param bean <code>JavaBean</code> * @param name <code>Generics</code>???? * @return <code>JavaBean</code>????? * @throws IllegalArgumentException <code>JavaBean</code>?? ?????????? */ protected static Method getMethod(Object bean, String name) throws IllegalArgumentException { PropertyDescriptor descriptor = null; try { descriptor = PropertyUtils.getPropertyDescriptor(bean, name); } catch (IllegalAccessException e) { throw new IllegalArgumentException( "Failed to detect getter for " + bean.getClass().getName() + "#" + name, e); } catch (InvocationTargetException e) { throw new IllegalArgumentException( "Failed to detect getter for " + bean.getClass().getName() + "#" + name, e); } catch (NoSuchMethodException e) { throw new IllegalArgumentException( "Failed to detect getter for " + bean.getClass().getName() + "#" + name, e); } Method method = null; if (descriptor != null) { method = descriptor.getReadMethod(); } if (method == null) { throw new IllegalArgumentException(bean.getClass().getName() + " has no getter for property " + name); } return method; } /** * ??????? <code>Generics</code>????? * @param genericClass <code>Generics</code>? ??? * @param clazz ??? * @param type ????? <code>Type</code> * @param index ?? * @return <code>Generics</code>??? ???????<code>Object</code>??? * @throws IllegalArgumentException <code>genericClass</code>? <code>null</code>?? <code>clazz</code>? * <code>null</code>?? <code>index</code>?<code>0</code>???????? ???? * @throws IllegalStateException ?<code>WildCardType</code>??? */ @SuppressWarnings("unchecked") protected static Class<?> resolveType(Class<?> genericClass, @SuppressWarnings("rawtypes") Class clazz, Type type, int index) throws IllegalArgumentException, IllegalStateException { if (genericClass == null) { throw new IllegalArgumentException("Argument 'genericsClass' (" + Class.class.getName() + ") is null"); } if (clazz == null || !genericClass.isAssignableFrom(clazz)) { throw new IllegalStateException(genericClass + " is not assignable from " + clazz); } List<ParameterizedType> ancestorTypeList = null; try { ancestorTypeList = GenericsUtil.getAncestorTypeList(genericClass, clazz); } catch (IllegalStateException e) { if (log.isTraceEnabled()) { log.trace(e.getMessage()); } } if (ancestorTypeList == null) { ancestorTypeList = new ArrayList<ParameterizedType>(); } if (type instanceof ParameterizedType) { ancestorTypeList.add(0, (ParameterizedType) type); } if (ancestorTypeList.size() <= 0) { throw new IllegalStateException("No parameterizedType was detected."); } ParameterizedType parameterizedType = ancestorTypeList.get(ancestorTypeList.size() - 1); Type[] actualTypes = parameterizedType.getActualTypeArguments(); // ?????? if (index < 0 || index >= actualTypes.length) { throw new IllegalArgumentException("Argument 'index'(" + Integer.toString(index) + ") is out of bounds of" + " generics parameters"); } Class<?> resolved = Object.class; try { resolved = GenericsUtil.resolveTypeVariable(actualTypes[index], ancestorTypeList); } catch (IllegalStateException e) { if (log.isTraceEnabled()) { log.trace(e.getMessage()); } } return resolved; } }