package org.testory.proxy; import static java.util.Arrays.asList; import static org.testory.common.Collections.immutable; import static org.testory.proxy.ProxyException.check; import java.util.HashSet; import java.util.Set; /** * Runtime (after erasure) type signature of concrete/abstract class. <br> * For example:<br> * public final class Integer <b>extends Number implements Comparable</b> */ public class Typing { public final Class<?> superclass; public final Set<Class<?>> interfaces; private Typing(Class<?> superclass, Set<Class<?>> interfaces) { this.superclass = superclass; this.interfaces = interfaces; } public static Typing typing(Class<?> superclass, Set<? extends Class<?>> interfaces) { check(superclass != null); check(interfaces != null); check(!superclass.isInterface()); check(!superclass.isPrimitive()); check(!superclass.isArray()); Set<Class<?>> interfacesCopy = immutable(interfaces); for (Class<?> interfacee : interfacesCopy) { check(interfacee.isInterface() && !interfacee.isAnnotation()); } return new Typing(superclass, interfacesCopy); } public static Typing extending(Class<?> type) { return typing(type, new HashSet<Class<?>>()); } public static Typing implementing(Class<?>... type) { return typing(Object.class, new HashSet<Class<?>>(asList(type))); } public static Typing subclassing(Class<?> type) { return type.isInterface() ? implementing(type) : extending(type); } public boolean equals(Object object) { return this == object || object instanceof Typing && equalsTyping((Typing) object); } private boolean equalsTyping(Typing typing) { return superclass == typing.superclass && interfaces.equals(typing.interfaces); } public int hashCode() { return ((0xFFFF + superclass.hashCode()) * 0xFFFF + interfaces.hashCode()) * 0xFFFF; } public String toString() { return "typing(" + superclass + ", " + interfaces + ")"; } }