View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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          // register converters to standard Strategies
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      // Tag interface
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          // now lets clear this introspector so that its recreated again next time
93          this.introspector = null;
94      }
95  
96      // Properties
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 &lt;parse&gt; or &lt;output&gt; tag
140      */
141     public void setVar(String var) {
142         this.var = var;
143     }
144 
145     // Implementation methods
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             // lets try load the class of this name
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 }