Coverage Report - org.apache.giraph.utils.ReflectionUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ReflectionUtils
84%
38/45
82%
23/28
5
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 package org.apache.giraph.utils;
 20  
 
 21  
 import java.lang.reflect.Array;
 22  
 import java.lang.reflect.Field;
 23  
 import java.lang.reflect.GenericArrayType;
 24  
 import java.lang.reflect.ParameterizedType;
 25  
 import java.lang.reflect.Type;
 26  
 import java.lang.reflect.TypeVariable;
 27  
 
 28  
 import java.util.ArrayList;
 29  
 import java.util.HashMap;
 30  
 import java.util.List;
 31  
 import java.util.Map;
 32  
 
 33  
 /**
 34  
  * Helper methods to get type arguments to generic classes.  Courtesy of
 35  
  * Ian Robertson (overstock.com).  Make sure to use with abstract
 36  
  * generic classes, not interfaces.
 37  
  */
 38  
 public class ReflectionUtils {
 39  
   /**
 40  
    * Do not instantiate.
 41  
    */
 42  0
   private ReflectionUtils() { }
 43  
 
 44  
   /**
 45  
    * Get the underlying class for a type, or null if the type is
 46  
    * a variable type.
 47  
    *
 48  
    * @param type the type
 49  
    * @return the underlying class
 50  
    */
 51  
   public static Class<?> getClass(Type type) {
 52  424
     if (type instanceof Class) {
 53  296
       return (Class<?>) type;
 54  128
     } else if (type instanceof ParameterizedType) {
 55  101
       return getClass(((ParameterizedType) type).getRawType());
 56  27
     } else if (type instanceof GenericArrayType) {
 57  0
       Type componentType =
 58  
           ((GenericArrayType) type).getGenericComponentType();
 59  0
       Class<?> componentClass = getClass(componentType);
 60  0
       if (componentClass != null) {
 61  0
         return Array.newInstance(componentClass, 0).getClass();
 62  
       } else {
 63  0
         return null;
 64  
       }
 65  
     } else {
 66  27
       return null;
 67  
     }
 68  
   }
 69  
 
 70  
   /**
 71  
    * Get the actual type arguments a child class has used to extend a
 72  
    * generic base class.
 73  
    *
 74  
    * @param <T> Type to evaluate.
 75  
    * @param baseClass the base class
 76  
    * @param childClass the child class
 77  
    * @return a list of the raw classes for the actual type arguments.
 78  
    */
 79  
   public static <T> List<Class<?>> getTypeArguments(
 80  
       Class<T> baseClass, Class<? extends T> childClass) {
 81  44
     Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();
 82  44
     Type type = childClass;
 83  
     // start walking up the inheritance hierarchy until we hit baseClass
 84  152
     while (! getClass(type).equals(baseClass)) {
 85  108
       if (type instanceof Class) {
 86  
         // there is no useful information for us in raw types,
 87  
         // so just keep going.
 88  46
         type = ((Class<?>) type).getGenericSuperclass();
 89  
       } else {
 90  62
         ParameterizedType parameterizedType = (ParameterizedType) type;
 91  62
         Class<?> rawType = (Class<?>) parameterizedType.getRawType();
 92  
 
 93  62
         Type[] actualTypeArguments =
 94  
             parameterizedType.getActualTypeArguments();
 95  62
         TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
 96  307
         for (int i = 0; i < actualTypeArguments.length; i++) {
 97  245
           resolvedTypes.put(typeParameters[i],
 98  
               actualTypeArguments[i]);
 99  
         }
 100  
 
 101  62
         if (!rawType.equals(baseClass)) {
 102  62
           type = rawType.getGenericSuperclass();
 103  
         }
 104  62
       }
 105  
     }
 106  
 
 107  
     // finally, for each actual type argument provided to baseClass,
 108  
     // determine (if possible)
 109  
     // the raw class for that type argument.
 110  
     Type[] actualTypeArguments;
 111  44
     if (type instanceof Class) {
 112  5
       actualTypeArguments = ((Class<?>) type).getTypeParameters();
 113  
     } else {
 114  39
       actualTypeArguments =
 115  
           ((ParameterizedType) type).getActualTypeArguments();
 116  
     }
 117  44
     List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();
 118  
     // resolve types by chasing down type variables.
 119  215
     for (Type baseType: actualTypeArguments) {
 120  416
       while (resolvedTypes.containsKey(baseType)) {
 121  245
         baseType = resolvedTypes.get(baseType);
 122  
       }
 123  171
       typeArgumentsAsClasses.add(getClass(baseType));
 124  
     }
 125  44
     return typeArgumentsAsClasses;
 126  
   }
 127  
 
 128  
   /**
 129  
    * Try to directly set a (possibly private) field on an Object.
 130  
    *
 131  
    * @param target Target to set the field on.
 132  
    * @param fieldname Name of field.
 133  
    * @param value Value to set on target.
 134  
    */
 135  
   public static void setField(Object target, String fieldname, Object value)
 136  
     throws NoSuchFieldException, IllegalAccessException {
 137  16
     Field field = findDeclaredField(target.getClass(), fieldname);
 138  16
     field.setAccessible(true);
 139  16
     field.set(target, value);
 140  16
   }
 141  
 
 142  
   /**
 143  
    * Find a declared field in a class or one of its super classes
 144  
    *
 145  
    * @param inClass Class to search for declared field.
 146  
    * @param fieldname Field name to search for
 147  
    * @return Field or will throw.
 148  
    * @throws NoSuchFieldException When field not found.
 149  
    */
 150  
   private static Field findDeclaredField(Class<?> inClass, String fieldname)
 151  
     throws NoSuchFieldException {
 152  64
     while (!Object.class.equals(inClass)) {
 153  168
       for (Field field : inClass.getDeclaredFields()) {
 154  120
         if (field.getName().equalsIgnoreCase(fieldname)) {
 155  16
           return field;
 156  
         }
 157  
       }
 158  48
       inClass = inClass.getSuperclass();
 159  
     }
 160  0
     throw new NoSuchFieldException();
 161  
   }
 162  
 }