package main.utils; import java.awt.Component; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.LinkedList; import java.util.List; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JSpinner; import gui.utils.GUIErrorHandler; /** * Contains utility methods using reflection. * * @author Maxime PIA */ public class ReflectionUtils { /** * Finds the getters of a class. * * @param c * The class. * @return The getters of the class. */ public static List<Method> getGetters(Class<?> c) { Method[] allMethods = c.getDeclaredMethods(); List<Method> getters = new LinkedList<>(); for (Method m : allMethods) { if (((m.getReturnType().equals(boolean.class) && m.getName().startsWith("is")) || m.getName().startsWith("get")) && m.getParameterTypes().length == 0) { getters.add(m); } } return getters; } /** * Finds the setters of a class. * * @param c * The class. * @return The setters of the class. */ public static List<Method> getSetters(Class<?> c) { return getSetters(c, false); } private static List<Method> getSetters(Class<?> c, boolean flag) { Method[] allMethods = c.getDeclaredMethods(); List<Method> setters = new LinkedList<>(); for (Method m : allMethods) { Class<?>[] types = m.getParameterTypes(); if (m.getName().startsWith("set") && types.length == (flag ? 2 : 1)) { if ((flag && types[1].equals(boolean.class)) || !flag) { setters.add(m); } } } return setters; } private static Method getAccessor(Class<?> c, Field field, boolean setter, boolean flag) { String accessorSuffix; int modifiers = field.getModifiers(); if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) { accessorSuffix = StringUtils.screamingSnakeToWords(field.getName()); } else { accessorSuffix = StringUtils.camelToWords(field.getName()); } accessorSuffix = StringUtils.wordsToScreamingCamel(accessorSuffix); List<Method> accessors = setter ? getSetters(c, flag) : getGetters(c); for (Method accessor : accessors) { if (accessor.getName().endsWith(accessorSuffix)) { return accessor; } } return null; } /** * Finds the setter of a field. * * @param c * The class containing the field. * @param field * The field. * @return The setter of the field. */ public static Method getSetter(Class<?> c, Field field) { return getAccessor(c, field, true, false); } /** * Finds the getter of a field. * * @param c * The class containing the field. * @param field * The field. * @return The getter of the field. */ public static Method getGetter(Class<?> c, Field field) { return getAccessor(c, field, false, false); } /** * Finds the setter of a field containing flags. * * @param c * The class containing the field. * @param field * The field. * @return The setter of the field. */ public static Method getFlagSetter(Class<?> c, Field field) { return getAccessor(c, field, true, true); } /** * Finds the fields annotated by a given annotation. * * @param c * The class containing the fields. * @param annotationClass * The annotation. * @return The fields annotated by the annotation. */ public static List<Field> getAnnotatedFields(Class<?> c, Class<? extends Annotation> annotationClass) { Field[] fields = c.getDeclaredFields(); List<Field> annotatedFields = new LinkedList<>(); for (Field field : fields) { if (field.getAnnotation(annotationClass) != null) { annotatedFields.add(field); } } return annotatedFields; } /** * Finds the annotation objects of annotated fields. * * @param c * The class containing the fields. * @param annotationClass * The annotation. * @return The annotations of the annotated fields. */ public static <T extends Annotation> List<T> getAnnotations(Class<?> c, Class<T> annotationClass) { Field[] fields = c.getDeclaredFields(); List<T> annotations = new LinkedList<>(); for (Field field : fields) { T annotation = field.getAnnotation(annotationClass); if (annotation != null) { annotations.add(annotation); } } return annotations; } /** * Finds the fields with the given modifiers. * * @param c * The class containing the fields. * @param modifiers * The modifiers. * @return The fields with the given modifiers. */ public static List<Field> getModifiedFields(Class<?> c, int modifiers) { Field[] fields = c.getDeclaredFields(); List<Field> modifiedFields = new LinkedList<>(); for (Field field : fields) { if ((field.getModifiers() & modifiers) > 0) { modifiedFields.add(field); } } return modifiedFields; } private static Method getGUIComponentValueAccessor(Component elt, boolean setter) { String accessorPrefix = setter ? "set" : "get"; Class<?>[] args = new Class<?>[0]; try { if (elt instanceof JCheckBox) { if (setter) { args = new Class<?>[]{boolean.class}; } else { accessorPrefix = "is"; } return elt.getClass().getMethod( accessorPrefix + "Selected", args ); } else if (elt instanceof JComboBox || elt instanceof JSpinner) { if (setter) { args = new Class<?>[]{Object.class}; } String accessorSuffix = elt instanceof JComboBox ? "SelectedItem" : "Value"; return elt.getClass().getMethod( accessorPrefix + accessorSuffix, args ); } } catch (NoSuchMethodException | SecurityException e) { new GUIErrorHandler(e); } return null; } /** * Finds the getter on the value contained in a component. * * @param elt * The graphical component containing a value. * @return The getter on the value contained in the component. */ public static Method getGUIComponentValueGetter(Component elt) { return getGUIComponentValueAccessor(elt, false); } /** * Finds the setter on the value contained in a component. * * @param elt * The graphical component containing a value. * @return The setter on the value contained in the component. */ public static Method getGUIComponentValueSetter(Component elt) { return getGUIComponentValueAccessor(elt, true); } }