Coverage Report - org.dozer.util.BridgedMethodFinder
 
Classes in this File Line Coverage Branch Coverage Complexity
BridgedMethodFinder
8%
3/36
7%
3/42
7.8
 
 1  
 /**
 2  
  * Copyright 2005-2013 Dozer Project
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.dozer.util;
 17  
 
 18  
 import java.lang.reflect.Method;
 19  
 
 20  
 /**
 21  
  * Utility class to find methods that are bridged by other methods (bridge methods)
 22  
  *
 23  
  * @author andor.greissl
 24  
  */
 25  
 public final class BridgedMethodFinder {
 26  
 
 27  
   /** utility class constructor */
 28  0
   private BridgedMethodFinder() {}
 29  
 
 30  
   /**
 31  
    * Find the original method for the Java5 bridge Method. If the supplied method
 32  
    * is not a bridge method then the supplied method is returned.
 33  
    * If the supplied method is a bridge method, the algorithm tries to find a more
 34  
    * specific method with parameters and return types that can be assigned to the
 35  
    * the supplied method parameters and return type.
 36  
    *
 37  
    * Informally, method A is more specific than method B if
 38  
    * any invocation handled by method A can also be handled by method B.
 39  
    *
 40  
    * @param bridgeMethod the bridge method (Java 5 specific)
 41  
    * @param targetClass the class the method belongs to
 42  
    * @return the original method or a more specific method if available
 43  
    */
 44  
   public static Method findMethod(final Method bridgeMethod, final Class< ? > targetClass) {
 45  112803
     if (bridgeMethod == null || targetClass == null)
 46  0
       return bridgeMethod;
 47  
 
 48  112803
     if (!bridgeMethod.isBridge())
 49  112803
       return bridgeMethod;
 50  
 
 51  0
     Method[] methods = bridgeMethod.getDeclaringClass().getDeclaredMethods();
 52  0
     for (Method method : methods) {
 53  
       // don't care about methods that are bridge methods
 54  0
       if (method.isBridge())
 55  0
         continue;
 56  
 
 57  
       // check if the method is more specific
 58  0
       if (isAssignable(method, bridgeMethod))
 59  0
         return method;
 60  
     }
 61  0
     return bridgeMethod;
 62  
   }
 63  
 
 64  
   /**
 65  
    * returns true if the supplied method can handle the invocation
 66  
    * of the candidate Method.
 67  
    *
 68  
    * @param candidate the method to inspect
 69  
    * @param method the proposed bridge method
 70  
    * @return
 71  
    *   true if the supplied method can handle the invocation
 72  
    *   of the candidate Method.
 73  
    */
 74  
   private static boolean isAssignable(final Method candidate, final Method method) {
 75  0
     if (!method.getName().equals(candidate.getName()))
 76  0
       return false;
 77  0
     if (method.getParameterTypes().length != candidate.getParameterTypes().length)
 78  0
       return false;
 79  0
     if (!isAssignable(method.getReturnType(), candidate.getReturnType()))
 80  0
       return false;
 81  0
     if (!isAssignable(method.getParameterTypes(), candidate.getParameterTypes()))
 82  0
       return false;
 83  
 
 84  0
     return true;
 85  
   }
 86  
 
 87  
   /**
 88  
    * Returns true if all the classes supplied as a's can be assigned
 89  
    * to the classes supplied as b's
 90  
    */
 91  
   private static boolean isAssignable(final Class< ? >[] as, final Class< ? >[] bs) {
 92  0
     if (as == null && bs == null)
 93  0
       return true;
 94  0
     if (as == null || bs == null)
 95  0
       return false;
 96  0
     if (as.length != bs.length)
 97  0
       return false;
 98  
 
 99  0
     for (int i = 0; i < as.length; i++) {
 100  0
       if (!isAssignable(as[i], bs[i]))
 101  0
         return false;
 102  
     }
 103  0
     return true;
 104  
   }
 105  
 
 106  
   /**
 107  
    * Returns true if all the class supplied as a can be assigned
 108  
    * from b
 109  
    */
 110  
   private static boolean isAssignable(final Class< ? > a, final Class< ? > b) {
 111  0
     if (a == null && b == null)
 112  0
       return true;
 113  0
     if (a == null || b == null)
 114  0
       return false;
 115  
 
 116  0
     return a.isAssignableFrom(b);
 117  
   }
 118  
 
 119  
 }