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 }