1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jelly.tags.betwixt;
17
18 import org.apache.commons.beanutils.ConversionException;
19 import org.apache.commons.beanutils.ConvertUtils;
20 import org.apache.commons.beanutils.Converter;
21
22 import org.apache.commons.betwixt.XMLIntrospector;
23 import org.apache.commons.betwixt.strategy.CapitalizeNameMapper;
24 import org.apache.commons.betwixt.strategy.DecapitalizeNameMapper;
25 import org.apache.commons.betwixt.strategy.HyphenatedNameMapper;
26 import org.apache.commons.betwixt.strategy.NameMapper;
27
28 import org.apache.commons.jelly.JellyTagException;
29 import org.apache.commons.jelly.MissingAttributeException;
30 import org.apache.commons.jelly.TagSupport;
31 import org.apache.commons.jelly.XMLOutput;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 /***
36 * Creates a Betwixt XMLIntrospector instance that can be used by the other Betwixt tags.</p>
37 *
38 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
39 * @version $Revision: 155420 $
40 */
41 public class IntrospectorTag extends TagSupport {
42
43 /*** The Log to which logging calls will be made. */
44 private static final Log log = LogFactory.getLog(IntrospectorTag.class);
45
46 private XMLIntrospector introspector;
47 private String var;
48
49 static {
50
51
52 ConvertUtils.register(
53 new Converter() {
54 public Object convert(Class type, Object value) {
55 if ( value instanceof String ) {
56 return createNameMapper((String) value);
57 }
58 else if ( value == null ) {
59 return null;
60 }
61 else {
62 throw new ConversionException(
63 "Don't know how to convert: " + value
64 + " of type: " + value.getClass().getName()
65 + " into a NameMapper"
66 );
67 }
68 }
69 },
70 NameMapper.class
71 );
72 }
73
74
75
76 public IntrospectorTag() {
77 }
78
79
80
81 public void doTag(final XMLOutput output) throws MissingAttributeException, JellyTagException {
82
83 if ( var == null ) {
84 throw new MissingAttributeException( "var" );
85 }
86 invokeBody(output);
87
88 XMLIntrospector introspector = getIntrospector();
89
90 context.setVariable( var, introspector );
91
92
93 this.introspector = null;
94 }
95
96
97
98
99 /***
100 * @return the current XMLIntrospector, lazily creating one if required
101 */
102 public XMLIntrospector getIntrospector() {
103 if ( introspector == null ) {
104 introspector = createIntrospector();
105 }
106 return introspector;
107 }
108
109 /***
110 * Sets whether attributes or elements should be used for primitive types.
111 * The default is false.
112 */
113 public void setAttributesForPrimitives(boolean attributesForPrimitives) {
114 getIntrospector().setAttributesForPrimitives(attributesForPrimitives);
115 }
116
117 /***
118 * Sets the name mapper used for element names.
119 * You can also use the Strings 'lowercase', 'uppercase' or 'hyphenated'
120 * as aliases to the common name mapping strategies or specify a class name String.
121 */
122 public void setElementNameMapper(NameMapper nameMapper) {
123 getIntrospector().setElementNameMapper(nameMapper);
124 }
125
126 /***
127 * Sets the name mapper used for attribute names.
128 * You can also use the Strings 'lowercase', 'uppercase' or 'hyphenated'
129 * as aliases to the common name mapping strategies or specify a class name String.
130 */
131 public void setAttributeNameMapper(NameMapper nameMapper) {
132 getIntrospector().setAttributeNameMapper(nameMapper);
133 }
134
135
136 /***
137 * Sets the variable name to output the new XMLIntrospector to.
138 * If this attribute is not specified then this tag must be nested
139 * inside an <parse> or <output> tag
140 */
141 public void setVar(String var) {
142 this.var = var;
143 }
144
145
146
147
148 /***
149 * Static helper method which will convert the given string into
150 * standard named strategies such as 'lowercase', 'uppercase' or 'hyphenated'
151 * or use the name as a class name and create a new instance.
152 */
153 protected static NameMapper createNameMapper(String name) {
154 if ( name.equalsIgnoreCase( "lowercase" ) ) {
155 return new DecapitalizeNameMapper();
156 }
157 else if ( name.equalsIgnoreCase( "uppercase" ) ) {
158 return new CapitalizeNameMapper();
159 }
160 else if ( name.equalsIgnoreCase( "hyphenated" ) ) {
161 return new HyphenatedNameMapper();
162 }
163 else {
164
165 Class theClass = null;
166 try {
167 theClass = Thread.currentThread().getContextClassLoader().loadClass( name );
168 }
169 catch (Exception e) {
170 throw new ConversionException( "Could not load class called: " + name, e );
171 }
172
173 Object object = null;
174 try {
175 object = theClass.newInstance();
176 }
177 catch (Exception e) {
178 throw new ConversionException( "Could not instantiate an instance of: " + name, e );
179 }
180 if ( object instanceof NameMapper ) {
181 return (NameMapper) object;
182 }
183 if ( object == null ) {
184 throw new ConversionException( "No NameMapper created for type: " + name );
185 }
186 else {
187 throw new ConversionException(
188 "Created object: " + object
189 + " is not a NameMapper! Its type is: " + object.getClass().getName()
190 );
191 }
192 }
193 }
194
195 /***
196 * Factory method to create a new XMLIntrospector
197 */
198 protected XMLIntrospector createIntrospector() {
199 return new XMLIntrospector();
200 }
201 }