    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    }