- private Class _class;
- private boolean _publicOnly;
-
- private List<Pair<Method, ParameterValues>> _setters;
-
- /**
- * Constructs the setter configuration. By default all setters are added.
- *
- * @param aClass
- * Class which is being configured.
- */
- public SetterConfiguration(Class aClass) {
- _class = aClass;
- _publicOnly = true;
- _setters = getAllSetters(_class, _publicOnly);
- }
-
- /**
- * Called to set whether non-public setters are also used. By default only
- * public setters are used.
- *
- * @param aIsNonPublic
- * Non public flag.
- */
- public void setNonPublic(boolean aIsNonPublic) {
- _publicOnly = !aIsNonPublic;
- _setters = getAllSetters(_class, _publicOnly);
- }
-
- /**
- * Removes all setters.
- *
- * @return Reference to the current object to allow call chaining.
- */
- public SetterConfiguration clear() {
- _setters.clear();
- return this;
- }
-
- /**
- * Removes a setter from the set of methods.
- *
- * @param aName
- * Name of the setter to remove (without the "set" prefix).
- * @return Reference to the current object to allow call chaining.
- */
- 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 + "'");
- }
- _setters = setters;
- return this;
- }
-
- /**
- * Creates the name of a setter based on the name of the setter without the
- * "set" prefix.
- *
- * @param aName
- * Setter name.
- * @return Setter name.
- */
- private String createSetterName(String aName) {
- return "set" + aName.substring(0, 1).toUpperCase() + aName.substring(1);
- }
-
- /**
- * Adds a given setter name to the setters.
- *
- * @param aName
- * @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(_class, false), _setters,
- new Condition<Pair<Method, ParameterValues>>() {
- @Override
- public boolean matches(Pair<Method, ParameterValues> aObject) {
- return aObject.getFirst().getName().equals(name);
- }
-
- });
- if (_setters.size() == oldlen) {
- throw new IllegalArgumentException("No setter found for '" + aName
- + "' in " + _class.getName());
- }
- return this;
- }
-
- /**
- * Gets all setters for the current class.
- *
- * @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>>();
- 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] })));
- }
- }
- }
- return result;
- }
-
- 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;
+ private boolean publicOnly;
+
+ private Map<Method, ParameterValues> setters;
+
+ /**
+ * Constructs the setter configuration. By default no setters are added.
+ *
+ * @param aClass
+ * Class which is being configured.
+ */
+ public SetterConfiguration(Class aClass) {
+ clazz = aClass;
+ publicOnly = true;
+ setters = new HashMap<Method, ParameterValues>();
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Removes all setters.
+ *
+ * @return Reference to the current object to allow call chaining.
+ */
+ public SetterConfiguration clear() {
+ setters.clear();
+
+ return this;
+ }
+
+ /**
+ * Removes a setter from the set of methods.
+ *
+ * @param aName
+ * Name of the setter to remove.
+ *
+ * @return Reference to the current object to allow call chaining.
+ *
+ */
+ public SetterConfiguration remove(String aName) {
+ for (Method method : setters.keySet()) {
+ if (method.getName().equals(aName)) {
+ setters.remove(method);
+
+ 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(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.
+ *
+ * @param aName
+ * Name of a setter method.
+ *
+ * @return Reference to the current object to allow call chaining.
+ *
+ */
+ public SetterConfiguration add(final String aName) {
+ List<Method> methods = new ArrayList<Method>();
+ CollectionFilter.filter(getAllSetters(clazz, publicOnly), methods,
+ new Condition<Method>() {
+ @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;
+ }
+
+ /**
+ * 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 addSetter(final Class aType) {
+ List<Method> result = new ArrayList<Method>();
+ CollectionFilter.filter(getAllSetters(clazz, 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 '" +
+ 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<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);
+ 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<Method> getAllMethods(Class aClass) {
+ return ReflectionUtils.getAllMethods(aClass);
+ }
+
+ /**
+ * Gets the required interfaces based on the configured setteres.
+ *
+ * @return List of required interfaces.
+ */
+ public List<RequiredInterface> getRequiredInterfaces() {
+ List<RequiredInterface> result = new ArrayList<RequiredInterface>();
+
+ for (Method method : setters.keySet()) {
+ result.addAll(setters.get(method).getRequiredInterfaces());
+ }
+
+ return result;