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 }