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;
private Class _class;
private boolean _publicOnly;
- private List<Pair<Method, ParameterValues>> _setters;
+ private Map<Method, ParameterValues> _setters;
/**
* Constructs the setter configuration. By default all setters are added.
public SetterConfiguration(Class aClass) {
_class = aClass;
_publicOnly = true;
- _setters = getAllSetters(_class, _publicOnly);
+ initSetters();
+ }
+
+ private void initSetters() {
+ _setters = new HashMap<Method, ParameterValues>();
+ for (Method method: getAllSetters(_class, _publicOnly) ) {
+ _setters.put(method, createParameterValues(method));
+ }
}
/**
* Called to set whether non-public setters are also used. By default only
- * public setters are used.
+ * public setters are used. This resets all changes made and selects all
+ * public setters if non-public is false and all setters if it is true.
*
* @param aIsNonPublic
* Non public flag.
*/
public void setNonPublic(boolean aIsNonPublic) {
_publicOnly = !aIsNonPublic;
- _setters = getAllSetters(_class, _publicOnly);
+ initSetters();
}
/**
*/
public SetterConfiguration remove(String aName) {
final String name = createSetterName(aName);
- List<Pair<Method, ParameterValues>> setters = new ArrayList<Pair<Method, ParameterValues>>();
- CollectionFilter.filter(_setters, setters,
- new Condition<Pair<Method, ParameterValues>>() {
- @Override
- public boolean matches(Pair<Method, ParameterValues> aObject) {
- return !aObject.getFirst().getName().equals(name);
- }
-
- });
- if (_setters.size() == setters.size()) {
- throw new IllegalArgumentException(
- "No setter configured by the name of '" + aName + "'");
+ Map<Method, ParameterValues> setters = new HashMap<Method, ParameterValues>();
+ for (Method method : _setters.keySet()) {
+ if (method.getName().equals(name)) {
+ _setters.remove(method);
+ return this;
+ }
}
- _setters = setters;
- return this;
+ throw new IllegalArgumentException(
+ "No setter configured by the name of '" + aName + "'");
}
/**
public SetterConfiguration add(String aName) {
final String name = createSetterName(aName);
int oldlen = _setters.size();
- CollectionFilter.filter(getAllSetters(_class, false), _setters,
- new Condition<Pair<Method, ParameterValues>>() {
+ List<Method> methods = new ArrayList<Method>();
+ CollectionFilter.filter(getAllSetters(_class, _publicOnly), methods,
+ new Condition<Method>() {
@Override
- public boolean matches(Pair<Method, ParameterValues> aObject) {
- return aObject.getFirst().getName().equals(name);
+ public boolean matches(Method aObject) {
+ return aObject.getName().equals(name);
}
});
- if (_setters.size() == oldlen) {
+ if (methods.size() == 0 ) {
throw new IllegalArgumentException("No setter found for '" + aName
+ "' 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<Method> result = new ArrayList<Method>();
+ CollectionFilter.filter(getAllSetters(_class, _publicOnly), result,
+ new Condition<Method>() {
+ @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;
}
*
* @return List of all setters.
*/
- private static List<Pair<Method, ParameterValues>> getAllSetters(
- Class aClass, boolean aPublicOnly) {
- List<Pair<Method, ParameterValues>> result = new ArrayList<Pair<Method, ParameterValues>>();
+ private static List<Method> getAllSetters(Class aClass,
+ boolean aPublicOnly) {
+ List<Method> result = new ArrayList<Method>();
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, ParameterValues>(method,
- new ParameterValues(new String[] { name },
- new Class[] { method
- .getParameterTypes()[0] })));
+ result.add(method);
}
}
}
return result;
}
+ private static ParameterValues createParameterValues(Method method) {
+ return new ParameterValues(
+ new String[] { getSetterName(method) }, new Class[] { method
+ .getParameterTypes()[0] });
+ }
+
private static final List<Method> getAllMethods(Class aClass) {
- List<Method> result = new ArrayList<Method>();
- 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.
*/
public List<RequiredInterface> getRequiredInterfaces() {
List<RequiredInterface> result = new ArrayList<RequiredInterface>();
- for (Pair<Method, ParameterValues> method : _setters) {
- result.addAll(method.getSecond().getRequiredInterfaces());
+ for (Method method : _setters.keySet()) {
+ result.addAll(_setters.get(method).getRequiredInterfaces());
}
return result;
}
throw new IllegalArgumentException("Object '" + aObject
+ "' is not an instance of " + _class.getName());
}
- for (Pair<Method, ParameterValues> 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));
*/
public ParameterValues values(String aMethod) {
String name = createSetterName(aMethod);
- for (Pair<Method, ParameterValues> method : _setters) {
- if (method.getFirst().getName().equals(name)) {
- return method.getSecond();
+ for (Method method : _setters.keySet()) {
+ if (method.getName().equals(name)) {
+ return _setters.get(method);
}
}
throw new IllegalArgumentException("No setter method '" + name
return result.substring(0, 1).toLowerCase() + result.substring(1);
}
+ public List<Method> getSetters() {
+ return new ArrayList<Method>(_setters.keySet());
+ }
}
*/
package org.wamblee.system.adapters;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import javax.sql.DataSource;
+
import org.wamblee.system.core.DefaultProvidedInterface;
import org.wamblee.system.core.ProvidedInterface;
import org.wamblee.system.core.RequiredInterface;
assertNull(obj.getPort());
}
- public void testAdd() {
+ public void testAddByName() {
SetterConfiguration config = new SetterConfiguration(X6.class);
config.clear().add("host");
List<RequiredInterface> required = config.getRequiredInterfaces();
assertEquals("hello", obj.getHost());
assertNull(obj.getPort());
}
+
+ public void testAddByType() {
+ SetterConfiguration config = new SetterConfiguration(X6.class);
+ config.clear().add(String.class);
+ List<RequiredInterface> required = config.getRequiredInterfaces();
+ Collections.sort(required, new RequiredInterfaceComparator());
+ assertEquals(1, required.size());
+ assertEquals("host", required.get(0).getName());
+
+ ProvidedInterface provided0 = new DefaultProvidedInterface("janse",
+ String.class);
+ required.get(0).setProvider(provided0);
+ provided0.publish("hello", _scope);
+
+ X6 obj = new X6();
+ assertNull(obj.getHost());
+ assertNull(obj.getPort());
+
+ config.inject(_scope, obj);
+ assertEquals("hello", obj.getHost());
+ assertNull(obj.getPort());
+ }
+
+ public void testAddPrivate() {
+ X5 obj = new X5();
+ final SetterConfiguration config = new SetterConfiguration(X5.class);
+ AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+ @Override
+ public void run() throws Exception {
+ config.add("xyz");
+ }
+ }, IllegalArgumentException.class);
+
+ config.setNonPublic(true);
+ config.clear();
+ config.add("xyz");
+ assertEquals(1, config.getRequiredInterfaces().size());
+ }
public void testAddNonExisting() {
final SetterConfiguration config = new SetterConfiguration(X6.class);
config.add("bladibla");
}
}, IllegalArgumentException.class);
+ AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+ @Override
+ public void run() throws Exception {
+ config.add(DataSource.class);
+ }
+ }, IllegalArgumentException.class);
+ }
+
+ public void testAddByTypeNonUnique() {
+ final SetterConfiguration config = new SetterConfiguration(X11.class);
+ config.clear();
+ AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+ @Override
+ public void run() throws Exception {
+ config.add(String.class);
+ }
+ }, IllegalArgumentException.class);
}
public void testRemove() {
}
}, IllegalArgumentException.class);
}
+
+ public void testOverridingSetters() {
+ SetterConfiguration config = new SetterConfiguration(X10.class);
+ assertEquals(2, config.getRequiredInterfaces().size());
+ List<Method> methods = config.getSetters();
+ assertEquals(2, methods.size());
+ for (Method method: methods) {
+ assertEquals(X10.class, method.getDeclaringClass());
+ }
+
+ }
}