X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=system%2Fgeneral%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsystem%2Fadapters%2FSetterConfiguration.java;h=f81c4a4bc405837d893f5e021635a3b3bd1e0137;hb=2d7b0cb1921d9b37821f7d838ab070f5394a6fa4;hp=581c5b5913e7513fd5c7d59e37ceeb5c1b1c2429;hpb=d3f458acc63a8754f4104d0623f8b4af6b708168;p=utils diff --git a/system/general/src/main/java/org/wamblee/system/adapters/SetterConfiguration.java b/system/general/src/main/java/org/wamblee/system/adapters/SetterConfiguration.java index 581c5b59..f81c4a4b 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/SetterConfiguration.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/SetterConfiguration.java @@ -21,12 +21,16 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; import org.wamblee.collections.CollectionFilter; import org.wamblee.conditions.Condition; import org.wamblee.conditions.FixedCondition; import org.wamblee.general.Pair; +import org.wamblee.reflection.ReflectionUtils; import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.DefaultRequiredInterface; import org.wamblee.system.core.ProvidedInterface; @@ -45,10 +49,10 @@ public class SetterConfiguration { private Class _class; private boolean _publicOnly; - private List> _setters; + private Map _setters; /** - * Constructs the setter configuration. By default all setters are added. + * Constructs the setter configuration. By default no setters are added. * * @param aClass * Class which is being configured. @@ -56,19 +60,30 @@ public class SetterConfiguration { public SetterConfiguration(Class aClass) { _class = aClass; _publicOnly = true; - _setters = getAllSetters(_class, _publicOnly); + _setters = new HashMap(); + } + + /** + * Makes sure that all available setters are used. + */ + public SetterConfiguration initAllSetters() { + _setters.clear(); + for (Method method: getAllSetters(_class, _publicOnly) ) { + _setters.put(method, createParameterValues(method)); + } + return this; } /** * Called to set whether non-public setters are also used. By default only - * public setters are used. + * public setters are used. The currently selected setters remain chosen. * * @param aIsNonPublic * Non public flag. */ - public void setNonPublic(boolean aIsNonPublic) { + public SetterConfiguration setNonPublic(boolean aIsNonPublic) { _publicOnly = !aIsNonPublic; - _setters = getAllSetters(_class, _publicOnly); + return this; } /** @@ -85,27 +100,40 @@ public class SetterConfiguration { * Removes a setter from the set of methods. * * @param aName - * Name of the setter to remove (without the "set" prefix). + * Name of the setter to remove. * @return Reference to the current object to allow call chaining. */ public SetterConfiguration remove(String aName) { - final String name = createSetterName(aName); - List> setters = new ArrayList>(); - CollectionFilter.filter(_setters, setters, - new Condition>() { - @Override - public boolean matches(Pair aObject) { - return !aObject.getFirst().getName().equals(name); - } - - }); - if (_setters.size() == setters.size()) { - throw new IllegalArgumentException( - "No setter configured by the name of '" + aName + "'"); + for (Method method : _setters.keySet()) { + if (method.getName().equals(aName)) { + _setters.remove(method); + return this; + } } - _setters = setters; - return this; + throw new IllegalArgumentException( + "No method configured by the name of '" + aName + "'"); } + + /** + * Removes the method from the set of methods. + * @param aMethod Method to remove. + * @return + */ + public SetterConfiguration remove(Method aMethod) { + if ( !aMethod.getDeclaringClass().isAssignableFrom(_class) ) { + throw new RuntimeException("Method " + aMethod + " not found in class " + _class + " or its superclasses"); + } + for (Method method : _setters.keySet()) { + if (method.equals(aMethod)) { + _setters.remove(method); + return this; + } + } + throw new IllegalArgumentException( + "Method '" + aMethod + "' was not configured. "); + } + + /** * Creates the name of a setter based on the name of the setter without the @@ -115,31 +143,77 @@ public class SetterConfiguration { * Setter name. * @return Setter name. */ - private String createSetterName(String aName) { + private String createxSetterName(String aName) { return "set" + aName.substring(0, 1).toUpperCase() + aName.substring(1); } /** * Adds a given setter name to the setters. * - * @param aName + * @param aName Name of a setter method. * @return Reference to the current object to allow call chaining. */ - public SetterConfiguration add(String aName) { - final String name = createSetterName(aName); + public SetterConfiguration add(final String aName) { int oldlen = _setters.size(); - CollectionFilter.filter(getAllSetters(_class, false), _setters, - new Condition>() { + List methods = new ArrayList(); + CollectionFilter.filter(getAllSetters(_class, _publicOnly), methods, + new Condition() { @Override - public boolean matches(Pair aObject) { - return aObject.getFirst().getName().equals(name); + public boolean matches(Method aObject) { + return aObject.getName().equals(aName); } }); - if (_setters.size() == oldlen) { - throw new IllegalArgumentException("No setter found for '" + aName - + "' in " + _class.getName()); + if (methods.size() == 0 ) { + throw new IllegalArgumentException("Method '" + aName + + "' not found in " + _class.getName()); } + // TODO is it possible to get more than one setter here in case the subclass overrides + // the baseclass method? + _setters.put(methods.get(0), createParameterValues(methods.get(0))); + return this; + } + + /** + * Adds a given setter identified by the type it accepts to the list of + * setters.N + * + * @param aType + * Type to look for. Note that this must be the exact type as + * autoboxing and autounboxing is not used. + * @return Reference to the current object to allow call chaining. + * @throws IllegalArgumentException + * In case no setter is found or multiple setters are found. + */ + public SetterConfiguration add(final Class aType) { + List result = new ArrayList(); + CollectionFilter.filter(getAllSetters(_class, _publicOnly), result, + new Condition() { + @Override + public boolean matches(Method aObject) { + Class type = aObject.getParameterTypes()[0]; + return type.equals(aType); + } + + }); + if (result.size() == 0) { + throw new IllegalArgumentException("No setter found in class '" + + _class.getName() + + "' that has a setter with argument type '" + + aType.getName() + "'"); + } + if (result.size() > 1) { + String setters = ""; + for (Method method : result) { + setters += method.getName() + " "; + } + throw new IllegalArgumentException( + "Multiple setters found in class '" + _class.getName() + + " that accept type '" + aType.getName() + "': " + + setters); + } + Method method = result.get(0); + _setters.put(method, createParameterValues(method)); return this; } @@ -148,35 +222,31 @@ public class SetterConfiguration { * * @return List of all setters. */ - private static List> getAllSetters( - Class aClass, boolean aPublicOnly) { - List> result = new ArrayList>(); + public static List getAllSetters(Class aClass, + boolean aPublicOnly) { + List result = new ArrayList(); for (Method method : getAllMethods(aClass)) { if (!aPublicOnly || Modifier.isPublic(method.getModifiers())) { if (method.getName().startsWith("set") && method.getParameterTypes().length == 1) { method.setAccessible(true); - String name = getSetterName(method); - result - .add(new Pair(method, - new ParameterValues(new String[] { name }, - new Class[] { method - .getParameterTypes()[0] }))); + result.add(method); } } } return result; } + private static ParameterValues createParameterValues(Method method) { + // TODO generalize to multiple parameters. + return new ParameterValues( + new String[] { method.getName() }, new Class[] { method + .getParameterTypes()[0] }); + } + private static final List getAllMethods(Class aClass) { - List result = new ArrayList(); - result.addAll(Arrays.asList(aClass.getDeclaredMethods())); - Class superClass = aClass.getSuperclass(); - if ( superClass != null ) { - result.addAll(getAllMethods(superClass)); - } - return result; - } + return ReflectionUtils.getAllMethods(aClass); + } /** * Gets the required interfaces based on the configured setteres. @@ -185,8 +255,8 @@ public class SetterConfiguration { */ public List getRequiredInterfaces() { List result = new ArrayList(); - for (Pair method : _setters) { - result.addAll(method.getSecond().getRequiredInterfaces()); + for (Method method : _setters.keySet()) { + result.addAll(_setters.get(method).getRequiredInterfaces()); } return result; } @@ -204,9 +274,8 @@ public class SetterConfiguration { throw new IllegalArgumentException("Object '" + aObject + "' is not an instance of " + _class.getName()); } - for (Pair setter : _setters) { - Method method = setter.getFirst(); - ParameterValues values = setter.getSecond(); + for (Method method : _setters.keySet()) { + ParameterValues values = _setters.get(method); try { method.invoke(aObject, values.values(aScope)); @@ -230,13 +299,12 @@ public class SetterConfiguration { * @return Parameter values. */ public ParameterValues values(String aMethod) { - String name = createSetterName(aMethod); - for (Pair method : _setters) { - if (method.getFirst().getName().equals(name)) { - return method.getSecond(); + for (Method method : _setters.keySet()) { + if (method.getName().equals(aMethod)) { + return _setters.get(method); } } - throw new IllegalArgumentException("No setter method '" + name + throw new IllegalArgumentException("No setter method '" + aMethod + "' found"); } @@ -249,9 +317,12 @@ public class SetterConfiguration { * Method. * @return Setter name. */ - private static String getSetterName(Method aMethod) { + private static String getxSetterName(Method aMethod) { String result = aMethod.getName().substring(3); return result.substring(0, 1).toLowerCase() + result.substring(1); } + public List getSetters() { + return new ArrayList(_setters.keySet()); + } }