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    
049            //Instantiate Chain of ComponentFactories
050            for (ComponentFactory componentFactory : list) {
051                if (lastFactory != null && componentFactory instanceof BehaviorFactory) {
052                    ((BehaviorFactory)componentFactory).wrap(lastFactory);
053                }
054                lastFactory = componentFactory;
055            }
056    
057            return lastFactory.createComponentAdapter(componentMonitor,
058                                                      lifecycleStrategy,
059                                                      componentProperties,
060                                                      componentKey,
061                                                      componentImplementation,
062                                                      parameters);
063        }
064    
065    
066        public ComponentAdapter addComponentAdapter(ComponentMonitor componentMonitor,
067                                                    LifecycleStrategy lifecycleStrategy,
068                                                    Properties componentProperties,
069                                                    ComponentAdapter adapter) {
070            List<BehaviorFactory> list = new ArrayList<BehaviorFactory>();
071            processSynchronizing(componentProperties, list);
072            processImplementationHiding(componentProperties, list);
073            processCaching(componentProperties, adapter.getComponentImplementation(), list);
074    
075            //Instantiate Chain of ComponentFactories
076            BehaviorFactory lastFactory = null;
077            for (BehaviorFactory componentFactory : list) {
078                if (lastFactory != null) {
079                    componentFactory.wrap(lastFactory);
080                }
081                lastFactory = componentFactory;
082            }
083    
084            if (lastFactory == null) {
085                return adapter;
086            }
087    
088    
089            return lastFactory.addComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, adapter);
090        }
091    
092        public void verify(PicoContainer container) {
093        }
094    
095        public void accept(PicoVisitor visitor) {
096            visitor.visitComponentFactory(this);
097            
098        }
099    
100        protected AdaptingInjection makeInjectionFactory() {
101            return new AdaptingInjection();
102        }
103    
104        protected void processSynchronizing(Properties componentProperties, List<BehaviorFactory> list) {
105            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.SYNCHRONIZE)) {
106                list.add(new Synchronizing());
107            }
108        }
109    
110        protected void processLocking(Properties componentProperties, List<BehaviorFactory> list) {
111            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.LOCK)) {
112                list.add(new Locking());
113            }
114        }
115    
116        protected void processCaching(Properties componentProperties,
117                                           Class componentImplementation,
118                                           List<BehaviorFactory> list) {
119            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.CACHE) ||
120                componentImplementation.getAnnotation(Cache.class) != null) {
121                list.add(new Caching());
122            }
123            AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.NO_CACHE);
124        }
125    
126        protected void processImplementationHiding(Properties componentProperties,
127                                                 List<BehaviorFactory> list) {
128            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.HIDE_IMPL)) {
129                list.add(new ImplementationHiding());
130            }
131            AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.NO_HIDE_IMPL);
132        }
133    
134        protected void processPropertyApplying(Properties componentProperties,
135                                                 List<BehaviorFactory> list) {
136            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.PROPERTY_APPLYING)) {
137                list.add(new PropertyApplying());
138            }
139        }
140    
141        protected void processAutomatic(Properties componentProperties,
142                                                 List<BehaviorFactory> list) {
143            if (AbstractBehaviorFactory.removePropertiesIfPresent(componentProperties, Characteristics.AUTOMATIC)) {
144                list.add(new Automating());
145            }
146        }
147    
148    
149        public ComponentFactory wrap(ComponentFactory delegate) {
150            throw new UnsupportedOperationException();
151        }
152    }