Package org.nanocontainer.script.groovy.buildernodes

Source Code of org.nanocontainer.script.groovy.buildernodes.ChildContainerNode

/*****************************************************************************
* Copyright (C) NanoContainer Organization. All rights reserved.            *
* ------------------------------------------------------------------------- *
* The software in this package is published under the terms of the BSD      *
* style license a copy of which has been included with this distribution in *
* the LICENSE.txt file.                                                     *
*                                                                           *
* Original code by James Strachan                                           *
*****************************************************************************/

package org.nanocontainer.script.groovy.buildernodes;

import java.util.Map;
import org.nanocontainer.NanoContainer;
import org.nanocontainer.script.NanoContainerMarkupException;
import org.picocontainer.defaults.DefaultPicoContainer;
import java.security.PrivilegedAction;
import org.picocontainer.defaults.ComponentAdapterFactory;
import java.security.AccessController;
import org.picocontainer.defaults.DefaultComponentAdapterFactory;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.PicoContainer;
import org.nanocontainer.DefaultNanoContainer;
import org.nanocontainer.script.NodeBuilderDecorationDelegate;
import org.picocontainer.ComponentMonitor;
import org.picocontainer.defaults.DelegatingComponentMonitor;
import org.picocontainer.defaults.ComponentMonitorStrategy;

/**
* Creates a new NanoContainer node.  There may or may not be a parent
* container involved.
* @author James Strachan
* @author Paul Hammant
* @author Aslak Hellesøy
* @author Michael Rimov
* @author Mauro Talevi
* @version $Revision: 2695 $
*/
public class ChildContainerNode extends AbstractCustomBuilderNode {

    /**
     * Node name.
     */
    public static final String NODE_NAME = "container";

    /**
     * Supported Attribute: 'class'  Reference to a classname of the container
     * to use.
     */
    private static final String CLASS = "class";

    /**
     * The node decoration delegate.
     */
    private final NodeBuilderDecorationDelegate decorationDelegate;

    /**
     * Attribute: 'componentAdapterFactory' a reference to an instance of a
     * component adapter factory.
     */
    private static final String COMPONENT_ADAPTER_FACTORY = "componentAdapterFactory";

    /**
     * Attribute: 'componentMonitor' a reference to an instance of a component monitor.
     */
    private static final String COMPONENT_MONITOR = "componentMonitor";


    /**
     * Attribute that exists in test cases, but not necessarily used?
     *
     */
    private static final String SCOPE = "scope";


    /**
     * Attribute: 'parent'  a reference to the parent for this new container.
     */
    private static final String PARENT = "parent";


    /**
     * Constructs a child container node.  It requires a <tt>NodeBuilderDecorationDelegate</tt>
     * for construction.
     * @param delegate NodeBuilderDecorationDelegate
     */
    public ChildContainerNode(NodeBuilderDecorationDelegate delegate) {
        super(NODE_NAME);
        decorationDelegate = delegate;

        this.addAttribute(CLASS)
            .addAttribute(COMPONENT_ADAPTER_FACTORY)
            .addAttribute(COMPONENT_MONITOR)
            .addAttribute(PARENT)
            .addAttribute(SCOPE);


    }

    /**
     * Creates a new container.  There may or may not be a parent to this container.
     * Supported attributes are
     * <p>{@inheritDoc}</p>
     * @param parentContainer NanoContainer
     * @param attributes Map
     * @return Object
     * @throws ClassNotFoundException
     * @throws NanoContainerMarkupException
     */
    public Object createNewNode(NanoContainer parentContainer, Map attributes) throws ClassNotFoundException,
        NanoContainerMarkupException {

        return createChildContainer(attributes,parentContainer);
    }

    /**
     * Retrieve the decoration delegate.
     * @return NodeBuilderDecorationDelegate
     */
    private NodeBuilderDecorationDelegate getDecorationDelegate() {
        return decorationDelegate;
    }



    /**
     * Creates a new container.  There may or may not be a parent to this container.
     * Supported attributes are:
     * <ul>
     <li><tt>componentAdapterFactory</tt>: The ComponentAdapterFactory used for new container</li>
     <li><tt>componentMonitor</tt>: The ComponentMonitor used for new container</li>
     * </ul>
     * @param attributes Map Attributes defined by the builder in the script.
     * @param parent The parent container
     * @return The NanoContainer
     */
    protected NanoContainer createChildContainer(Map attributes, NanoContainer parent) {

        ClassLoader parentClassLoader = null;
        MutablePicoContainer childContainer = null;
        if (parent != null) {
            parentClassLoader = parent.getComponentClassLoader();
            if ( isAttribute(attributes, COMPONENT_ADAPTER_FACTORY) ) {
                ComponentAdapterFactory componentAdapterFactory = createComponentAdapterFactory(attributes);
                childContainer = new DefaultPicoContainer(
                        getDecorationDelegate().decorate(componentAdapterFactory, attributes), parent.getPico());
                if ( isAttribute(attributes, COMPONENT_MONITOR) ) {
                    changeComponentMonitor(childContainer, createComponentMonitor(attributes));
                }
                parent.getPico().addChildContainer(childContainer);
            } else if ( isAttribute(attributes, COMPONENT_MONITOR) ) {
                ComponentAdapterFactory componentAdapterFactory = new DefaultComponentAdapterFactory(
                                                    createComponentMonitor(attributes));
                childContainer = new DefaultPicoContainer(
                        getDecorationDelegate().decorate(componentAdapterFactory, attributes), parent.getPico());
            } else {
                childContainer = parent.getPico().makeChildContainer();
            }
        } else {
            parentClassLoader = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    return PicoContainer.class.getClassLoader();
                }
            });
            ComponentAdapterFactory componentAdapterFactory = createComponentAdapterFactory(attributes);
            childContainer = new DefaultPicoContainer(
                    getDecorationDelegate().decorate(componentAdapterFactory, attributes));
            if ( isAttribute(attributes, COMPONENT_MONITOR) ) {
                changeComponentMonitor(childContainer, createComponentMonitor(attributes));
            }
        }

        MutablePicoContainer decoratedPico = getDecorationDelegate().decorate(childContainer);
        if ( isAttribute(attributes, CLASS) )  {
            Class clazz = (Class) attributes.get(CLASS);
            return createNanoContainer(clazz, decoratedPico, parentClassLoader);
        } else {
            return new DefaultNanoContainer(parentClassLoader, decoratedPico);
        }
    }

    private void changeComponentMonitor(MutablePicoContainer childContainer, ComponentMonitor monitor) {
        if ( childContainer instanceof ComponentMonitorStrategy ){
            ((ComponentMonitorStrategy)childContainer).changeMonitor(monitor);
        }
    }

    private NanoContainer createNanoContainer(Class clazz, MutablePicoContainer decoratedPico, ClassLoader parentClassLoader) {
        DefaultPicoContainer instantiatingContainer = new DefaultPicoContainer();
        instantiatingContainer.registerComponentInstance(ClassLoader.class, parentClassLoader);
        instantiatingContainer.registerComponentInstance(MutablePicoContainer.class, decoratedPico);
        instantiatingContainer.registerComponentImplementation(NanoContainer.class, clazz);
        Object componentInstance = instantiatingContainer.getComponentInstance(NanoContainer.class);
        return (NanoContainer) componentInstance;
    }

    private ComponentAdapterFactory createComponentAdapterFactory(Map attributes) {
        final ComponentAdapterFactory factory = (ComponentAdapterFactory) attributes.remove(COMPONENT_ADAPTER_FACTORY);
        if ( factory == null ){
            return new DefaultComponentAdapterFactory();
        }
        return factory;
    }

    private ComponentMonitor createComponentMonitor(Map attributes) {
        final ComponentMonitor monitor = (ComponentMonitor) attributes.remove(COMPONENT_MONITOR);
        if ( monitor == null ){
            return new DelegatingComponentMonitor();
        }
        return monitor;
    }


}
TOP

Related Classes of org.nanocontainer.script.groovy.buildernodes.ChildContainerNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.