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 }