001 /******************************************************************************* 002 * Copyright (C) PicoContainer Organization. All rights reserved. 003 * --------------------------------------------------------------------------- 004 * The software in this package is published under the terms of the BSD style 005 * license a copy of which has been included with this distribution in the 006 * LICENSE.txt file. 007 ******************************************************************************/ 008 package org.picocontainer.script.groovy.nodes; 009 010 import java.util.List; 011 import java.util.Map; 012 import java.util.Properties; 013 014 import org.picocontainer.Parameter; 015 import org.picocontainer.parameters.ConstantParameter; 016 import org.picocontainer.script.NodeBuilderDecorator; 017 import org.picocontainer.classname.ClassLoadingPicoContainer; 018 import org.picocontainer.script.util.ComponentElementHelper; 019 020 /** 021 * Creates a component node 022 * 023 * @author James Strachan 024 * @author Paul Hammant 025 * @author Aslak Hellesøy 026 * @author Michael Rimov 027 * @author Mauro Talevi 028 */ 029 @SuppressWarnings("serial") 030 public class ComponentNode extends AbstractBuilderNode { 031 032 public static final String NODE_NAME = "component"; 033 034 /** 035 * Attributes 'key' 036 */ 037 public static final String KEY = "key"; 038 039 /** 040 * Class attribute. 041 */ 042 private static final String CLASS = "class"; 043 044 /** 045 * Class Name Key Attribute. 046 */ 047 private static final String CLASS_NAME_KEY = "classNameKey"; 048 049 /** 050 * Instance attribute name. 051 */ 052 private static final String INSTANCE = "instance"; 053 054 /** 055 * Parameters attribute name. 056 */ 057 private static final String PARAMETERS = "parameters"; 058 059 /** 060 * Properties attribute name. 061 */ 062 private static final String PROPERTIES = "properties"; 063 064 private final NodeBuilderDecorator decorator; 065 066 public ComponentNode(NodeBuilderDecorator decorator) { 067 super(NODE_NAME); 068 this.decorator = decorator; 069 // Supported attributes. 070 this.addAttribute(KEY).addAttribute(CLASS).addAttribute(CLASS_NAME_KEY).addAttribute(INSTANCE).addAttribute( 071 PARAMETERS).addAttribute(PROPERTIES); 072 } 073 074 /** 075 * Execute the handler for the given node builder. 076 * 077 * @param current The current node. 078 * @param attributes Map attributes specified in the groovy script for the 079 * builder node. 080 * @return Object 081 */ 082 public Object createNewNode(final Object current, final Map<String, Object> attributes) { 083 decorator.rememberComponentKey(attributes); 084 Object key = attributes.remove(KEY); 085 Object classNameKey = attributes.remove(CLASS_NAME_KEY); 086 Object classValue = attributes.remove(CLASS); 087 Object instance = attributes.remove(INSTANCE); 088 Object parameters = attributes.remove(PARAMETERS); 089 Object properties = attributes.remove(PROPERTIES); 090 091 return ComponentElementHelper.makeComponent(classNameKey, key, getParameters(parameters), classValue, 092 (ClassLoadingPicoContainer) current, instance, getProperties(properties)); 093 } 094 095 @SuppressWarnings("unchecked") 096 private static Parameter[] getParameters(Object params) { 097 if (params == null) { 098 return null; 099 } 100 101 if (params instanceof Parameter[]) { 102 return (Parameter[]) params; 103 } 104 105 if (!(params instanceof List)) { 106 throw new IllegalArgumentException("Parameters may only be of type List or Parameter Array"); 107 } 108 109 List<Parameter> list = (List<Parameter>) params; 110 111 int n = list.size(); 112 Parameter[] parameters = new Parameter[n]; 113 for (int i = 0; i < n; ++i) { 114 parameters[i] = toParameter(list.get(i)); 115 } 116 return parameters; 117 } 118 119 private static Parameter toParameter(Object obj) { 120 return obj instanceof Parameter ? (Parameter) obj : new ConstantParameter(obj); 121 } 122 123 @SuppressWarnings("unchecked") 124 private static Properties[] getProperties(Object props) { 125 if (props == null) { 126 return new Properties[0]; 127 } 128 if (!(props instanceof List)) { 129 throw new IllegalArgumentException("Properties may only be of type List"); 130 } 131 132 List<Properties> list = (List<Properties>) props; 133 return list.toArray(new Properties[list.size()]); 134 } 135 136 }