001package ca.uhn.fhir.util;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2016 University Health Network
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import java.lang.reflect.Field;
024import java.lang.reflect.Method;
025import java.lang.reflect.ParameterizedType;
026import java.lang.reflect.Type;
027import java.lang.reflect.TypeVariable;
028import java.lang.reflect.WildcardType;
029import java.util.LinkedHashSet;
030import java.util.List;
031
032public class ReflectionUtil {
033
034        /**
035         * For a field of type List<Enumeration<Foo>>, returns Foo
036         */
037        public static Class<?> getGenericCollectionTypeOfFieldWithSecondOrderForList(Field next) {
038                if (!List.class.isAssignableFrom(next.getType())) {
039                        return getGenericCollectionTypeOfField(next);
040                }
041                
042                Class<?> type;
043                ParameterizedType collectionType = (ParameterizedType) next.getGenericType();
044                Type firstArg = collectionType.getActualTypeArguments()[0];
045                if (ParameterizedType.class.isAssignableFrom(firstArg.getClass())) {
046                        ParameterizedType pt = ((ParameterizedType) firstArg);
047                        Type pt2 = pt.getActualTypeArguments()[0];
048                        return (Class<?>) pt2;
049                } else {
050                        type = (Class<?>) firstArg;
051                }
052                return type;
053        }
054
055        public static Class<?> getGenericCollectionTypeOfField(Field next) {
056                Class<?> type;
057                ParameterizedType collectionType = (ParameterizedType) next.getGenericType();
058                Type firstArg = collectionType.getActualTypeArguments()[0];
059                if (ParameterizedType.class.isAssignableFrom(firstArg.getClass())) {
060                        ParameterizedType pt = ((ParameterizedType) firstArg);
061                        type = (Class<?>) pt.getRawType();
062                } else {
063                        type = (Class<?>) firstArg;
064                }
065                return type;
066        }
067
068        public static Class<?> getGenericCollectionTypeOfMethodParameter(Method theMethod, int theParamIndex) {
069                Class<?> type;
070                Type genericParameterType = theMethod.getGenericParameterTypes()[theParamIndex];
071                if (Class.class.equals(genericParameterType)) {
072                        return null;
073                }
074                ParameterizedType collectionType = (ParameterizedType) genericParameterType;
075                Type firstArg = collectionType.getActualTypeArguments()[0];
076                if (ParameterizedType.class.isAssignableFrom(firstArg.getClass())) {
077                        ParameterizedType pt = ((ParameterizedType) firstArg);
078                        type = (Class<?>) pt.getRawType();
079                } else {
080                        type = (Class<?>) firstArg;
081                }
082                return type;
083        }
084
085        @SuppressWarnings({ "rawtypes" })
086        public static Class<?> getGenericCollectionTypeOfMethodReturnType(Method theMethod) {
087                Class<?> type;
088                Type genericReturnType = theMethod.getGenericReturnType();
089                if (!(genericReturnType instanceof ParameterizedType)) {
090                        return null;
091                }
092                ParameterizedType collectionType = (ParameterizedType) genericReturnType;
093                Type firstArg = collectionType.getActualTypeArguments()[0];
094                if (ParameterizedType.class.isAssignableFrom(firstArg.getClass())) {
095                        ParameterizedType pt = ((ParameterizedType) firstArg);
096                        type = (Class<?>) pt.getRawType();
097                } else if (firstArg instanceof TypeVariable<?>) {
098                        Type decl = ((TypeVariable) firstArg).getBounds()[0];
099                        return (Class<?>) decl;
100                } else if (firstArg instanceof WildcardType) {
101                        Type decl = ((WildcardType) firstArg).getUpperBounds()[0];
102                        return (Class<?>) decl;
103                } else {
104                        type = (Class<?>) firstArg;
105                }
106                return type;
107        }
108
109        public static LinkedHashSet<Method> getDeclaredMethods(Class<?> theClazz) {
110                LinkedHashSet<Method> retVal = new LinkedHashSet<Method>();
111                for (Method next : theClazz.getDeclaredMethods()) {
112                        try {
113                                Method method = theClazz.getMethod(next.getName(), next.getParameterTypes());
114                                retVal.add(method);
115                        } catch (NoSuchMethodException e) {
116                                retVal.add(next);
117                        } catch (SecurityException e) {
118                                retVal.add(next);
119                        }
120                }
121                return retVal;
122        }
123
124}