X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=system%2Fgeneral%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsystem%2Fadapters%2FSetterConfiguration.java;h=18fde542b0050ede0ea92acbdde55093ccfc8cda;hb=49ce7cb8387601982d5e6ef186ce206d38f6e3d7;hp=374edae6cb12a3afb767070985dbc444f54bcd7a;hpb=f667896143dc82c75b9df053e58cac25bafb0daa;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 374edae6..18fde542 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 @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,19 +15,17 @@ */ package org.wamblee.system.adapters; -import java.awt.CompositeContext; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.wamblee.collections.CollectionFilter; import org.wamblee.conditions.Condition; -import org.wamblee.conditions.FixedCondition; -import org.wamblee.general.Pair; -import org.wamblee.system.core.DefaultProvidedInterface; -import org.wamblee.system.core.DefaultRequiredInterface; -import org.wamblee.system.core.ProvidedInterface; +import org.wamblee.reflection.ReflectionUtils; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; import org.wamblee.system.core.SystemAssemblyException; @@ -39,20 +37,50 @@ import org.wamblee.system.core.SystemAssemblyException; * @author Erik Brakkee */ public class SetterConfiguration { + private Class clazz; - 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. */ public SetterConfiguration(Class aClass) { - _class = aClass; - _setters = getAllSetters(); + clazz = aClass; + publicOnly = true; + setters = new HashMap(); + } + + /** + * Makes sure that all available setters are used. + * + */ + public SetterConfiguration initAllSetters() { + setters.clear(); + + for (Method method : getAllSetters(clazz, 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. The currently selected setters remain chosen. + * + * @param aIsNonPublic + * Non public flag. + * + */ + public SetterConfiguration setNonPublic(boolean aIsNonPublic) { + publicOnly = !aIsNonPublic; + + return this; } /** @@ -61,7 +89,8 @@ public class SetterConfiguration { * @return Reference to the current object to allow call chaining. */ public SetterConfiguration clear() { - _setters.clear(); + setters.clear(); + return this; } @@ -69,143 +98,238 @@ 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); - } + for (Method method : setters.keySet()) { + if (method.getName().equals(aName)) { + setters.remove(method); - }); - if ( _setters.size() == setters.size()) { - throw new IllegalArgumentException("No setter configured by the name of '" + aName + "'"); + return this; + } } - _setters = setters; - return this; + + throw new IllegalArgumentException( + "No method configured by the name of '" + aName + "'"); } /** - * Creates the name of a setter based on the name of the setter without - * the "set" prefix. - * @param aName Setter name. - * @return Setter name. + * Removes the method from the set of methods. + * + * @param aMethod + * Method to remove. + * + * @return + * */ - private String createSetterName(String aName) { - return "set" + aName.substring(0, 1).toUpperCase() - + aName.substring(1); + public SetterConfiguration remove(Method aMethod) { + if (!aMethod.getDeclaringClass().isAssignableFrom(clazz)) { + throw new RuntimeException("Method " + aMethod + + " not found in class " + clazz + " 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. "); } /** - * Adds a given setter name to the setters. + * Adds a given setter name to the setters. + * * @param aName - * @return Reference to the current object to allow call chaining. + * 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); - int oldlen = _setters.size(); - CollectionFilter.filter(getAllSetters(), _setters, - new Condition>() { - @Override - public boolean matches(Pair aObject) { - return aObject.getFirst().getName().equals(name); - } - - }); - if ( _setters.size() == oldlen) { - throw new IllegalArgumentException("No setter found for '" + aName + "' in " + _class.getName()); + public SetterConfiguration add(final String aName) { + List methods = new ArrayList(); + CollectionFilter.filter(getAllSetters(clazz, publicOnly), methods, + new Condition() { + @Override + public boolean matches(Method aObject) { + return aObject.getName().equals(aName); + } + }); + + if (methods.size() == 0) { + throw new IllegalArgumentException("Method '" + aName + + "' not found in " + clazz.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; } /** - * Gets all setters for the current class. - * @return List of all setters. + * 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. */ - private List> getAllSetters() { - List> result = - new ArrayList>(); - for (Method method : _class.getMethods()) { - if (method.getName().startsWith("set") - && method.getParameterTypes().length == 1) { - String name = getSetterName(method); - result.add(new Pair(method, - new ParameterValues( - new String[] { name }, new Class[] { method.getParameterTypes()[0] }))); + public SetterConfiguration addSetter(final Class aType) { + List result = new ArrayList(); + CollectionFilter.filter(getAllSetters(clazz, 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 '" + + clazz.getName() + "' that has a setter with argument type '" + + aType.getName() + "'"); + } + + if (result.size() > 1) { + StringBuffer settersString = new StringBuffer(); + + for (Method method : result) { + settersString.append((method.getName() + " ")); + } + + throw new IllegalArgumentException( + "Multiple setters found in class '" + clazz.getName() + + " that accept type '" + aType.getName() + "': " + + settersString); + } + + Method method = result.get(0); + setters.put(method, createParameterValues(method)); + + return this; + } + + /** + * Gets all setters for the current class. + * + * + * @return List of all setters. + */ + 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); + result.add(method); + } } } + return result; } - + + private static ParameterValues createParameterValues(Method aMethod) { + Class[] paramTypes = aMethod.getParameterTypes(); + String[] paramNames = new String[paramTypes.length]; + + for (int i = 0; i < paramTypes.length; i++) { + paramNames[i] = aMethod.getName() + "." + i; + } + + return new ParameterValues(paramNames, paramTypes); + } + + private static final List getAllMethods(Class aClass) { + return ReflectionUtils.getAllMethods(aClass); + } + /** * Gets the required interfaces based on the configured setteres. - * @return List of required interfaces. + * + * @return List of required interfaces. */ - public List getRequiredInterfaces() { + 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; + + return result; } - - + /** - * Invokes all configured setters with the appropriate values. - * @param aScope Scope within which invocation takes place. - * @param aObject Object on which the invocation takes place. + * Invokes all configured setters with the appropriate values. + * + * @param aScope + * Scope within which invocation takes place. + * @param aObject + * Object on which the invocation takes place. + * */ public void inject(Scope aScope, Object aObject) { - if ( !_class.isInstance(aObject)) { - throw new IllegalArgumentException("Object '" + aObject + "' is not an instance of " - + _class.getName()); + if (!clazz.isInstance(aObject)) { + throw new IllegalArgumentException("Object '" + aObject + + "' is not an instance of " + clazz.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)); } catch (IllegalAccessException e) { - throw new SystemAssemblyException("Problem invoking " + method + " with " + values, e); - } catch (InvocationTargetException e) { - throw new SystemAssemblyException("Problem invoking " + method + " with " + values, e); + throw new SystemAssemblyException("Problem invoking " + method + + " with " + values, e); + } catch (InvocationTargetException e) { + throw new SystemAssemblyException("Problem invoking " + method + + " with " + values, e); } } } - + /** * Returns the parameter values for allowing detailed configuration of how * parameter values are set. - * @param aSetter Setter name without the "set" prefix with the first - * character converted to lower case. - * @return Parameter values. + * + * @param aMethod + * Setter name without the "set" prefix with the first character + * converted to lower case. + * + * @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(); + public ParameterValues values(String aMethod) { + for (Method method : setters.keySet()) { + if (method.getName().equals(aMethod)) { + return setters.get(method); } } - throw new IllegalArgumentException("No setter method '" + name + "' found"); + + throw new IllegalArgumentException("No setter method '" + aMethod + + "' found"); } - /** - * Gets the setter name for a given setter method. This is the name of the - * setter without the "set" prefix and with the first character converted to - * lowercase. - * @param aMethod Method. - * @return Setter name. - */ - private String getSetterName(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()); } - }