package no.priv.garshol.duke.utils; import java.util.Map; import java.util.ArrayList; import java.util.Collection; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; import no.priv.garshol.duke.DukeException; import no.priv.garshol.duke.DukeConfigException; public class ObjectUtils { /** * Returns the enum constant from the given enum class representing * the constant with the given identifier/name. */ public static Object getEnumConstantByName(Class klass, String name) { name = name.toUpperCase(); Object c[] = klass.getEnumConstants(); for (int ix = 0; ix < c.length; ix++) if (c[ix].toString().equals(name)) return c[ix]; throw new DukeConfigException("No such " + klass + ": '" + name + "'"); } /** * Calls the named bean setter property on the object, converting * the given value to the correct type. Note that parameter 'prop' * is converted to a method name according to Lisp convention: * (foo-bar), and not the usual Java dromedaryCase (fooBar). So * "foo-bar" will become "setFooBar". * * <p>The value conversion is mostly straightforward, except that if * the type of the method's first parameter is not a * java.lang.Something, then the method will assume that the value * is the name of an object in the 'objects' map, and pass that. * * <p>Further, if the type is a Collection, the method will assume * the value is a list of object names separated by whitespace. */ public static void setBeanProperty(Object object, String prop, String value, Map<String, Object> objects) { prop = makePropertyName(prop); try { boolean found = false; Method[] methods = object.getClass().getMethods(); for (int ix = 0; ix < methods.length && !found; ix++) { if (!methods[ix].getName().equals(prop)) continue; if (methods[ix].getParameterTypes().length != 1) continue; Class type = methods[ix].getParameterTypes()[0]; methods[ix].invoke(object, convertToType(value, type, objects)); found = true; } if (!found) throw new DukeConfigException("Couldn't find method '" + prop + "' in " + "class " + object.getClass()); } catch (IllegalArgumentException e) { throw new DukeConfigException("Couldn't set bean property " + prop + " on object of class " + object.getClass() + ": " + e); } catch (IllegalAccessException e) { throw new DukeException(e); } catch (InvocationTargetException e) { throw new DukeConfigException("Couldn't set bean property " + prop + " on object of class " + object.getClass() + ": " + e); } } // public because it's used by other packages that use Duke public static String makePropertyName(String name) { char[] buf = new char[name.length() + 3]; int pos = 0; buf[pos++] = 's'; buf[pos++] = 'e'; buf[pos++] = 't'; for (int ix = 0; ix < name.length(); ix++) { char ch = name.charAt(ix); if (ix == 0) ch = Character.toUpperCase(ch); else if (ch == '-') { ix++; if (ix == name.length()) break; ch = Character.toUpperCase(name.charAt(ix)); } buf[pos++] = ch; } return new String(buf, 0, pos); } private static Object convertToType(String value, Class type, Map<String, Object> objects) { if (type == String.class) return value; else if (type == Integer.TYPE) return Integer.parseInt(value); else if (type == Boolean.TYPE) return Boolean.parseBoolean(value); else if (type == Double.TYPE) return Double.parseDouble(value); else if (type == Float.TYPE) return Float.parseFloat(value); else if (type == Character.TYPE) { if (value.length() != 1) throw new DukeConfigException("String '" + value + "' is not a character"); return new Character(value.charAt(0)); } else if (type.isEnum()) return getEnumConstantByName(type, value); else if (type.equals(Collection.class)) { Collection coll = new ArrayList(); String[] values = StringUtils.split(value); for (int ix = 0; ix < values.length; ix++) { Object object = objects.get(values[ix]); if (object == null) object = values[ix]; coll.add(object); } return coll; } else { // now we check if there's an object by this name. if there is // we return that, otherwise we return the value itself. Object object = objects.get(value); if (object != null) return object; else return value; } } public static Object instantiate(String klassname) { try { Class klass = Class.forName(klassname); return klass.newInstance(); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } }