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.impl;
17  
18  import java.util.HashSet;
19  import java.util.Iterator;
20  import java.util.Map;
21  import java.util.Set;
22  
23  import org.apache.commons.beanutils.DynaClass;
24  import org.apache.commons.jelly.DynaBeanTagSupport;
25  import org.apache.commons.jelly.JellyTagException;
26  import org.apache.commons.jelly.MissingAttributeException;
27  import org.apache.commons.jelly.XMLOutput;
28  import org.apache.commons.jelly.expression.Expression;
29  
30  /***
31   * This tag is bound onto a {@link DynaClass} instance.
32   * When the tag is invoked a {@link DynaBean will be created using the tags attributes.
33   * So this class is like a {@link DynaBean} implemenation of {@link DynamicBeanTag}
34   *
35   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
36   * @version $Revision: 155420 $
37   */
38  public class DynamicDynaBeanTag extends DynaBeanTagSupport implements BeanSource {
39  
40      /*** the bean class */
41      private DynaClass beanClass;
42  
43      /***
44       * the tag attribute name that is used to declare the name
45       * of the variable to export after running this tag
46       */
47      private String variableNameAttribute;
48  
49      /*** the current variable name that the bean should be exported as */
50      private String var;
51  
52      /*** the set of attribute names we've already set */
53      private Set setAttributesSet = new HashSet();
54  
55      /*** the attribute definitions */
56      private Map attributes;
57  
58      public DynamicDynaBeanTag(DynaClass beanClass, Map attributes, String variableNameAttribute) {
59          this.beanClass = beanClass;
60          this.attributes = attributes;
61          this.variableNameAttribute = variableNameAttribute;
62      }
63  
64      public void beforeSetAttributes() throws JellyTagException {
65          // create a new dynabean before the attributes are set
66          try {
67              setDynaBean( beanClass.newInstance() );
68          } catch (IllegalAccessException e) {
69              throw new JellyTagException("Could not instantiate dynabean",e);
70          } catch (InstantiationException e) {
71              throw new JellyTagException("Could not instantiate dynabean",e);
72          }
73  
74          setAttributesSet.clear();
75      }
76  
77      public void setAttribute(String name, Object value) throws JellyTagException {
78          boolean isVariableName = false;
79          if (variableNameAttribute != null ) {
80              if ( variableNameAttribute.equals( name ) ) {
81                  if (value == null) {
82                      var = null;
83                  }
84                  else {
85                      var = value.toString();
86                  }
87                  isVariableName = true;
88              }
89          }
90          if (! isVariableName) {
91  
92              // #### strictly speaking we could
93              // know what attributes are specified at compile time
94              // so this dynamic set is unnecessary
95              setAttributesSet.add(name);
96  
97              // we could maybe implement attribute specific validation here
98  
99              super.setAttribute(name, value);
100         }
101     }
102 
103     // Tag interface
104     //-------------------------------------------------------------------------
105     public void doTag(XMLOutput output) throws JellyTagException {
106 
107         // lets find any attributes that are not set and
108         for ( Iterator iter = attributes.values().iterator(); iter.hasNext(); ) {
109             Attribute attribute = (Attribute) iter.next();
110             String name = attribute.getName();
111             if ( ! setAttributesSet.contains( name ) ) {
112                 if ( attribute.isRequired() ) {
113                     throw new MissingAttributeException(name);
114                 }
115                 // lets get the default value
116                 Object value = null;
117                 Expression expression = attribute.getDefaultValue();
118                 if ( expression != null ) {
119                     value = expression.evaluate(context);
120                 }
121 
122                 // only set non-null values?
123                 if ( value != null ) {
124                     super.setAttribute(name, value);
125                 }
126             }
127         }
128 
129         invokeBody(output);
130 
131         // export the bean if required
132         if ( var != null ) {
133             context.setVariable(var, getDynaBean());
134         }
135     }
136 
137     // Properties
138     //-------------------------------------------------------------------------
139     /***
140      * @return the bean that has just been created
141      */
142     public Object getBean() {
143         return getDynaBean();
144     }
145 }