package openperipheral.adapter.types.classifier; import com.google.common.collect.Lists; import com.google.common.reflect.TypeToken; import java.lang.reflect.Type; import java.util.List; import openperipheral.api.adapter.IScriptType; import openperipheral.api.adapter.ITypeClassifier; public class TypeClassifier implements ITypeClassifier { private static class ClassQualifierAdapter implements IGenericClassifier { private final IClassClassifier wrapped; public ClassQualifierAdapter(IClassClassifier wrapped) { this.wrapped = wrapped; } @Override public IScriptType classify(ITypeClassifier classifier, Type type) { final TypeToken<?> token = TypeToken.of(type); return wrapped.classify(classifier, token.getRawType()); } } public static final TypeClassifier INSTANCE = new TypeClassifier(); private final List<IGenericClassifier> classifiers = Lists.newArrayList(); public TypeClassifier() { registerDefaultClassifiers(); } protected void registerDefaultClassifiers() { registerClassifier(new DefaultTypeClassifier()); } @Override public void registerClassifier(IGenericClassifier classifier) { classifiers.add(classifier); } @Override public void registerClassifier(IClassClassifier classifier) { classifiers.add(new ClassQualifierAdapter(classifier)); } @Override public void registerType(final Class<?> cls, final IScriptType type) { final TypeToken<?> match = TypeToken.of(cls); classifiers.add(new IGenericClassifier() { @Override public IScriptType classify(ITypeClassifier classifier, Type t) { return (match.isAssignableFrom(t))? type : null; } }); } @Override public IScriptType classifyType(Type type) { for (IGenericClassifier c : classifiers) { IScriptType result = c.classify(this, type); if (result != null) return result; } throw new IllegalArgumentException(String.format("Can't classify type '%s'", type)); } }