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 *****************************************************************************/
010package org.picocontainer;
011
012import org.picocontainer.lifecycle.LifecycleState;
013
014import 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 */
025public 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}