2 * Copyright 2008 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.system.adapters;
18 import java.awt.CompositeContext;
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21 import java.lang.reflect.Modifier;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.List;
26 import org.wamblee.collections.CollectionFilter;
27 import org.wamblee.conditions.Condition;
28 import org.wamblee.conditions.FixedCondition;
29 import org.wamblee.general.Pair;
30 import org.wamblee.system.core.DefaultProvidedInterface;
31 import org.wamblee.system.core.DefaultRequiredInterface;
32 import org.wamblee.system.core.ProvidedInterface;
33 import org.wamblee.system.core.RequiredInterface;
34 import org.wamblee.system.core.Scope;
35 import org.wamblee.system.core.SystemAssemblyException;
38 * Represents the configuration for exposing the setters of a class as required
41 * @author Erik Brakkee
43 public class SetterConfiguration {
46 private boolean _publicOnly;
48 private List<Pair<Method, ParameterValues>> _setters;
51 * Constructs the setter configuration. By default all setters are added.
54 * Class which is being configured.
56 public SetterConfiguration(Class aClass) {
59 _setters = getAllSetters(_class, _publicOnly);
63 * Called to set whether non-public setters are also used. By default only
64 * public setters are used.
69 public void setNonPublic(boolean aIsNonPublic) {
70 _publicOnly = !aIsNonPublic;
71 _setters = getAllSetters(_class, _publicOnly);
75 * Removes all setters.
77 * @return Reference to the current object to allow call chaining.
79 public SetterConfiguration clear() {
85 * Removes a setter from the set of methods.
88 * Name of the setter to remove (without the "set" prefix).
89 * @return Reference to the current object to allow call chaining.
91 public SetterConfiguration remove(String aName) {
92 final String name = createSetterName(aName);
93 List<Pair<Method, ParameterValues>> setters = new ArrayList<Pair<Method, ParameterValues>>();
94 CollectionFilter.filter(_setters, setters,
95 new Condition<Pair<Method, ParameterValues>>() {
97 public boolean matches(Pair<Method, ParameterValues> aObject) {
98 return !aObject.getFirst().getName().equals(name);
102 if (_setters.size() == setters.size()) {
103 throw new IllegalArgumentException(
104 "No setter configured by the name of '" + aName + "'");
111 * Creates the name of a setter based on the name of the setter without the
116 * @return Setter name.
118 private String createSetterName(String aName) {
119 return "set" + aName.substring(0, 1).toUpperCase() + aName.substring(1);
123 * Adds a given setter name to the setters.
126 * @return Reference to the current object to allow call chaining.
128 public SetterConfiguration add(String aName) {
129 final String name = createSetterName(aName);
130 int oldlen = _setters.size();
131 CollectionFilter.filter(getAllSetters(_class, false), _setters,
132 new Condition<Pair<Method, ParameterValues>>() {
134 public boolean matches(Pair<Method, ParameterValues> aObject) {
135 return aObject.getFirst().getName().equals(name);
139 if (_setters.size() == oldlen) {
140 throw new IllegalArgumentException("No setter found for '" + aName
141 + "' in " + _class.getName());
147 * Gets all setters for the current class.
149 * @return List of all setters.
151 private static List<Pair<Method, ParameterValues>> getAllSetters(
152 Class aClass, boolean aPublicOnly) {
153 List<Pair<Method, ParameterValues>> result = new ArrayList<Pair<Method, ParameterValues>>();
154 for (Method method : getAllMethods(aClass)) {
155 if (!aPublicOnly || Modifier.isPublic(method.getModifiers())) {
156 if (method.getName().startsWith("set")
157 && method.getParameterTypes().length == 1) {
158 method.setAccessible(true);
159 String name = getSetterName(method);
161 .add(new Pair<Method, ParameterValues>(method,
162 new ParameterValues(new String[] { name },
164 .getParameterTypes()[0] })));
171 private static final List<Method> getAllMethods(Class aClass) {
172 List<Method> result = new ArrayList<Method>();
173 result.addAll(Arrays.asList(aClass.getDeclaredMethods()));
174 Class superClass = aClass.getSuperclass();
175 if ( superClass != null ) {
176 result.addAll(getAllMethods(superClass));
182 * Gets the required interfaces based on the configured setteres.
184 * @return List of required interfaces.
186 public List<RequiredInterface> getRequiredInterfaces() {
187 List<RequiredInterface> result = new ArrayList<RequiredInterface>();
188 for (Pair<Method, ParameterValues> method : _setters) {
189 result.addAll(method.getSecond().getRequiredInterfaces());
195 * Invokes all configured setters with the appropriate values.
198 * Scope within which invocation takes place.
200 * Object on which the invocation takes place.
202 public void inject(Scope aScope, Object aObject) {
203 if (!_class.isInstance(aObject)) {
204 throw new IllegalArgumentException("Object '" + aObject
205 + "' is not an instance of " + _class.getName());
207 for (Pair<Method, ParameterValues> setter : _setters) {
208 Method method = setter.getFirst();
209 ParameterValues values = setter.getSecond();
212 method.invoke(aObject, values.values(aScope));
213 } catch (IllegalAccessException e) {
214 throw new SystemAssemblyException("Problem invoking " + method
215 + " with " + values, e);
216 } catch (InvocationTargetException e) {
217 throw new SystemAssemblyException("Problem invoking " + method
218 + " with " + values, e);
224 * Returns the parameter values for allowing detailed configuration of how
225 * parameter values are set.
228 * Setter name without the "set" prefix with the first character
229 * converted to lower case.
230 * @return Parameter values.
232 public ParameterValues values(String aMethod) {
233 String name = createSetterName(aMethod);
234 for (Pair<Method, ParameterValues> method : _setters) {
235 if (method.getFirst().getName().equals(name)) {
236 return method.getSecond();
239 throw new IllegalArgumentException("No setter method '" + name
244 * Gets the setter name for a given setter method. This is the name of the
245 * setter without the "set" prefix and with the first character converted to
250 * @return Setter name.
252 private static String getSetterName(Method aMethod) {
253 String result = aMethod.getName().substring(3);
254 return result.substring(0, 1).toLowerCase() + result.substring(1);