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 }