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 }