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:
024: void concat(Class[] c, LinearEntry le) {
025: entries = new Class[c.length + le.entries.length];
026: System.arraycopy(c, 0, entries, 0, c.length);
027: System.arraycopy(le.entries, 0, entries, c.length,
028: le.entries.length);
029: }
030:
031: void concat(Class c, LinearEntry le) {
032: entries = new Class[1 + le.entries.length];
033: entries[0] = c;
034: System.arraycopy(le.entries, 0, entries, 1,
035: le.entries.length);
036: }
037: }
038:
039: static {
040: classDistances = new WeakHashMap();
041: initialPopulate();
042: }
043:
044: private static void initialPopulate() {
045: // int, double, byte, float, BigInteger, BigDecimal, long, short
046: // GString, char
047:
048: LinearEntry object = new LinearEntry();
049: object.entries = new Class[] { Object.class };
050: classDistances.put(Object.class, object);
051:
052: LinearEntry number = new LinearEntry();
053: number.concat(new Class[] { Number.class, Serializable.class },
054: object);
055: classDistances.put(Number.class, number);
056:
057: LinearEntry compareableNumber = new LinearEntry();
058: compareableNumber.concat(Comparable.class, number);
059:
060: LinearEntry binteger = new LinearEntry();
061: binteger.concat(new Class[] { BigInteger.class,
062: BigDecimal.class }, compareableNumber);
063: classDistances.put(BigInteger.class, object);
064:
065: LinearEntry bdec = new LinearEntry();
066: binteger.concat(new Class[] { BigDecimal.class,
067: BigInteger.class }, compareableNumber);
068: classDistances.put(BigDecimal.class, object);
069:
070: // byte:
071: LinearEntry start = new LinearEntry();
072: start.entries = new Class[] { byte.class, Byte.class,
073: short.class, Short.class, int.class, Integer.class,
074: long.class, Long.class, BigInteger.class, float.class,
075: Float.class, double.class, Double.class,
076: BigDecimal.class, Number.class, Object.class };
077: classDistances.put(byte.class, start);
078:
079: // short:
080: start = new LinearEntry();
081: start.entries = new Class[] { short.class, Short.class,
082: int.class, Integer.class, long.class, Long.class,
083: BigInteger.class, float.class, Float.class,
084: double.class, Double.class, 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[] { int.class, Integer.class,
091: long.class, Long.class, BigInteger.class, float.class,
092: Float.class, double.class, Double.class,
093: BigDecimal.class, Number.class, Object.class };
094: classDistances.put(int.class, start);
095:
096: // long:
097: start = new LinearEntry();
098: start.entries = new Class[] { long.class, Long.class,
099: BigInteger.class, float.class, Float.class,
100: double.class, Double.class, BigDecimal.class,
101: Number.class, Object.class };
102: classDistances.put(long.class, start);
103:
104: // Biginteger:
105: start = new LinearEntry();
106: start.entries = new Class[] { BigInteger.class, float.class,
107: Float.class, double.class, Double.class,
108: BigDecimal.class, Number.class, Object.class };
109: classDistances.put(long.class, start);
110:
111: // float:
112: start = new LinearEntry();
113: start.entries = new Class[] { byte.class, Byte.class,
114: short.class, Short.class, int.class, Integer.class,
115: long.class, Long.class, BigInteger.class, float.class,
116: Float.class, double.class, Double.class,
117: BigDecimal.class, Number.class, Object.class };
118: classDistances.put(float.class, start);
119:
120: // double:
121: start = new LinearEntry();
122: start.entries = new Class[] { double.class, Double.class,
123: BigDecimal.class, Number.class, Object.class };
124: classDistances.put(double.class, start);
125:
126: }
127:
128: private synchronized static void popultate(Class clazz) {
129: if (classDistances.get(clazz) != null)
130: return;
131:
132: }
133:
134: }
|