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