View Javadoc

1   package org.apache.commons.digester3;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static java.lang.String.format;
23  import static org.apache.commons.beanutils.BeanUtils.setProperty;
24  import static org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptor;
25  
26  import java.beans.PropertyDescriptor;
27  
28  import org.apache.commons.beanutils.DynaBean;
29  import org.apache.commons.beanutils.DynaProperty;
30  import org.xml.sax.Attributes;
31  
32  /**
33   * Rule implementation that sets an individual property on the object at the top of the stack, based on attributes with
34   * specified names.
35   */
36  public class SetPropertyRule
37      extends Rule
38  {
39  
40      // ----------------------------------------------------------- Constructors
41  
42      /**
43       * Construct a "set property" rule with the specified name and value attributes.
44       * 
45       * @param name Name of the attribute that will contain the name of the property to be set
46       * @param value Name of the attribute that will contain the value to which the property should be set
47       */
48      public SetPropertyRule( String name, String value )
49      {
50          this.name = name;
51          this.value = value;
52      }
53  
54      // ----------------------------------------------------- Instance Variables
55  
56      /**
57       * The attribute that will contain the property name.
58       */
59      protected String name = null;
60  
61      /**
62       * The attribute that will contain the property value.
63       */
64      protected String value = null;
65  
66      // --------------------------------------------------------- Public Methods
67  
68      /**
69       * {@inheritDoc}
70       */
71      @Override
72      public void begin( String namespace, String name, Attributes attributes )
73          throws Exception
74      {
75          if ( attributes.getLength() == 0 )
76          {
77              return;
78          }
79  
80          // Identify the actual property name and value to be used
81          String actualName = null;
82          String actualValue = null;
83          for ( int i = 0; i < attributes.getLength(); i++ )
84          {
85              String attributeName = attributes.getLocalName( i );
86              if ( "".equals( attributeName ) )
87              {
88                  attributeName = attributes.getQName( i );
89              }
90              String value = attributes.getValue( i );
91              if ( attributeName.equals( this.name ) )
92              {
93                  actualName = value;
94              }
95              else if ( attributeName.equals( this.value ) )
96              {
97                  actualValue = value;
98              }
99          }
100 
101         // Get a reference to the top object
102         Object top = getDigester().peek();
103 
104         // Log some debugging information
105         if ( getDigester().getLogger().isDebugEnabled() )
106         {
107             getDigester().getLogger().debug( format( "[SetPropertiesRule]{%s} Set %s property %s to %s",
108                                                      getDigester().getMatch(),
109                                                      top.getClass().getName(),
110                                                      actualName,
111                                                      actualValue ) );
112         }
113 
114         // Force an exception if the property does not exist
115         // (BeanUtils.setProperty() silently returns in this case)
116         //
117         // This code should probably use PropertyUtils.isWriteable(),
118         // like SetPropertiesRule does.
119         if ( top instanceof DynaBean )
120         {
121             DynaProperty desc = ( (DynaBean) top ).getDynaClass().getDynaProperty( actualName );
122             if ( desc == null )
123             {
124                 throw new NoSuchMethodException( "Bean has no property named " + actualName );
125             }
126         }
127         else
128         /* this is a standard JavaBean */
129         {
130             PropertyDescriptor desc = getPropertyDescriptor( top, actualName );
131             if ( desc == null )
132             {
133                 throw new NoSuchMethodException( "Bean has no property named " + actualName );
134             }
135         }
136 
137         // Set the property (with conversion as necessary)
138         setProperty( top, actualName, actualValue );
139     }
140 
141     /**
142      * {@inheritDoc}
143      */
144     @Override
145     public String toString()
146     {
147         return format( "SetPropertyRule[name=%s, value=%s]", name, value );
148     }
149 
150 }