package org.simpleflatmapper.reflect.instantiator; import org.simpleflatmapper.reflect.InstantiatorDefinition; import org.simpleflatmapper.reflect.TypeAffinity; import org.simpleflatmapper.util.TypeHelper; import java.util.Collection; import java.util.Comparator; public class InstantiatorDefinitions { public static final Comparator<InstantiatorDefinition> COMPARATOR = new Comparator<InstantiatorDefinition>() { @Override public int compare(InstantiatorDefinition o1, InstantiatorDefinition o2) { InstantiatorDefinition.Type t1 = o1.getType(); InstantiatorDefinition.Type t2 = o2.getType(); int d = t1.ordinal() - t2.ordinal(); if (d != 0) return d; if (isValueOf(o1)) { if (!isValueOf(o2)) { return -1; } } else if (isValueOf(o2)) { return 1; } final int p = o1.getParameters().length - o2.getParameters().length; if (p == 0) { return o1.getName().compareTo(o2.getName()); } return p; } }; private static boolean isValueOf(InstantiatorDefinition d) { if (d.getType() != InstantiatorDefinition.Type.METHOD) return false; String name = d.getName(); return name.equals("valueOf") || name.equals("of") || name.equals("newInstance"); } public static InstantiatorDefinition lookForCompatibleOneArgument(Collection<InstantiatorDefinition> col, CompatibilityScorer scorer) { InstantiatorDefinition current = null; int currentScore = -1; for(InstantiatorDefinition id : col ) { if (id.getParameters().length == 1) { int score = scorer.score(id); if (score > currentScore) { current = id; currentScore = score; } } } return current; } public static InstantiatorDefinitions.CompatibilityScorer getCompatibilityScorer(Object key) { if (key instanceof TypeAffinity) { TypeAffinity ta = (TypeAffinity) key; Class<?>[] affinities = ta.getAffinities(); if (affinities != null && affinities.length > 0) { return new TypeAffinityCompatibilityScorer(affinities); } } return new DefaultCompatibilityScorer(); } private static class DefaultCompatibilityScorer implements InstantiatorDefinitions.CompatibilityScorer { @Override public int score(InstantiatorDefinition id) { Package aPackage = id.getParameters()[0].getType().getPackage(); if (aPackage != null && aPackage.getName().equals("java.lang")) { return 1; } return 0; } } private static class TypeAffinityCompatibilityScorer implements InstantiatorDefinitions.CompatibilityScorer { private final Class<?>[] classes; private TypeAffinityCompatibilityScorer(Class<?>[] classes) { this.classes = classes; } @Override public int score(InstantiatorDefinition id) { Class<?> paramType = TypeHelper.toBoxedClass(id.getParameters()[0].getType()); for(int i = 0; i < classes.length; i++) { Class<?> c = classes[i]; if (c.isAssignableFrom(paramType)) { return classes.length - i + 10; } } Package aPackage = paramType.getPackage(); if (aPackage != null && aPackage.getName().equals("java.lang")) { return 1; } return 0; } } public interface CompatibilityScorer { int score(InstantiatorDefinition id); } }