1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jelly.tags.core;
17
18 import java.util.HashMap;
19 import java.util.Map;
20
21 import org.apache.commons.beanutils.ConversionException;
22 import org.apache.commons.beanutils.Converter;
23 import org.apache.commons.beanutils.converters.BooleanConverter;
24 import org.apache.commons.beanutils.converters.ByteConverter;
25 import org.apache.commons.beanutils.converters.CharacterConverter;
26 import org.apache.commons.beanutils.converters.DoubleConverter;
27 import org.apache.commons.beanutils.converters.FloatConverter;
28 import org.apache.commons.beanutils.converters.IntegerConverter;
29 import org.apache.commons.beanutils.converters.LongConverter;
30 import org.apache.commons.beanutils.converters.ShortConverter;
31 import org.apache.commons.jelly.JellyTagException;
32 import org.apache.commons.jelly.XMLOutput;
33
34 /***
35 * An argument to a {@link NewTag} or {@link InvokeTag}.
36 * This tag MUST be enclosed within an {@link ArgTagParent}
37 * implementation.
38 *
39 * @author Rodney Waldhoff
40 * @version $Revision: 155420 $
41 */
42 public class ArgTag extends BaseClassLoaderTag {
43
44
45
46
47 public ArgTag() {
48 }
49
50
51
52
53 /***
54 * The name of the argument class or type, if any.
55 * This may be a fully specified class name or
56 * a primitive type name
57 * (<code>boolean<code>, <code>int</code>, <code>double</code>, etc.).
58 */
59 public void setType(String type) {
60 this.typeString = type;
61 }
62
63 /*** The (possibly null) value of this argument. */
64 public void setValue(Object value) {
65 this.value= value;
66 }
67
68
69
70
71 public void doTag(XMLOutput output) throws JellyTagException {
72 invokeBody(output);
73
74 Class klass = null;
75 if("boolean".equals(typeString)) {
76 klass = Boolean.TYPE;
77 assertNotNull(value);
78 } else if("byte".equals(typeString)) {
79 klass = Byte.TYPE;
80 assertNotNull(value);
81 } else if("short".equals(typeString)) {
82 klass = Short.TYPE;
83 assertNotNull(value);
84 } else if("int".equals(typeString)) {
85 klass = Integer.TYPE;
86 assertNotNull(value);
87 } else if("char".equals(typeString)) {
88 klass = Character.TYPE;
89 assertNotNull(value);
90 } else if("float".equals(typeString)) {
91 klass = Float.TYPE;
92 assertNotNull(value);
93 } else if("long".equals(typeString)) {
94 klass = Long.TYPE;
95 assertNotNull(value);
96 } else if("double".equals(typeString)) {
97 klass = Double.TYPE;
98 assertNotNull(value);
99 } else if(null != typeString) {
100 try {
101 klass = getClassLoader().loadClass(typeString);
102 } catch (ClassNotFoundException e) {
103 throw new JellyTagException(e);
104 }
105 } else if(null == value) {
106 klass = Object.class;
107 } else {
108 klass = value.getClass();
109 }
110
111 if(!isInstanceOf(klass,value)) {
112 if (klass.equals(Class.class))
113 {
114 try {
115 value = getClassLoader().loadClass((String) value);
116 } catch (ClassNotFoundException e) {
117 throw new JellyTagException(e);
118 }
119 }
120 else
121 {
122 value = convert(klass,value);
123 }
124 }
125
126 ArgTagParent parent = (ArgTagParent)findAncestorWithClass(ArgTagParent.class);
127 if(null == parent) {
128 throw new JellyTagException("This tag must be enclosed inside an ArgTagParent implementation (for example, <new> or <invoke>)" );
129 } else {
130 parent.addArgument(klass,value);
131 }
132 }
133
134
135
136
137 private void assertNotNull(Object value) throws JellyTagException {
138 if(null == value) {
139 throw new JellyTagException("A " + typeString + " instance cannot be null.");
140 }
141 }
142
143 private boolean isInstanceOf(Class klass, Object value) {
144 return (null == value || (klass.isInstance(value)));
145 }
146
147
148
149
150 /*** The name of the parameter type, if any. */
151 private String typeString;
152
153 /*** The value of the parameter, if any */
154 private Object value;
155
156
157
158
159 private static Object convert(Class klass, Object value) throws JellyTagException {
160 if(null == value) {
161 return null;
162 } else if(!klass.isInstance(value)) {
163 Converter converter = (Converter)(converterMap.get(klass));
164 if(null == converter) {
165 throw new JellyTagException("Can't convert " + value + " to " + klass);
166 } else {
167 try {
168 return converter.convert(klass,value);
169 } catch(ConversionException e) {
170 throw new JellyTagException("Can't convert " + value + " to " + klass + " (" + e.toString() + ")",e);
171 }
172 }
173 } else {
174 return value;
175 }
176
177 }
178
179 /*** My bag of converters, by target Class */
180 private static Map converterMap = new HashMap();
181
182 static {
183 {
184 Converter c = new BooleanConverter();
185 converterMap.put(Boolean.TYPE,c);
186 converterMap.put(Boolean.class,c);
187 }
188 {
189 Converter c = new CharacterConverter();
190 converterMap.put(Character.TYPE,c);
191 converterMap.put(Character.class,c);
192 }
193 {
194 Converter c = new Converter() {
195 public Object convert(Class klass, Object value) {
196 if(value instanceof Number) {
197 return new Byte(((Number)value).byteValue());
198 } else {
199 return inner.convert(klass,value);
200 }
201 }
202 private Converter inner = new ByteConverter();
203 };
204 converterMap.put(Byte.TYPE,c);
205 converterMap.put(Byte.class,c);
206 }
207 {
208 Converter c = new Converter() {
209 public Object convert(Class klass, Object value) {
210 if(value instanceof Number) {
211 return new Short(((Number)value).shortValue());
212 } else {
213 return inner.convert(klass,value);
214 }
215 }
216 private Converter inner = new ShortConverter();
217 };
218 converterMap.put(Short.TYPE,c);
219 converterMap.put(Short.class,c);
220 }
221 {
222 Converter c = new Converter() {
223 public Object convert(Class klass, Object value) {
224 if(value instanceof Number) {
225 return new Integer(((Number)value).intValue());
226 } else {
227 return inner.convert(klass,value);
228 }
229 }
230 private Converter inner = new IntegerConverter();
231 };
232 converterMap.put(Integer.TYPE,c);
233 converterMap.put(Integer.class,c);
234 }
235 {
236 Converter c = new Converter() {
237 public Object convert(Class klass, Object value) {
238 if(value instanceof Number) {
239 return new Long(((Number)value).longValue());
240 } else {
241 return inner.convert(klass,value);
242 }
243 }
244 private Converter inner = new LongConverter();
245 };
246 converterMap.put(Long.TYPE,c);
247 converterMap.put(Long.class,c);
248 }
249 {
250 Converter c = new Converter() {
251 public Object convert(Class klass, Object value) {
252 if(value instanceof Number) {
253 return new Float(((Number)value).floatValue());
254 } else {
255 return inner.convert(klass,value);
256 }
257 }
258 private Converter inner = new FloatConverter();
259 };
260 converterMap.put(Float.TYPE,c);
261 converterMap.put(Float.class,c);
262 }
263 {
264 Converter c = new Converter() {
265 public Object convert(Class klass, Object value) {
266 if(value instanceof Number) {
267 return new Double(((Number)value).doubleValue());
268 } else {
269 return inner.convert(klass,value);
270 }
271 }
272 private Converter inner = new DoubleConverter();
273 };
274 converterMap.put(Double.TYPE,c);
275 converterMap.put(Double.class,c);
276 }
277 }
278 }