blob: cd6c2775812042cf53f6100b43f68c99f504c8f6 [file] [log] [blame]
/*
* Copyright 2003-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.groovy.runtime.typehandling;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.WeakHashMap;
/*
* 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.
*/
public class ClassDistance {
private static final WeakHashMap CLASS_DISTANCES;
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 {
CLASS_DISTANCES = 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};
CLASS_DISTANCES.put(Object.class,object);
LinearEntry number = new LinearEntry();
number.concat(new Class[]{Number.class,Serializable.class},object);
CLASS_DISTANCES.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);
CLASS_DISTANCES.put(BigInteger.class,object);
LinearEntry bdec = new LinearEntry();
binteger.concat(new Class[]{BigDecimal.class, BigInteger.class}, compareableNumber);
CLASS_DISTANCES.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};
CLASS_DISTANCES.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};
CLASS_DISTANCES.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};
CLASS_DISTANCES.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};
CLASS_DISTANCES.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};
CLASS_DISTANCES.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};
CLASS_DISTANCES.put(float.class,start);
// double:
start = new LinearEntry();
start.entries = new Class[]{
double.class,
Double.class, BigDecimal.class,
Number.class,Object.class};
CLASS_DISTANCES.put(double.class,start);
}
private static synchronized void popultate(Class clazz) {
if (CLASS_DISTANCES.get(clazz) != null) return;
}
}