001    /*****************************************************************************
002     * Copyright (C) NanoContainer 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 Michael Rimov                                            *
009     *****************************************************************************/
010    
011    
012    package org.nanocontainer.script.groovy.buildernodes;
013    
014    import java.util.Map;
015    import org.nanocontainer.NanoContainer;
016    import org.nanocontainer.script.NanoContainerMarkupException;
017    import org.picocontainer.PicoContainer;
018    
019    /**
020     * Sometimes it is worthwhile to split apart Nanocontainer building
021     * into functions.  For example, you might want to group adding the domain
022     * object repositories (DAOs) into a single function to make your composition script
023     * easier to maintain.
024     * <p>Unfortunately, normally this is not allowed under normal builder rules.  If
025     * you wish to separate code you must revert to standard picocontainer calling
026     * systax.</p>
027     * <p>This node corrects that deficiency.</p>
028     * <p>With it you can perform:
029     * <code><pre>
030     * pico = builder.container(parent:parent) {
031     * &nbsp;&nbsp;component(....)
032     * &nbsp;&nbsp;//...
033     * }
034     * <br/>
035     * //<em>Now add more to pico.</em>
036     * builder.append(container: pico) {
037     * &nbsp;&nbsp;component(....)
038     * &nbsp;&nbsp;//...
039     * }
040     * </pre></code>
041     * </p>
042     * @author Michael Rimov
043     * @version 1.0
044     */
045    public class AppendContainerNode extends AbstractBuilderNode {
046        /**
047         * Node name.
048         */
049        public static final String NODE_NAME = "append";
050    
051    
052        /**
053         * Supported Attribute (Required): 'container.'  Reference to the container
054         * we are going to append to.
055         */
056        public static final String CONTAINER = "container";
057    
058        /**
059         * Constructs an append container node.
060         */
061        public AppendContainerNode() {
062            super(NODE_NAME);
063        }
064    
065        /**
066         * Returns the container passed in as the &quot;container&quot; attribute.
067         * @param current Object unused.
068         * @param attributes Map attributes passed in.  This must have the container
069         * attribute defined.
070         * @return Object the passed in Nanocontainer.
071         * @throws NanoContainerMarkupException if the container attribute
072         * is not supplied.
073         * @throws ClassCastException if the container node specified is  not
074         * a nano or picocontainer.
075         */
076        public Object createNewNode(final Object current, final Map attributes) throws NanoContainerMarkupException, ClassCastException {
077            if (!isAttribute(attributes, CONTAINER)) {
078                throw new NanoContainerMarkupException(NODE_NAME + " must have a container attribute");
079            }
080    
081    
082            Object attributeValue = attributes.get(CONTAINER);
083            if (! (attributeValue instanceof NanoContainer) && !(attributeValue instanceof PicoContainer) ) {
084                throw new ClassCastException(attributeValue.toString() + " must be a derivative of nanocontainer.  Got: "
085                    + attributeValue.getClass().getName() + " instead.");
086            }
087            return attributeValue;
088        }
089    
090    
091    }