View Javadoc

1   /*
2    * Copyright 2004-2005 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    * 
8    * http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package net.sf.composite.composites;
17  
18  import net.sf.composite.Component;
19  import net.sf.composite.CompositeException;
20  import net.sf.composite.Defaults;
21  import net.sf.composite.ListableComposite;
22  import net.sf.composite.SimpleComposite;
23  import net.sf.composite.StrictlyTypedComposite;
24  import net.sf.composite.ValidatableComposite;
25  import net.sf.composite.specialize.SpecializationException;
26  import net.sf.composite.specialize.Specializer;
27  import net.sf.composite.util.ContainerUtils;
28  import net.sf.composite.validate.ComponentValidationException;
29  import net.sf.composite.validate.ComponentValidator;
30  
31  /***
32   * <p>
33   * A Convenient base class for composites that provides exception handling,
34   * argument checking and default implementations of the methods defined in
35   * {@link net.sf.composite.ListableComposite},
36   * {@link net.sf.composite.StrictlyTypedComposite},
37   * {@link net.sf.composite.ValidatableComposite} and
38   * {@link net.sf.composite.SpecializableComposite}. The final interface is not
39   * declared to be implemented by this class so that subclasses may choose to
40   * expose the interface or not.
41   * </p>
42   * 
43   * @author Matt Sgarlata
44   * @since Dec 27, 2004
45   */
46  public class BaseComposite implements SimpleComposite, ListableComposite, StrictlyTypedComposite, ValidatableComposite {
47  	private Specializer specializer;
48  
49  	private boolean initialized = false;
50  	private Object[] components;
51  	private ComponentValidator componentValidator;
52  	
53  	/***
54  	 * Creates a new composite.  To complete initialization of the composite,
55  	 * either {@link BaseComposite#setComponents(Component[])} or
56  	 * {@link BaseComposite#setComponent(Component)}.
57  	 */
58  	public BaseComposite() {
59  		super();
60  	}
61  
62  	/***
63  	 * Creates a new composite that is composed of only a single component.
64  	 * 
65  	 * @param the
66  	 *            component that makes up this composite
67  	 */
68  	public BaseComposite(Component component) {
69  		super();
70  		setComponent(component);
71  	}
72  	
73  	protected void initializeImpl() {
74  		
75  	}
76  	
77  	private final void initialize() {
78  		if (!initialized) {
79  			validate();
80  			
81  			initializeImpl();
82  		}
83  		initialized = true;
84  	}
85  
86  	public void validate() throws ComponentValidationException {
87  		if (getComponentValidator() != null) {
88  			getComponentValidator().validate(this);
89  		}
90  	}
91  
92  	public boolean containsComponentOfType(Class componentType)
93  		throws CompositeException {
94  		
95  		return !ContainerUtils.hasElementOfType(getComponents(), componentType);
96  	}
97  	
98  	public Object[] getComponentsOfType(Class componentType)
99  		throws CompositeException {
100 		initialize();
101 		try {
102 			return ContainerUtils.getElementsOfType(getComponents(), componentType);
103 		}
104 		catch (Exception e) {
105 			throw new CompositeException(e);
106 		}
107 	}
108 	
109 	public Class getComponentType() throws CompositeException {
110 		return Component.class;
111 	}
112 	
113 	public boolean isSpecializable(Class type) throws SpecializationException {
114 		return getSpecializer().isSpecializable(this, type);
115 	}
116 	public Object specialize(Class type) throws SpecializationException {
117 		return getSpecializer().specialize(this, type);
118 	}	
119 	
120 //	protected SimpleComposite exposeAsTypeImpl(Class compositeType) throws Exception {
121 //		if (compositeType.isAssignableFrom(getClass())) {
122 //			return this;
123 //		}
124 //		else {
125 //			Class[] interfaces = getClass().getInterfaces();
126 //			Class[] implementedInterfaces = new Class[interfaces.length + 1];
127 //			System.arraycopy(interfaces, 0, implementedInterfaces, 0, interfaces.length);
128 //			implementedInterfaces[interfaces.length] = compositeType;
129 //			
130 //			SimpleComposite newComposite = (SimpleComposite) Proxy.newProxyInstance(
131 //				
132 //				compositeType.getClassLoader(), implementedInterfaces,
133 //				createInvocationHandler());
134 //			newComposite.setComponents(getComponentsOfType(compositeType));
135 //			return newComposite;
136 //		}
137 //	}
138 //
139 //	protected InvocationHandler createInvocationHandler() throws Exception {
140 //		return new DelegatingInvocationHandler(this);
141 //	}
142 //
143 //	protected boolean containsComponentOfTypeImpl(Class componentType) throws Exception {
144 //		for (int i=0; getComponents() != null && i<getComponents().length; i++) {
145 //			if (componentType.isAssignableFrom(getComponents()[i].getClass())) {
146 //				return true;
147 //			}
148 //		}
149 //		return false;
150 //	}
151 //
152 //	protected Component[] getComponentsOfTypeImpl(Class componentType) throws Exception {
153 //		Component[] components = getComponents();
154 //		List list = new ArrayList();
155 //		for (int i=0; i<components.length; i++) {
156 //			if (components[i] != null &&
157 //				componentType.isAssignableFrom(components[i].getClass())) {
158 //				list.add(components[i]);
159 //			}
160 //		}
161 //		Object[] array = (Object[]) ClassUtils.createArray(componentType, list.size());
162 //		return (Component[]) list.toArray(array);
163 //	}
164 //
165 //	protected boolean isExposableAsTypeImpl(Class type) throws Exception {
166 //		return containsComponentOfType(type);
167 //	}
168 //
169 //	public final boolean isSpecializable(Class type) throws CompositeException {
170 //		if (type == null) {
171 //			throw new CompositeException("A non-null type must be passed to the " + getClass().getName() + ".isExposableAsType method");
172 //		}
173 //		
174 //		try {
175 //			return isExposableAsTypeImpl(type);
176 //		}
177 //		catch (CompositeException e) {
178 //			throw e;
179 //		}
180 //		catch (Exception e) {
181 //			throw new CompositeException("Unable to determine if this composite, " + ObjectUtils.getObjectDescription(this) + ", can exposed an implementation of " + type.getClass().getName());
182 //		}
183 //	}	
184 //	
185 //	public final SimpleComposite specialize(Class compositeType) {
186 //		initialize();
187 //		
188 //		if (compositeType == null) {
189 //			throw new CompositeException("You must specify the type you would like to have exposed");
190 //		}
191 //		
192 //		try {
193 //			return exposeAsTypeImpl(compositeType);
194 //		}
195 //		catch (CompositeException e) {
196 //			throw e;
197 //		}
198 //		catch (Exception e) {
199 //			throw new CompositeException("Unable to create dynamic composite from "
200 //				+ ObjectUtils.getObjectDescription(this) + " that implements "
201 //				+ ObjectUtils.getObjectDescription(compositeType), e);
202 //		}
203 //	
204 //	}
205 //	
206 //	public final boolean containsComponentOfType(Class componentType) {
207 //		initialize();
208 //		if (componentType == null) {
209 //			throw new CompositeException("A component type must be specified");
210 //		}
211 //		
212 //		try {
213 //			return containsComponentOfTypeImpl(componentType);
214 //		}
215 //		catch (CompositeException e) {
216 //			throw e;
217 //		}
218 //		catch (Exception e) {
219 //			throw new CompositeException(
220 //				"Unable to determine if there are components of type "
221 //					+ ObjectUtils.getObjectDescription(componentType)
222 //					+ " in composite "
223 //					+ ObjectUtils.getObjectDescription(this), e);
224 //		}
225 //	}
226 //	
227 //	public final Component[] getComponentsOfType(Class componentType) {
228 //		initialize();
229 //		if (componentType == null) {
230 //			throw new CompositeException("A component type must be specified");
231 //		}
232 //		
233 //		try {
234 //			return getComponentsOfTypeImpl(componentType);
235 //		}
236 //		catch (CompositeException e) {
237 //			throw e;
238 //		}
239 //		catch (Exception e) {
240 //			throw new CompositeException(
241 //				"Unable to retrieve components of type "
242 //					+ ObjectUtils.getObjectDescription(componentType)
243 //					+ " from composite "
244 //					+ ObjectUtils.getObjectDescription(this), e);
245 //		}
246 //	}
247 //	
248 //	public final Class getComponentType() {
249 //		return Component.class;
250 //	}
251 //	
252 //	protected Component[] getComponentsImpl() throws Exception {
253 //		return this.components;
254 //	}
255 //	
256 //	protected void setComponentsImpl(Component[] components) throws Exception {
257 //		Component[] oldComponents = getComponents();
258 //		this.components = components;
259 //		try {
260 //			initialize();
261 //		}
262 //		catch (CompositeException e) {
263 //			this.components = oldComponents;
264 //			throw e;
265 //		}		
266 //	}
267 	
268 	public Object[] getComponents() {
269 		return components;
270 		
271 //		try {
272 //			return getComponentsImpl(); 
273 //		}
274 //		catch (CompositeException e) {
275 //			throw e;
276 //		}
277 //		catch (Exception e) {
278 //			throw new CompositeException("Unable to return components of composite " + ObjectUtils.getObjectDescription(this), e);
279 //		}
280 	}
281 	
282 	public void setComponents(Object[] components) {
283 		this.components = components;
284 //		try {
285 //			setComponents(components); 
286 //		}
287 //		catch (CompositeException e) {
288 //			throw e;
289 //		}
290 //		catch (Exception e) {
291 //			throw new CompositeException("Unable to set components of composite " + ObjectUtils.getObjectDescription(this), e);
292 //		}		
293 	}
294 	public final void setComponent(Object component) {
295 		setComponents(new Object[] { component });
296 	}
297 
298 	public ComponentValidator getComponentValidator() {
299 		if (componentValidator == null) {
300 			setComponentValidator(Defaults.createComponentValidator());
301 		}
302 		return componentValidator;
303 	}
304 	public void setComponentValidator(ComponentValidator componentValidator) {
305 		this.componentValidator = componentValidator;
306 	}
307 	public Specializer getSpecializer() {
308 		if (specializer == null) {
309 			setSpecializer(Defaults.createSpecializer());
310 		}
311 		return specializer;
312 	}
313 	public void setSpecializer(Specializer specializer) {
314 		this.specializer = specializer;
315 	}
316 }