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     *****************************************************************************/
010    package org.picocontainer.behaviors;
011    
012    import java.io.Serializable;
013    import java.util.ArrayList;
014    import java.util.List;
015    import java.util.Properties;
016    
017    import org.picocontainer.BehaviorFactory;
018    import org.picocontainer.Characteristics;
019    import org.picocontainer.ComponentAdapter;
020    import org.picocontainer.ComponentFactory;
021    import org.picocontainer.ComponentMonitor;
022    import org.picocontainer.LifecycleStrategy;
023    import org.picocontainer.Parameter;
024    import org.picocontainer.PicoCompositionException;
025    import org.picocontainer.PicoContainer;
026    import org.picocontainer.PicoVisitor;
027    import org.picocontainer.annotations.Cache;
028    import org.picocontainer.injectors.AdaptingInjection;
029    
030    @SuppressWarnings("serial")
031    public class AdaptingBehavior implements BehaviorFactory, Serializable {
032    
033    
034        public ComponentAdapter createComponentAdapter(ComponentMonitor componentMonitor,
035                                                       LifecycleStrategy lifecycleStrategy,
036                                                       Properties componentProperties,
037                                                       Object componentKey,
038                                                       Class componentImplementation,
039                                                       Parameter... parameters) throws PicoCompositionException {
040            List<BehaviorFactory> list = new ArrayList<BehaviorFactory>();
041            ComponentFactory lastFactory = makeInjectionFactory();
042            processSynchronizing(componentProperties, list);
043            processLocking(componentProperties, list);
044            processPropertyApplying(componentProperties, list);
045            processAutomatic(componentProperties, list);
046            processImplementationHiding(componentProperties, list);
047            processCaching(componentProperties, componentImplementation, list);
048            processGuarding(componentProperties, componentImplementation, list);
049    
050            //Instantiate Chain of ComponentFactories
051            for (ComponentFactory componentFactory : list) {
052                if (lastFactory != null && componentFactory instanceof BehaviorFactory) {
053                    ((BehaviorFactory)componentFactory).wrap(lastFactory);
054                }
055                lastFactory = componentFactory;
056            }
057    
058            return lastFactory.createComponentAdapter(componentMonitor,
059                                                      lifecycleStrategy,
060                                                      componentProperties,
061                                                      componentKey,
062                                                      componentImplementation,
063                                                      parameters);
064        }
065    
066    
067        public ComponentAdapter addComponentAdapter(ComponentMonitor componentMonitor,
068                                                    LifecycleStrategy lifecycleStrategy,
069                                                    Properties componentProperties,
070                                                    ComponentAdapter adapter) {
071            List<BehaviorFactory> list = new ArrayList<BehaviorFactory>();
072            processSynchronizing(componentProperties, list);
073            processImplementationHiding(componentProperties, list);
074            processCaching(componentProperties, adapter.getComponentImplementation(), list);
075            processGuarding(componentProperties, adapter.getComponentImplementation(), list);
076    
077            //Instantiate Chain of ComponentFactories
078            BehaviorFactory lastFactory = null;
079            for (BehaviorFactory componentFactory : list) {
080                if (lastFactory != null) {
081                    componentFactory.wrap(lastFactory);
082                }
083                lastFactory = componentFactory;
084            }
085    
086            if (lastFactory == null) {
087                return adapter;
088            }
089    
090    
091            return lastFactory.addComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, adapter);
092        }
093    
094        public void verify(PicoContainer container) {
095        }
096    
097        public void accept(PicoVisitor visitor) {
098            visitor.visitComponentFactory(this);
099            
100        }
101    
102        protected AdaptingInjection makeInjectionFactory() {
103            return new AdaptingInjection();
104        }
105    
106        protected void processSynchronizing(Properties componentProperties, List<BehaviorFactory> list) {
107            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.SYNCHRONIZE)) {
108                list.add(new Synchronizing());
109            }
110        }
111    
112        protected void processLocking(Properties componentProperties, List<BehaviorFactory> list) {
113            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.LOCK)) {
114                list.add(new Locking());
115            }
116        }
117    
118        protected void processCaching(Properties componentProperties,
119                                           Class componentImplementation,
120                                           List<BehaviorFactory> list) {
121            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.CACHE) ||
122                componentImplementation.getAnnotation(Cache.class) != null) {
123                list.add(new Caching());
124            }
125            AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.NO_CACHE);
126        }
127    
128        protected void processGuarding(Properties componentProperties, Class componentImplementation, List<BehaviorFactory> list) {
129            if (AbstractBehaviorFactory.arePropertiesPresent(componentProperties, Characteristics.GUARD, false)) {
130                list.add(new Guarding());
131            }
132        }
133    
134        protected void processImplementationHiding(Properties componentProperties,
135                                                 List<BehaviorFactory> list) {
136            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.HIDE_IMPL)) {
137                list.add(new ImplementationHiding());
138            }
139            AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.NO_HIDE_IMPL);
140        }
141    
142        protected void processPropertyApplying(Properties componentProperties,
143                                                 List<BehaviorFactory> list) {
144            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.PROPERTY_APPLYING)) {
145                list.add(new PropertyApplying());
146            }
147        }
148    
149        protected void processAutomatic(Properties componentProperties,
150                                                 List<BehaviorFactory> list) {
151            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.AUTOMATIC)) {
152                list.add(new Automating());
153            }
154        }
155    
156    
157        public ComponentFactory wrap(ComponentFactory delegate) {
158            throw new UnsupportedOperationException();
159        }
160    }