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 *****************************************************************************/
010package org.picocontainer.behaviors;
011
012import java.io.Serializable;
013import java.util.ArrayList;
014import java.util.List;
015import java.util.Properties;
016
017import org.picocontainer.BehaviorFactory;
018import org.picocontainer.Characteristics;
019import org.picocontainer.ComponentAdapter;
020import org.picocontainer.ComponentFactory;
021import org.picocontainer.ComponentMonitor;
022import org.picocontainer.LifecycleStrategy;
023import org.picocontainer.Parameter;
024import org.picocontainer.PicoCompositionException;
025import org.picocontainer.PicoContainer;
026import org.picocontainer.PicoVisitor;
027import org.picocontainer.annotations.Cache;
028import org.picocontainer.injectors.AdaptingInjection;
029
030@SuppressWarnings("serial")
031public 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}