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     * Idea by Rachel Davies, Original code by various                           *
009     *****************************************************************************/
010    package org.picocontainer;
011    
012    import org.picocontainer.lifecycle.LifecycleState;
013    
014    import java.util.Properties;
015    
016    /**
017     * This is the core interface used for registration of components with a container. It is possible to register
018     * implementations and instances here
019     *
020     * @author Paul Hammant
021     * @author Aslak Hellesøy
022     * @author Jon Tirsén
023     * @see <a href="package-summary.html#package_description">See package description for basic overview how to use PicoContainer.</a>
024     */
025    public interface MutablePicoContainer extends PicoContainer, Startable, Disposable {
026    
027        /**
028         * Register a component and creates specific instructions on which constructor to use, along with
029         * which components and/or constants to provide as constructor arguments.  These &quot;directives&quot; are
030         * provided through an array of <tt>Parameter</tt> objects.  Parameter[0] correspondes to the first constructor
031         * argument, Parameter[N] corresponds to the  N+1th constructor argument.
032         * <h4>Tips for Parameter usage</h4>
033         * <ul>
034         * <li><strong>Partial Autowiring: </strong>If you have two constructor args to match and you only wish to specify one of the constructors and
035         * let PicoContainer wire the other one, you can use as parameters:
036         * <code><strong>new ComponentParameter()</strong>, new ComponentParameter("someService")</code>
037         * The default constructor for the component parameter indicates auto-wiring should take place for
038         * that parameter.
039         * </li>
040         * <li><strong>Force No-Arg constructor usage:</strong> If you wish to force a component to be constructed with
041         * the no-arg constructor, use a zero length Parameter array.  Ex:  <code>new Parameter[0]</code>
042         * <ul>
043         *
044         * @param componentKey a key that identifies the component. Must be unique within the container. The type
045         *                     of the key object has no semantic significance unless explicitly specified in the
046         *                     documentation of the implementing container.
047         * @param componentImplementationOrInstance
048         *                     the component's implementation class. This must be a concrete class (ie, a
049         *                     class that can be instantiated). Or an intance of the compoent.
050         * @param parameters   the parameters that gives the container hints about what arguments to pass
051         *                     to the constructor when it is instantiated. Container implementations may ignore
052         *                     one or more of these hints.
053         *
054         * @return the same instance of MutablePicoContainer
055         *
056         * @throws PicoCompositionException if registration of the component fails.
057         * @see org.picocontainer.Parameter
058         * @see org.picocontainer.parameters.ConstantParameter
059         * @see org.picocontainer.parameters.ComponentParameter
060         */
061        MutablePicoContainer addComponent(Object componentKey,
062                                          Object componentImplementationOrInstance,
063                                          Parameter... parameters);
064    
065        /**
066         * Register an arbitrary object. The class of the object will be used as a key. Calling this method is equivalent to
067         * calling  <code>addComponent(componentImplementation, componentImplementation)</code>.
068         *
069         * @param implOrInstance Component implementation or instance
070         *
071         * @return the same instance of MutablePicoContainer
072         *
073         * @throws PicoCompositionException if registration fails.
074         */
075        MutablePicoContainer addComponent(Object implOrInstance);
076    
077        /**
078         * Register a config item.
079         *
080         * @param name the name of the config item
081         * @param val the value of the config item
082         *
083         * @return the same instance of MutablePicoContainer
084         *
085         * @throws PicoCompositionException if registration fails.
086         */
087        MutablePicoContainer addConfig(String name, Object val);
088    
089        /**
090         * Register a component via a ComponentAdapter. Use this if you need fine grained control over what
091         * ComponentAdapter to use for a specific component.  The adapter will be wrapped in whatever behaviors that the 
092         * the container has been set up with.  If you want to bypass that behavior for the adapter you are adding, 
093         * you should use Characteristics.NONE like so pico.as(Characteristics.NONE).addAdapter(...)
094         *
095         * @param componentAdapter the adapter
096         *
097         * @return the same instance of MutablePicoContainer
098         *
099         * @throws PicoCompositionException if registration fails.
100         */
101        MutablePicoContainer addAdapter(ComponentAdapter<?> componentAdapter);
102    
103        /**
104         * Unregister a component by key.
105         *
106         * @param componentKey key of the component to unregister.
107         *
108         * @return the ComponentAdapter that was associated with this component.
109         */
110        <T> ComponentAdapter<T> removeComponent(Object componentKey);
111    
112        /**
113         * Unregister a component by instance.
114         *
115         * @param componentInstance the component instance to unregister.
116         *
117         * @return the same instance of MutablePicoContainer
118         */
119        <T> ComponentAdapter<T> removeComponentByInstance(T componentInstance);
120    
121        /**
122         * Make a child container, using both the same implementation of MutablePicoContainer as the parent
123         * and identical behaviors as well.
124         * It will have a reference to this as parent.  This will list the resulting MPC as a child.
125         * Lifecycle events will be cascaded from parent to child
126         * as a consequence of this.  
127         * <p>Note that for long-lived parent containers, you need to unregister child containers
128         * made with this call before disposing or you will leak memory.  <em>(Experience
129         * speaking here! )</em></p>
130         * <p>Incorrect Example:</p>
131         * <pre>
132         *   MutablePicoContainer parent = new PicoBuilder().withCaching().withLifecycle().build();
133         *   MutablePicoContainer child = parent.makeChildContainer();
134         *   child = null; //Child still retains in memory because parent still holds reference.
135         * </pre>
136         * <p>Correct Example:</p>
137         * <pre>
138         *   MutablePicoContainer parent = new PicoBuilder().withCaching().withLifecycle().build();
139         *   MutablePicoContainer child = parent.makeChildContainer();
140         *   parent.removeChildContainer(child); //Remove the bi-directional references.
141         *   child = null; 
142         * </pre>
143         * @return the new child container.
144         */
145        MutablePicoContainer makeChildContainer();
146    
147        /**
148         * Add a child container. This action will list the the 'child' as exactly that in the parents scope.
149         * It will not change the child's view of a parent.  That is determined by the constructor arguments of the child
150         * itself. Lifecycle events will be cascaded from parent to child
151         * as a consequence of calling this method.
152         *
153         * @param child the child container
154         *
155         * @return the same instance of MutablePicoContainer
156         *
157         */
158        MutablePicoContainer addChildContainer(PicoContainer child);
159    
160        /**
161         * Remove a child container from this container. It will not change the child's view of a parent.
162         * Lifecycle event will no longer be cascaded from the parent to the child.
163         *
164         * @param child the child container
165         *
166         * @return <code>true</code> if the child container has been removed.
167         *
168         */
169        boolean removeChildContainer(PicoContainer child);
170    
171    
172        /**
173         * You can change the characteristic of registration of all subsequent components in this container.
174         *
175         * @param properties
176         * @return the same Pico instance with changed properties
177         */
178        MutablePicoContainer change(Properties... properties);
179    
180        /**
181         * You can set for the following operation only the characteristic of registration of a component on the fly.
182         *
183         * @param properties
184         * @return the same Pico instance with temporary properties
185         */
186        MutablePicoContainer as(Properties... properties);
187    
188        /**
189         * Name the container instance, to assist debugging or other indexing.
190         *
191         * @param name the name to call it.
192         * @since 2.8
193         */
194        void setName(String name);
195    
196        /**
197         * To assist ThreadLocal usage, LifecycleState can be set.  No need to use this for normal usages.
198         * @param lifecycleState the lifecyle state to use.
199         * @since 2.8
200         */
201        void setLifecycleState(LifecycleState lifecycleState);
202        
203        
204        /**
205         * Retrieve the name set (if any).
206         * @return Retrieve the arbitrary name of the container set by calling {@link #setName(String) setName}.
207         * @since 2.10.2
208         */
209        String getName();
210        
211        
212        /**
213         * Allow querying of the current lifecycle state of a MutablePicoContainer.
214         * @return the current Lifecycle State.
215         * @since 2.10.2
216         */
217        LifecycleState getLifecycleState();
218    }