blob: da630581ac8b441d81a62eb44931ced19b7d3a0b [file] [log] [blame]
/*
* Class for calculating "distances" between classes. Such a distance
* is not a real distance to something but should be seen as the order
* classes and interfaces are choosen for method selection. The class
* will keep a weak cache and recalculate the distances on demand.
*/
package org.codehaus.groovy.runtime.typehandling;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.WeakHashMap;
public class ClassDistance {
private static WeakHashMap classDistances;
private static class Entry {
}
private static class LinearEntry extends Entry{
Class[] entries;
void concat(Class[] c,LinearEntry le){
entries = new Class[c.length+le.entries.length];
System.arraycopy(c,0,entries,0,c.length);
System.arraycopy(le.entries,0,entries,c.length,le.entries.length);
}
void concat(Class c,LinearEntry le){
entries = new Class[1+le.entries.length];
entries[0] = c;
System.arraycopy(le.entries,0,entries,1,le.entries.length);
}
}
static {
classDistances = new WeakHashMap();
initialPopulate();
}
private static void initialPopulate() {
// int, double, byte, float, BigInteger, BigDecimal, long, short
// GString, char
LinearEntry object = new LinearEntry();
object.entries = new Class[]{Object.class};
classDistances.put(Object.class,object);
LinearEntry number = new LinearEntry();
number.concat(new Class[]{Number.class,Serializable.class},object);
classDistances.put(Number.class,number);
LinearEntry compareableNumber = new LinearEntry();
compareableNumber.concat(Comparable.class,number);
LinearEntry binteger = new LinearEntry();
binteger.concat(new Class[]{BigInteger.class, BigDecimal.class}, compareableNumber);
classDistances.put(BigInteger.class,object);
LinearEntry bdec = new LinearEntry();
binteger.concat(new Class[]{BigDecimal.class, BigInteger.class}, compareableNumber);
classDistances.put(BigDecimal.class,object);
// byte:
LinearEntry start = new LinearEntry();
start.entries = new Class[]{
byte.class, Byte.class, short.class, Short.class,
int.class, Integer.class, long.class, Long.class,
BigInteger.class,
float.class, Float.class, double.class, Double.class,
BigDecimal.class,
Number.class,Object.class};
classDistances.put(byte.class,start);
// short:
start = new LinearEntry();
start.entries = new Class[]{
short.class, Short.class,
int.class, Integer.class, long.class, Long.class,
BigInteger.class,
float.class, Float.class, double.class, Double.class,
BigDecimal.class,
Number.class,Object.class};
classDistances.put(short.class,start);
// int:
start = new LinearEntry();
start.entries = new Class[]{
int.class, Integer.class, long.class, Long.class,
BigInteger.class,
float.class, Float.class, double.class, Double.class,
BigDecimal.class,
Number.class,Object.class};
classDistances.put(int.class,start);
// long:
start = new LinearEntry();
start.entries = new Class[]{
long.class, Long.class,
BigInteger.class,
float.class, Float.class, double.class, Double.class,
BigDecimal.class,
Number.class,Object.class};
classDistances.put(long.class,start);
// Biginteger:
start = new LinearEntry();
start.entries = new Class[]{
BigInteger.class,
float.class, Float.class, double.class, Double.class,
BigDecimal.class,
Number.class,Object.class};
classDistances.put(long.class,start);
// float:
start = new LinearEntry();
start.entries = new Class[]{
byte.class, Byte.class, short.class, Short.class,
int.class, Integer.class, long.class, Long.class,
BigInteger.class,
float.class, Float.class, double.class, Double.class,
BigDecimal.class,
Number.class,Object.class};
classDistances.put(float.class,start);
// double:
start = new LinearEntry();
start.entries = new Class[]{
double.class,
Double.class, BigDecimal.class,
Number.class,Object.class};
classDistances.put(double.class,start);
}
private synchronized static void popultate(Class clazz) {
if (classDistances.get(clazz) != null) return;
}
}