package xapi.dev.scanner.impl; import java.util.ArrayList; import java.util.List; import xapi.bytecode.ClassFile; import xapi.collect.api.PrefixedMap; import xapi.dev.resource.impl.ByteCodeResource; import xapi.log.X_Log; import xapi.util.api.MatchesValue; public class MatchesImplementationsOf implements MatchesValue<ClassFile> { private final PrefixedMap<ByteCodeResource> bytecode; private final List<String> interfaces, classes; public MatchesImplementationsOf(PrefixedMap<ByteCodeResource> bytecode, String ... subclasses) { this.bytecode = bytecode; interfaces = new ArrayList<String>(); classes = new ArrayList<String>(); for (String subclass : subclasses) { ByteCodeResource resource = bytecode.get(subclass); if (resource == null) { X_Log.warn(getClass(), "Searching for implementations of",subclass,"that are not on search classpath"); interfaces.add(subclass); classes.add(subclass); } else { ClassFile cls = bytecode.get(subclass).getClassData(); (cls.isInterface() ? interfaces : classes).add(subclass); } } } @Override public boolean matches(ClassFile value) { for (String iface : value.getInterfaces()) { for (String subclass : interfaces) { if (iface.equals(subclass)) { return true; } } } if (!value.isInterface()) { for (String superclass : getHierarchy(value)) { for (String subclass : classes) { if (superclass.equals(subclass)) { return true; } } } } return false; } private Iterable<String> getHierarchy(ClassFile value) { List<String> hierarchy = new ArrayList<String>(); addSuperclasses(hierarchy, value.getSuperclass(), value); return hierarchy; } private void addSuperclasses(List<String> hierarchy, String superclass, ClassFile clazz) { if (superclass != null) { hierarchy.add(superclass); if (superclass.equals("java.lang.Object")) { return; } ByteCodeResource resource = bytecode.get(superclass); if (resource == null) { X_Log.trace(getClass(), "Unable to find superclass",superclass,"of",clazz,"on classpath; supertype search will end"); } else { ClassFile cls = resource.getClassData(); addSuperclasses(hierarchy, cls.getSuperclass(), cls); } } } }