package org.geoserver.ows.util; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Provides lookup information about java bean properties in a class. * * @author Justin Deoliveira, OpenGEO * @author Andrea Aime, OpenGEO * */ public class ClassProperties { private static final List<Method> EMPTY = new ArrayList<Method>(0); List<Method> methods; List<Method> getters; List<Method> setters; public ClassProperties(Class clazz) { methods = Arrays.asList(clazz.getMethods()); getters = new ArrayList<Method>(); setters = new ArrayList<Method>(); for (Method method : methods) { final String name = method.getName(); final Class<?>[] params = method.getParameterTypes(); if((name.startsWith("get") || name.startsWith("is")) && params.length == 0) { getters.add(method); } else if(name.startsWith("set") && params.length == 1) { setters.add(method); } } // avoid keeping lots of useless empty arrays in memory for // the long term, use just one if(methods.size() == 0) methods = EMPTY; if(getters.size() == 0) getters = EMPTY; if(setters.size() == 0) setters = EMPTY; } /** * Returns a list of all the properties of the class. * * @return A list of string. */ public List<String> properties() { //TODO: factor out check if method is a getter ArrayList<String> properties = new ArrayList<String>(); for ( Method g : getters ) { properties.add( gp( g ) ); } return properties; } /** * Looks up a setter method by property name. * <p> * setter("foo",Integer) -> void setFoo(Integer); * </p> * @param property The property. * @param type The type of the property. * * @return The setter for the property, or null if it does not exist. */ public Method setter(String property, Class type) { for (Method setter : setters) { if(setter.getName().substring(3).equalsIgnoreCase(property)) { if(type == null) { return setter; } else { Class target = setter.getParameterTypes()[0]; if(target.isAssignableFrom(type) || (target.isPrimitive() && type == wrapper(target)) || (type.isPrimitive() && target == wrapper(type))) { return setter; } } } } // could not be found, try again with a more lax match String lax = lax(property); if (!lax.equals(property)) { return setter(lax, type); } return null; } /** * Looks up a getter method by its property name. * <p> * getter("foo",Integer) -> Integer getFoo(); * </p> * @param property The property. * @param type The type of the property. * * @return The getter for the property, or null if it does not exist. */ public Method getter(String property, Class type) { for (Method getter : getters) { if(gp(getter).equalsIgnoreCase(property)) { if(type == null) { return getter; } else { Class target = getter.getReturnType(); if(type.isAssignableFrom(target) || (target.isPrimitive() && type == wrapper(target)) || (type.isPrimitive() && target == wrapper(type))) { return getter; } } } } // could not be found, try again with a more lax match String lax = lax(property); if (!lax.equals(property)) { return getter(lax, type); } return null; } /** * Does some checks on the property name to turn it into a java bean property. * <p> * Checks include collapsing any "_" characters. * </p> */ static String lax(String property) { return property.replaceAll("_", ""); } /** * Returns the wrapper class for a primitive class. * * @param primitive A primtive class, like int.class, double.class, etc... */ static Class wrapper( Class primitive ) { if ( boolean.class == primitive ) { return Boolean.class; } if ( char.class == primitive ) { return Character.class; } if ( byte.class == primitive ) { return Byte.class; } if ( short.class == primitive ) { return Short.class; } if ( int.class == primitive ) { return Integer.class; } if ( long.class == primitive ) { return Long.class; } if ( float.class == primitive ) { return Float.class; } if ( double.class == primitive ) { return Double.class; } return null; } /** * Looks up a method by name. */ public Method method(String name) { for(Method method : methods) { if(method.getName().equalsIgnoreCase(name)) return method; } return null; } /** * Returns the name of the property corresponding to the getter method. */ String gp( Method getter ) { return getter.getName().substring( getter.getName().startsWith("get") ? 3 : 2 ); } }