001    package net.sourceforge.javajson.converter;
002    
003    import java.lang.reflect.InvocationTargetException;
004    import java.lang.reflect.Method;
005    import java.util.HashMap;
006    import java.util.LinkedList;
007    import java.util.List;
008    import java.util.Map;
009    import java.util.regex.Matcher;
010    import java.util.regex.Pattern;
011    
012    /**
013     * A set of utility functions for reflection related things used in this json
014     * package
015     */
016    public class Reflection {
017    
018            private static Pattern setterPattern = Pattern.compile("^set[A-Z].*");
019    
020            private static Pattern getterPattern = Pattern.compile("^(is|get)[A-Z].*");
021    
022            public static List<Method> getSetterFieldMethods(Class cls) {
023                    List<Method> methods = new LinkedList<Method>();
024    
025                    Method[] a = cls.getMethods();
026                    for (int i = 0; i < a.length; i++) {
027    
028                            if (a[i].getParameterTypes().length == 1
029                                            && isSetterMethod(a[i].getName())) {
030                                    // TODO: make sure method isn't static or protected/private
031                                    methods.add(a[i]);
032                            }
033                    }
034    
035                    return methods;
036            }
037    
038            /**
039             * Returns the public getter methods that are normal getters, this includes
040             * getX and isX methods as long as the isX methods return a boolean.
041             * 
042             * @param cls
043             * @return
044             */
045            static List<Method> getGetterFieldMethods(Class cls) {
046                    List<Method> methods = new LinkedList<Method>();
047    
048                    Method[] a = cls.getMethods();
049                    for (int i = 0; i < a.length; i++) {
050    
051                            if (a[i].getParameterTypes().length == 0
052                                            && isGetterMethod(a[i].getName())) {
053                                    // TODO: check that 'is' methods are boolean
054                                    // TODO: make sure method isn't static or protected/private
055                                    methods.add(a[i]);
056                            }
057                    }
058    
059                    return methods;
060            }
061    
062            static Map<String, Object> getFields(Object o)
063                            throws IllegalArgumentException, IllegalAccessException,
064                            InvocationTargetException {
065                    List<Method> methods = getGetterFieldMethods(o.getClass());
066                    Map<String, Object> ret = new HashMap<String, Object>();
067    
068                    Object[] ARGS = new Object[0];
069                    for (Method m : methods) {
070                            String name = m.getName();
071                            Object value = m.invoke(o, ARGS);
072                            ret.put(name, value);
073                    }
074    
075                    return ret;
076            }
077    
078            /**
079             * Converts a methodname into a field name. Return null if its not a
080             * proper/normal method name that starts with get/set/is.
081             * 
082             * @param methodName
083             * @return
084             */
085            static String getFieldName(String methodName) {
086                    int l = methodName.length();
087                    if (l >= 2 && Character.isUpperCase(methodName.charAt(2))) {
088                            if (methodName.startsWith("is")) {
089                                    return Character.toLowerCase(methodName.charAt(2))
090                                                    + methodName.substring(3);
091                            }
092                    }
093                    if (l >= 3 && Character.isUpperCase(methodName.charAt(3))) {
094                            if (methodName.startsWith("get") || methodName.startsWith("set")) {
095                                    return Character.toLowerCase(methodName.charAt(3))
096                                                    + methodName.substring(4);
097                            }
098                    }
099    
100                    return null;
101            }
102    
103            /**
104             * Returns true if the name starts with get or is followed by a capital
105             * letter
106             */
107            private static boolean isGetterMethod(String name) {
108                    Matcher m = getterPattern.matcher(name);
109                    return m.matches();
110            }
111    
112            private static boolean isSetterMethod(String name) {
113                    Matcher m = setterPattern.matcher(name);
114                    return m.matches();
115            }
116    }