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 * component(....)
032 * //...
033 * }
034 * <br/>
035 * //<em>Now add more to pico.</em>
036 * builder.append(container: pico) {
037 * component(....)
038 * //...
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 "container" 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 }