package com.psddev.cms.view; import com.psddev.dari.db.ObjectType; import com.psddev.dari.db.Recordable; import com.psddev.dari.util.ObjectUtils; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; final class ViewUtils { private ViewUtils() { } // Returns classes in order of input class followed by all interfaces and // super interfaces, followed by its super classes and their interfaces // and super interfaces, followed by its modification classes. static List<Class<?>> getAnnotatableClasses(Class<?> klass) { Set<Class<?>> classesToCheck = new LinkedHashSet<>(); // add class and interfaces classesToCheck.add(klass); classesToCheck.addAll(getAllInterfaces(klass)); // repeat for each super class Class<?> superClass = klass.getSuperclass(); while (superClass != null) { if (!Object.class.equals(superClass)) { classesToCheck.add(superClass); classesToCheck.addAll(getAllInterfaces(superClass)); } superClass = superClass.getSuperclass(); } // check modification classes if (Recordable.class.isAssignableFrom(klass)) { ObjectType type = ObjectType.getInstance(klass); if (type != null) { for (String modClassName : type.getModificationClassNames()) { Class<?> modClass = ObjectUtils.getClassByName(modClassName); if (modClass != null) { classesToCheck.add(modClass); } } } } return new ArrayList<>(classesToCheck); } // returns the classes nearest to the provided {@code sourceClass} based on // the number of levels up in the class hierarchy tree. static Set<Class<?>> getNearestSuperClassesInSet(Class<?> sourceClass, Set<Class<?>> superTypes) { Set<Class<?>> superClasses = new HashSet<>(); Set<Class<?>> interfaces = new HashSet<>(); superTypes.forEach((superType) -> { if (superType.isAssignableFrom(sourceClass)) { if (superType.isInterface()) { interfaces.add(superType); } else { superClasses.add(superType); } } }); if (!superClasses.isEmpty()) { Class<?> superClass = sourceClass; while (superClass != null) { if (superClasses.contains(superClass)) { return Collections.singleton(superClass); } else { superClass = superClass.getSuperclass(); } } return Collections.emptySet(); } else { // TODO: Still need to determine how we will handle interfaces. return interfaces; } } // fetches the interfaces for the given class including including any super // interfaces. private static Set<Class<?>> getAllInterfaces(Class<?> klass) { Set<Class<?>> interfaces = new HashSet<>(); for (Class<?> interfaceClass : klass.getInterfaces()) { interfaces.add(interfaceClass); interfaces.addAll(getAllInterfaces(interfaceClass)); } return interfaces; } }