1 10 package org.nanocontainer.script.groovy; 11 12 import groovy.lang.Closure; 13 import groovy.lang.GroovyObject; 14 import groovy.util.BuilderSupport; 15 import org.codehaus.groovy.runtime.InvokerHelper; 16 import org.nanocontainer.DefaultNanoContainer; 17 import org.nanocontainer.NanoContainer; 18 import org.nanocontainer.script.NanoContainerMarkupException; 19 import org.nanocontainer.script.NodeBuilderDecorationDelegate; 20 import org.nanocontainer.script.NullNodeBuilderDecorationDelegate; 21 import org.nanocontainer.script.groovy.buildernodes.*; 22 import org.picocontainer.MutablePicoContainer; 23 24 import java.util.Collections ; 25 import java.util.HashMap ; 26 import java.util.List ; 27 import java.util.Map ; 28 29 61 public class GroovyNodeBuilder extends BuilderSupport { 62 63 private static final String CLASS = "class"; 64 65 private static final String PARENT = "parent"; 66 67 68 71 public static boolean PERFORM_ATTRIBUTE_VALIDATION = true; 72 73 74 77 public static boolean SKIP_ATTRIBUTE_VALIDATION = false; 78 79 80 84 private final NodeBuilderDecorationDelegate decorationDelegate; 85 86 89 private Map nodeBuilderHandlers = new HashMap (); 90 private Map nodeBuilders = new HashMap (); 91 92 private final boolean performAttributeValidation; 93 94 95 105 public GroovyNodeBuilder(NodeBuilderDecorationDelegate decorationDelegate, boolean performAttributeValidation) { 106 this.decorationDelegate = decorationDelegate; 107 this.performAttributeValidation = performAttributeValidation; 108 109 this.setNode(new ComponentNode(decorationDelegate)) 111 .setNode(new ChildContainerNode(decorationDelegate)) 112 .setNode(new BeanNode()) 113 .setNode(new ClasspathNode()) 114 .setNode(new DoCallNode()) 115 .setNode(new NewBuilderNode()) 116 .setNode(new ClassLoaderNode()) 117 .setNode(new DecoratingPicoContainerNode()) 118 .setNode(new GrantNode()) 119 .setNode(new AppendContainerNode()); 120 NanoContainer factory = new DefaultNanoContainer(); 121 try { 122 factory.registerComponentImplementation("wc", "org.nanocontainer.webcontainer.groovy.WebContainerBuilder"); 123 setNode((BuilderNode) factory.getPico().getComponentInstance("wc")); 124 } catch (ClassNotFoundException cnfe) { 125 } 126 127 } 128 129 132 public GroovyNodeBuilder() { 133 this(new NullNodeBuilderDecorationDelegate(), SKIP_ATTRIBUTE_VALIDATION); 134 } 135 136 137 protected void setParent(Object parent, Object child) { 138 } 139 140 protected Object doInvokeMethod(String s, Object name, Object args) { 141 Object answer = super.doInvokeMethod(s, name, args); 143 List list = InvokerHelper.asList(args); 144 if (!list.isEmpty()) { 145 Object o = list.get(list.size() - 1); 146 if (o instanceof Closure) { 147 Closure closure = (Closure) o; 148 closure.setDelegate(answer); 149 } 150 } 151 return answer; 152 } 153 154 protected Object createNode(Object name) { 155 return createNode(name, Collections.EMPTY_MAP); 156 } 157 158 protected Object createNode(Object name, Object value) { 159 Map attributes = new HashMap (); 160 attributes.put(CLASS, value); 161 return createNode(name, attributes); 162 } 163 164 175 protected Object createNode(Object name, Map attributes, Object value) { 176 Object current = getCurrent(); 177 if (current != null && current instanceof GroovyObject) { 178 GroovyObject groovyObject = (GroovyObject) current; 179 return groovyObject.invokeMethod(name.toString(), attributes); 180 } else if (current == null) { 181 current = extractOrCreateValidRootNanoContainer(attributes); 182 } else { 183 if (attributes.containsKey(PARENT)) { 184 throw new NanoContainerMarkupException("You can't explicitly specify a parent in a child element."); 185 } 186 } 187 if (name.equals("registerBuilder")) { 188 return registerBuilder(attributes); 189 190 } else { 191 return handleNode(name, attributes, current); 192 } 193 194 } 195 196 private Object registerBuilder(Map attributes) { 197 String builderName = (String ) attributes.remove("name"); 198 Object clazz = attributes.remove("class"); 199 try { 200 if (clazz instanceof String ) { 201 clazz = this.getClass().getClassLoader().loadClass((String ) clazz); 202 } 203 } catch (ClassNotFoundException e) { 204 throw new NanoContainerMarkupException("ClassNotFoundException " + clazz); 205 } 206 nodeBuilders.put(builderName, clazz); 207 return clazz; 208 } 209 210 private Object handleNode(Object name, Map attributes, Object current) { 211 212 attributes = new HashMap (attributes); 213 214 BuilderNode nodeHandler = this.getNode(name.toString()); 215 216 if (nodeHandler == null) { 217 Class builderClass = (Class ) nodeBuilders.get(name); 218 if (builderClass != null) { 219 nodeHandler = this.getNode("newBuilder"); 220 attributes.put("class",builderClass); 221 } 222 } 223 224 if (nodeHandler == null) { 225 return getDecorationDelegate().createNode(name, attributes, current); 227 228 } else { 229 231 if (performAttributeValidation) { 232 nodeHandler.validateScriptedAttributes(attributes); 234 } 235 236 return nodeHandler.createNewNode(current, attributes); 237 } 238 } 239 240 248 private NanoContainer extractOrCreateValidRootNanoContainer(final Map attributes) throws NanoContainerMarkupException { 249 Object parentAttribute = attributes.get(PARENT); 250 if (parentAttribute instanceof NanoContainer) { 255 return (NanoContainer) parentAttribute; 257 } 258 if (parentAttribute instanceof MutablePicoContainer) { 259 return new DefaultNanoContainer((MutablePicoContainer) parentAttribute); 261 } 262 return null; 263 } 264 265 266 271 public NodeBuilderDecorationDelegate getDecorationDelegate() { 272 return this.decorationDelegate; 273 } 274 275 276 284 public synchronized BuilderNode getNode(final String tagName) { 285 Object o = nodeBuilderHandlers.get(tagName); 286 return (BuilderNode) o; 287 } 288 289 297 public synchronized GroovyNodeBuilder setNode(final BuilderNode newGroovyNode) { 298 nodeBuilderHandlers.put(newGroovyNode.getNodeName(), newGroovyNode); 299 return this; 300 } 301 302 protected Object createNode(Object name, Map attributes) { 303 return createNode(name, attributes, null); 304 } 305 306 307 } 308 | Popular Tags |