Clover coverage report - JBind Project
Coverage timestamp: Fr Mai 28 2004 11:17:36 CEST
file stats: LOC: 252   Methods: 6
NCLOC: 158   Classes: 1
This license of Clover is provided to support the development of JBind only. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover.
 
 Source file Conditionals Statements Methods TOTAL
ReflectUtil.java 13,9% 15,7% 33,3% 15,6%
 1   
 /*
 2   
  * JBind
 3   
  *
 4   
  * Copyright (c) by Stefan Wachter. All rights reserved.
 5   
  *
 6   
  * Usage, modification, and redistribution is subject to license terms that are
 7   
  * available at 'http://www.jbind.org'. The JBind license is like the
 8   
  * 'Apache Software License V 1.1'.
 9   
  */
 10   
 package org.jbind.util.reflect;
 11   
 
 12   
 import java.lang.reflect.Constructor;
 13   
 import java.lang.reflect.Method;
 14   
 import java.util.ArrayList;
 15   
 import java.util.Collection;
 16   
 import java.util.Iterator;
 17   
 import java.util.List;
 18   
 import java.util.Map;
 19   
 
 20   
 /**
 21   
  * Static utility methods for the generator.
 22   
  */
 23   
 public class ReflectUtil {
 24   
 
 25  0
   private ReflectUtil() {}
 26   
 
 27   
   /**
 28   
    * Returns the type name of the specified class. Arrays and inner classes are
 29   
    * supported.
 30   
    *
 31   
    * @param The class whose type name is needed. <i>(required)</i>
 32   
    * @return The type name of the specified class. <i>(required)</i>
 33   
    */
 34  1627
   public static String getTypeName(Class aClass) {
 35  1627
     String typeName = null;
 36  1627
     if (aClass.isArray()) {
 37  0
       Class componentType = aClass.getComponentType();
 38  0
       typeName = getTypeName(componentType) + "[]";
 39   
     } else {
 40   
       // Reflection returns class names in which the inner parts of names are
 41   
       // separated by '$'. These must be replaced by '.'.
 42  1627
       StringBuffer sb = new StringBuffer(aClass.getName());
 43  1627
       for (int i = 0; i < sb.length(); i++) {
 44  26492
         if (sb.charAt(i) == '$') {
 45  24
           sb.setCharAt(i, '.');
 46   
         }
 47   
       }
 48  1627
       typeName = sb.toString();
 49   
     }
 50  1627
     return typeName;
 51   
   }
 52   
 
 53   
   /**
 54   
    * Removes all classes from the specified collection that have a (real) super class
 55   
    * in the collection.
 56   
    *
 57   
    * @param aClasses The classes that are considered. <i>(required)</i>
 58   
    * @return A list of the classes that have no (real) super classes in the
 59   
    * specified collection. <i>(required)</i>
 60   
    */
 61  0
   public static List removeSubClasses(Collection aClasses) {
 62  0
     List res = new ArrayList();
 63  0
     for (Iterator i = aClasses.iterator(); i.hasNext(); ) {
 64  0
       Class candidate = (Class)i.next();
 65  0
       boolean include = true;
 66  0
       for (Iterator j = aClasses.iterator(); j.hasNext(); ) {
 67  0
         Class c = (Class)j.next();
 68  0
         if (candidate == c) {
 69  0
           continue;
 70   
         }
 71  0
         if (c.isAssignableFrom(candidate)) {
 72  0
           include = false;
 73  0
           break;
 74   
         }
 75   
       }
 76  0
       if (include) {
 77  0
         res.add(candidate);
 78   
       }
 79   
     }
 80  0
     return res;
 81   
   }
 82   
 
 83   
   /**
 84   
    * Sorts the classes according to their subclass relationship. Super classes are
 85   
    * guaranteed to be in the list before their sub classes.
 86   
    *
 87   
    * @param aClasses The classes to sort. <i>(required)</i>
 88   
    * @return The sorted classes. <i>(required)</i>
 89   
    */
 90  0
   public static List sortClasses(Collection aClasses) {
 91  0
     List res = new ArrayList();
 92   
 
 93  0
     int nbClasses = aClasses.size();
 94   
 
 95  0
     for (int i = 0; i < nbClasses; i++) {
 96  0
       for (Iterator j = aClasses.iterator(); j.hasNext(); ) {
 97  0
         Class candidate = (Class)j.next();
 98  0
         boolean isTop = true;
 99   
 
 100  0
         for (Iterator k = aClasses.iterator(); k.hasNext(); ) {
 101  0
           Class c = (Class)k.next();
 102  0
           if ((c != candidate) && c.isAssignableFrom(candidate)) {
 103   
             // c is a super class of the candidate
 104  0
             isTop = false;
 105  0
             break;
 106   
           }
 107   
         }
 108   
 
 109  0
         if (isTop) {
 110  0
           res.add(candidate);
 111  0
           j.remove();
 112  0
           break;
 113   
         }
 114   
 
 115   
       }
 116   
 
 117   
     }
 118   
 
 119  0
     return res;
 120   
 
 121   
   }
 122   
 
 123  24
   public static final Class getWrapperClass(Class aClass) {
 124  24
     Class res = null;
 125  24
     if (aClass.isPrimitive()) {
 126  1
       String name = aClass.getName();
 127  1
       if (name.equals("byte")) {
 128  0
         res = Byte.class;
 129  1
       } else if (name.equals("short")) {
 130  0
         res = Short.class;
 131  1
       } else if (name.equals("int")) {
 132  1
         res = Integer.class;
 133  0
       } else if (name.equals("long")) {
 134  0
         res = Long.class;
 135  0
       } else if (name.equals("float")) {
 136  0
         res = Float.class;
 137  0
       } else if (name.equals("double")) {
 138  0
         res = Double.class;
 139  0
       } else if (name.equals("boolean")) {
 140  0
         res = Boolean.class;
 141  0
       } else if (name.equals("char")) {
 142  0
         res = Character.class;
 143   
       }
 144   
       assert null != res;
 145   
     } else {
 146  23
       res = aClass;
 147   
     }
 148  24
     return res;
 149   
   }
 150   
 
 151   
   /**
 152   
    * Tries to set the members of an object by their setter-methods if there is
 153   
    * a corresponding value in the map.
 154   
    * <p>
 155   
    * The method proceeds by iterating over all methods of the object selecting
 156   
    * those whose method names have the prefix "set". The member name is derived as the
 157   
    * remaining part of the method name (possibly an upper and lower case first
 158   
    * letter). For each such method it is tested the map contains a value
 159   
    * for the corresponding member name and if the method needs a single parameter
 160   
    * to set the member. If both conditions are true, it is tested if the value
 161   
    * in the map is assignment compatible with the parameter class of the
 162   
    * setter method. If this is not the case than it is tried to construct a
 163   
    * suitable parameter object from the value. Finally the setter method is called.
 164   
    *
 165   
    * @param anObject <i>(required)</i>.
 166   
    * @param aMap <i>(required)</i>. The values that are set are removed from
 167   
    * the map. Therefore the success of the method may be checked by testing
 168   
    * the map for emptiness.
 169   
    */
 170  0
   public static void setMembers(Object anObject, Map aMap) throws Exception {
 171  0
     Method[] ma = anObject.getClass().getMethods();
 172   
 
 173  0
     for (int i = 0; i < ma.length; i++) {
 174  0
       Method m = ma[i];
 175  0
       String methodName = m.getName();
 176   
 
 177   
       // check if the method is a setter
 178  0
       if (!methodName.startsWith("set")) {
 179  0
         continue;
 180   
       }
 181   
 
 182   
       // Calculate the attributeName and try to get its value from the hashtable.
 183   
       // Consider the first letter being upper or lower case.
 184  0
       String attributeName;
 185  0
       StringBuffer sb = new StringBuffer();
 186  0
       sb.append(methodName.substring(3));
 187  0
       attributeName = sb.toString();
 188  0
       Object value = aMap.get(attributeName);
 189  0
       if (null == value) {
 190  0
         sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
 191  0
         attributeName = sb.toString();
 192  0
         value = aMap.get(attributeName);
 193   
       }
 194  0
       if (null == value) {
 195  0
         continue;
 196   
       }
 197   
 
 198   
       // check if the setter has exactly one parameter
 199  0
       Class[] pa = m.getParameterTypes();
 200  0
       if ((pa.length == 0) || (pa.length > 1)) {
 201  0
         continue;
 202   
       }
 203   
 
 204   
       // check if the parameter of the setter is assignment compatible
 205  0
       Class originalParameterClass = pa[0];
 206  0
       Class parameterClass = null;
 207  0
       if (originalParameterClass.isPrimitive()) {
 208   
         // if the method needs a primitive type find the corresponding wrapper class
 209  0
         String primitiveName = originalParameterClass.getName();
 210  0
         if (primitiveName.equals("byte")) {
 211  0
           parameterClass = Byte.class;
 212  0
         } else if (primitiveName.equals("short")) {
 213  0
           parameterClass = Short.class;
 214  0
         } else if (primitiveName.equals("int")) {
 215  0
           parameterClass = Integer.class;
 216  0
         } else if (primitiveName.equals("long")) {
 217  0
           parameterClass = Long.class;
 218  0
         } else if (primitiveName.equals("float")) {
 219  0
           parameterClass = Float.class;
 220  0
         } else if (primitiveName.equals("double")) {
 221  0
           parameterClass = Double.class;
 222  0
         } else if (primitiveName.equals("boolean")) {
 223  0
           parameterClass = Boolean.class;
 224   
         } else {
 225  0
           parameterClass = Character.class;
 226   
         }
 227   
       } else {
 228  0
         parameterClass = originalParameterClass;
 229   
       }
 230   
 
 231   
       // Determine the object which should be used in the setter method.
 232   
 
 233  0
       Object useObject = null;
 234  0
       if (parameterClass.isInstance(value)) {
 235   
         // The value from the hashtable can be used.
 236  0
         useObject = value;
 237   
       } else {
 238   
         // Try to convert the value from the hashtable into the parameterClass
 239  0
         Constructor constructor = parameterClass.getConstructor(new Class[]{ value.getClass() });
 240  0
         useObject = constructor.newInstance(new Object[]{ value });
 241   
       }
 242   
 
 243  0
       m.invoke(anObject, new Object[]{ useObject });
 244   
       // Remove the attribute from the value hashtable because finally
 245   
       // it will be checked if all attribute have been set.
 246  0
       aMap.remove(attributeName);
 247   
 
 248   
     }
 249   
 
 250   
   }
 251   
 }
 252