View Javadoc

    1   /*
    2    * Class for calculating "distances" between classes. Such a distance
    3    * is not a real distance to something but should be seen as the order
    4    * classes and interfaces are choosen for method selection. The class
    5    * will keep a weak cache and recalculate the distances on demand.
    6    */
    7   package org.codehaus.groovy.runtime.typehandling;
    8
    9   import java.io.Serializable;
    10  import java.math.BigDecimal;
    11  import java.math.BigInteger;
    12  import java.util.WeakHashMap;
    13
    14  public class ClassDistance {
    15      private static WeakHashMap classDistances;
    16
    17      private static class Entry {
    18
    19      }
    20
    21      private static class LinearEntry  extends Entry{
    22          Class[] entries;
    23          void concat(Class[] c,LinearEntry le){
    24              entries = new Class[c.length+le.entries.length];
    25              System.arraycopy(c,0,entries,0,c.length);
    26              System.arraycopy(le.entries,0,entries,c.length,le.entries.length);
    27          }
    28          void concat(Class c,LinearEntry le){
    29              entries = new Class[1+le.entries.length];
    30              entries[0] = c;
    31              System.arraycopy(le.entries,0,entries,1,le.entries.length);
    32          }
    33      }
    34
    35      static {
    36          classDistances = new WeakHashMap();
    37          initialPopulate();
    38      }
    39
    40      private static void initialPopulate() {
    41          // int, double, byte, float, BigInteger, BigDecimal, long, short
    42          // GString, char
    43
    44
    45          LinearEntry object = new LinearEntry();
    46          object.entries = new Class[]{Object.class};
    47          classDistances.put(Object.class,object);
    48
    49          LinearEntry number = new LinearEntry();
    50          number.concat(new Class[]{Number.class,Serializable.class},object);
    51          classDistances.put(Number.class,number);
    52
    53          LinearEntry compareableNumber = new LinearEntry();
    54          compareableNumber.concat(Comparable.class,number);
    55
    56          LinearEntry binteger = new LinearEntry();
    57          binteger.concat(new Class[]{BigInteger.class, BigDecimal.class}, compareableNumber);
    58          classDistances.put(BigInteger.class,object);
    59
    60          LinearEntry bdec = new LinearEntry();
    61          binteger.concat(new Class[]{BigDecimal.class, BigInteger.class}, compareableNumber);
    62          classDistances.put(BigDecimal.class,object);
    63
    64
    65
    66          // byte:
    67          LinearEntry start = new LinearEntry();
    68          start.entries =  new Class[]{
    69                  byte.class, Byte.class, short.class, Short.class,
    70                  int.class, Integer.class, long.class, Long.class,
    71                  BigInteger.class,
    72                  float.class, Float.class,  double.class, Double.class,
    73                  BigDecimal.class,
    74                  Number.class,Object.class};
    75          classDistances.put(byte.class,start);
    76
    77          // short:
    78          start = new LinearEntry();
    79          start.entries =  new Class[]{
    80                  short.class, Short.class,
    81                  int.class, Integer.class, long.class, Long.class,
    82                  BigInteger.class,
    83                  float.class, Float.class,  double.class, Double.class,
    84                  BigDecimal.class,
    85                  Number.class,Object.class};
    86          classDistances.put(short.class,start);
    87
    88          // int:
    89          start = new LinearEntry();
    90          start.entries =  new Class[]{
    91                  int.class, Integer.class, long.class, Long.class,
    92                  BigInteger.class,
    93                  float.class, Float.class,  double.class, Double.class,
    94                  BigDecimal.class,
    95                  Number.class,Object.class};
    96          classDistances.put(int.class,start);
    97
    98          // long:
    99          start = new LinearEntry();
    100         start.entries =  new Class[]{
    101                 long.class, Long.class,
    102                 BigInteger.class,
    103                 float.class, Float.class,  double.class, Double.class,
    104                 BigDecimal.class,
    105                 Number.class,Object.class};
    106         classDistances.put(long.class,start);
    107
    108         // Biginteger:
    109         start = new LinearEntry();
    110         start.entries =  new Class[]{
    111                 BigInteger.class,
    112                 float.class, Float.class,  double.class, Double.class,
    113                 BigDecimal.class,
    114                 Number.class,Object.class};
    115         classDistances.put(long.class,start);
    116
    117         // float:
    118         start = new LinearEntry();
    119         start.entries =  new Class[]{
    120                 byte.class, Byte.class, short.class, Short.class,
    121                 int.class, Integer.class, long.class, Long.class,
    122                 BigInteger.class,
    123                 float.class, Float.class,  double.class, Double.class,
    124                 BigDecimal.class,
    125                 Number.class,Object.class};
    126         classDistances.put(float.class,start);
    127
    128         // double:
    129         start = new LinearEntry();
    130         start.entries =  new Class[]{
    131                 double.class,
    132                 Double.class, BigDecimal.class,
    133                 Number.class,Object.class};
    134         classDistances.put(double.class,start);
    135
    136     }
    137
    138     private synchronized static void popultate(Class clazz) {
    139         if (classDistances.get(clazz) != null) return;
    140
    141     }
    142
    143 }