001: /*****************************************************************************
002: * Copyright (C) PicoContainer Organization. All rights reserved. *
003: * ------------------------------------------------------------------------- *
004: * The software in this package is published under the terms of the BSD *
005: * style license a copy of which has been included with this distribution in *
006: * the LICENSE.txt file. *
007: * *
008: * Original code by *
009: *****************************************************************************/package org.picocontainer;
010:
011: import static org.picocontainer.behaviors.Behaviors.caching;
012: import static org.picocontainer.behaviors.Behaviors.implementationHiding;
013: import org.picocontainer.behaviors.PropertyApplying;
014: import org.picocontainer.behaviors.Synchronizing;
015: import org.picocontainer.behaviors.Locking;
016: import org.picocontainer.behaviors.Automating;
017: import org.picocontainer.injectors.MethodInjection;
018: import org.picocontainer.containers.EmptyPicoContainer;
019: import org.picocontainer.containers.TransientPicoContainer;
020: import static org.picocontainer.injectors.Injectors.CDI;
021: import static org.picocontainer.injectors.Injectors.annotatedMethodDI;
022: import static org.picocontainer.injectors.Injectors.annotatedFieldDI;
023: import static org.picocontainer.injectors.Injectors.SDI;
024: import static org.picocontainer.injectors.Injectors.adaptiveDI;
025: import org.picocontainer.lifecycle.NullLifecycleStrategy;
026: import org.picocontainer.lifecycle.ReflectionLifecycleStrategy;
027: import org.picocontainer.lifecycle.StartableLifecycleStrategy;
028: import org.picocontainer.monitors.ConsoleComponentMonitor;
029: import org.picocontainer.monitors.NullComponentMonitor;
030:
031: import java.util.ArrayList;
032: import java.util.Stack;
033: import java.util.List;
034:
035: /**
036: * Helps assembles the myriad items available to a picocontainer.
037: * <p>Simple Example:</p>
038: * <pre>
039: * MutablePicoContainer mpc = new PicoBuilder()
040: * .withCaching()
041: * .withLifecycle()
042: * .build();
043: * </pre>
044: * @author Paul Hammant
045: */
046: public class PicoBuilder {
047:
048: private PicoContainer parentContainer;
049: private Class<? extends MutablePicoContainer> mpcClass = DefaultPicoContainer.class;
050: private ComponentMonitor componentMonitor;
051: private List<Object> containerComps = new ArrayList<Object>();
052:
053: public PicoBuilder(PicoContainer parentContainer,
054: InjectionFactory injectionType) {
055: this .injectionType = injectionType;
056: if (parentContainer != null) {
057: this .parentContainer = parentContainer;
058: } else {
059: this .parentContainer = new EmptyPicoContainer();
060: }
061: }
062:
063: public PicoBuilder(PicoContainer parentContainer) {
064: this (parentContainer, adaptiveDI());
065: }
066:
067: public PicoBuilder(InjectionFactory injectionType) {
068: this (new EmptyPicoContainer(), injectionType);
069: }
070:
071: public PicoBuilder() {
072: this (new EmptyPicoContainer(), adaptiveDI());
073: }
074:
075: private final Stack<Object> componentFactories = new Stack<Object>();
076:
077: private InjectionFactory injectionType;
078:
079: private Class<? extends ComponentMonitor> componentMonitorClass = NullComponentMonitor.class;
080: private Class<? extends LifecycleStrategy> lifecycleStrategyClass = NullLifecycleStrategy.class;
081:
082: public PicoBuilder withLifecycle() {
083: lifecycleStrategyClass = StartableLifecycleStrategy.class;
084: return this ;
085: }
086:
087: public PicoBuilder withReflectionLifecycle() {
088: lifecycleStrategyClass = ReflectionLifecycleStrategy.class;
089: return this ;
090: }
091:
092: public PicoBuilder withConsoleMonitor() {
093: componentMonitorClass = ConsoleComponentMonitor.class;
094: return this ;
095: }
096:
097: public PicoBuilder withMonitor(
098: Class<? extends ComponentMonitor> cmClass) {
099: if (cmClass == null) {
100: throw new NullPointerException(
101: "monitor class cannot be null");
102: }
103: if (!ComponentMonitor.class.isAssignableFrom(cmClass)) {
104: throw new ClassCastException(cmClass.getName()
105: + " is not a " + ComponentMonitor.class.getName());
106:
107: }
108: componentMonitorClass = cmClass;
109: componentMonitor = null;
110: return this ;
111: }
112:
113: public MutablePicoContainer build() {
114:
115: DefaultPicoContainer temp = new TransientPicoContainer();
116: temp.addComponent(PicoContainer.class, parentContainer);
117:
118: for (Object containerComp : containerComps) {
119: temp.addComponent(containerComp);
120: }
121:
122: ComponentFactory lastCaf = injectionType;
123: while (!componentFactories.empty()) {
124: Object componentFactory = componentFactories.pop();
125: DefaultPicoContainer temp2 = new TransientPicoContainer(
126: temp);
127: temp2.addComponent("componentFactory", componentFactory);
128: if (lastCaf != null) {
129: temp2.addComponent(ComponentFactory.class, lastCaf);
130: }
131: ComponentFactory penultimateCaf = lastCaf;
132: lastCaf = (ComponentFactory) temp2
133: .getComponent("componentFactory");
134: if (lastCaf instanceof BehaviorFactory) {
135: ((BehaviorFactory) lastCaf).wrap(penultimateCaf);
136: }
137: }
138:
139: temp.addComponent(ComponentFactory.class, lastCaf);
140: if (componentMonitorClass == null) {
141: temp.addComponent(ComponentMonitor.class, componentMonitor);
142: } else {
143: temp.addComponent(ComponentMonitor.class,
144: componentMonitorClass);
145: }
146: temp.addComponent(LifecycleStrategy.class,
147: lifecycleStrategyClass);
148: temp.addComponent("mpc", mpcClass);
149:
150: return (MutablePicoContainer) temp.getComponent("mpc");
151: }
152:
153: public PicoBuilder withHiddenImplementations() {
154: componentFactories.push(implementationHiding());
155: return this ;
156: }
157:
158: public PicoBuilder withSetterInjection() {
159: injectionType = SDI();
160: return this ;
161: }
162:
163: public PicoBuilder withAnnotatedMethodInjection() {
164: injectionType = annotatedMethodDI();
165: return this ;
166: }
167:
168: public PicoBuilder withAnnotatedFieldInjection() {
169: injectionType = annotatedFieldDI();
170: return this ;
171: }
172:
173: public PicoBuilder withConstructorInjection() {
174: injectionType = CDI();
175: return this ;
176: }
177:
178: public PicoBuilder withCaching() {
179: componentFactories.push(caching());
180: return this ;
181: }
182:
183: public PicoBuilder withComponentFactory(
184: ComponentFactory componentFactory) {
185: if (componentFactory == null) {
186: throw new NullPointerException("CAF cannot be null");
187: }
188: componentFactories.push(componentFactory);
189: return this ;
190: }
191:
192: public PicoBuilder withSynchronizing() {
193: componentFactories.push(Synchronizing.class);
194: return this ;
195: }
196:
197: public PicoBuilder withLocking() {
198: componentFactories.push(Locking.class);
199: return this ;
200: }
201:
202: public PicoBuilder withBehaviors(BehaviorFactory... factories) {
203: for (ComponentFactory componentFactory : factories) {
204: componentFactories.push(componentFactory);
205: }
206: return this ;
207: }
208:
209: public PicoBuilder implementedBy(
210: Class<? extends MutablePicoContainer> containerClass) {
211: mpcClass = containerClass;
212: return this ;
213: }
214:
215: public PicoBuilder withMonitor(ComponentMonitor componentMonitor) {
216: this .componentMonitor = componentMonitor;
217: componentMonitorClass = null;
218: return this ;
219: }
220:
221: public PicoBuilder withComponentFactory(
222: Class<? extends ComponentFactory> componentFactoryClass) {
223: componentFactories.push(componentFactoryClass);
224: return this ;
225: }
226:
227: public PicoBuilder withCustomContainerComponent(
228: Object containerDependency) {
229: containerComps.add(containerDependency);
230: return this ;
231: }
232:
233: public PicoBuilder withPropertyApplier() {
234: componentFactories.push(PropertyApplying.class);
235: return this ;
236: }
237:
238: public PicoBuilder withAutomatic() {
239: componentFactories.push(Automating.class);
240: return this ;
241: }
242:
243: public PicoBuilder withMethodInjection() {
244: componentFactories.push(new MethodInjection());
245: return this;
246: }
247: }
|