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 }