001    /*
002     * Class for calculating "distances" between classes. Such a distance
003     * is not a real distance to something but should be seen as the order
004     * classes and interfaces are choosen for method selection. The class
005     * will keep a weak cache and recalculate the distances on demand. 
006     */
007    package org.codehaus.groovy.runtime.typehandling;
008    
009    import java.io.Serializable;
010    import java.math.BigDecimal;
011    import java.math.BigInteger;
012    import java.util.WeakHashMap;
013    
014    public class ClassDistance {
015        private static WeakHashMap classDistances;
016        
017        private static class Entry {
018            
019        }
020        
021        private static class LinearEntry  extends Entry{
022            Class[] entries;
023            void concat(Class[] c,LinearEntry le){
024                entries = new Class[c.length+le.entries.length];
025                System.arraycopy(c,0,entries,0,c.length);
026                System.arraycopy(le.entries,0,entries,c.length,le.entries.length);
027            }
028            void concat(Class c,LinearEntry le){
029                entries = new Class[1+le.entries.length];
030                entries[0] = c;
031                System.arraycopy(le.entries,0,entries,1,le.entries.length);
032            }
033        }
034        
035        static {
036            classDistances = new WeakHashMap();
037            initialPopulate();
038        }
039        
040        private static void initialPopulate() {
041            // int, double, byte, float, BigInteger, BigDecimal, long, short
042            // GString, char
043            
044            
045            LinearEntry object = new LinearEntry();
046            object.entries = new Class[]{Object.class};
047            classDistances.put(Object.class,object);
048            
049            LinearEntry number = new LinearEntry();
050            number.concat(new Class[]{Number.class,Serializable.class},object);
051            classDistances.put(Number.class,number);
052    
053            LinearEntry compareableNumber = new LinearEntry();
054            compareableNumber.concat(Comparable.class,number);
055            
056            LinearEntry binteger = new LinearEntry();
057            binteger.concat(new Class[]{BigInteger.class, BigDecimal.class}, compareableNumber);
058            classDistances.put(BigInteger.class,object);
059            
060            LinearEntry bdec = new LinearEntry();
061            binteger.concat(new Class[]{BigDecimal.class, BigInteger.class}, compareableNumber);
062            classDistances.put(BigDecimal.class,object);
063            
064            
065            
066            // byte:
067            LinearEntry start = new LinearEntry();
068            start.entries =  new Class[]{
069                    byte.class, Byte.class, short.class, Short.class,
070                    int.class, Integer.class, long.class, Long.class,
071                    BigInteger.class,
072                    float.class, Float.class,  double.class, Double.class, 
073                    BigDecimal.class,
074                    Number.class,Object.class};
075            classDistances.put(byte.class,start);
076            
077            // short:
078            start = new LinearEntry();
079            start.entries =  new Class[]{
080                    short.class, Short.class,
081                    int.class, Integer.class, long.class, Long.class,
082                    BigInteger.class,
083                    float.class, Float.class,  double.class, Double.class, 
084                    BigDecimal.class,
085                    Number.class,Object.class};
086            classDistances.put(short.class,start);
087            
088            // int:
089            start = new LinearEntry();
090            start.entries =  new Class[]{
091                    int.class, Integer.class, long.class, Long.class,
092                    BigInteger.class,
093                    float.class, Float.class,  double.class, Double.class, 
094                    BigDecimal.class,
095                    Number.class,Object.class};
096            classDistances.put(int.class,start);
097            
098            // long:
099            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    }