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 }