001 /* $Id: SetPropertyRule.java 992060 2010-09-02 19:09:47Z simonetripodi $
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019
020 package org.apache.commons.digester;
021
022
023 import java.beans.PropertyDescriptor;
024
025 import org.apache.commons.beanutils.BeanUtils;
026 import org.apache.commons.beanutils.DynaBean;
027 import org.apache.commons.beanutils.DynaProperty;
028 import org.apache.commons.beanutils.PropertyUtils;
029 import org.xml.sax.Attributes;
030
031
032 /**
033 * Rule implementation that sets an individual property on the object at the
034 * top of the stack, based on attributes with specified names.
035 */
036
037 public class SetPropertyRule extends Rule {
038
039
040 // ----------------------------------------------------------- Constructors
041
042
043 /**
044 * Construct a "set property" rule with the specified name and value
045 * attributes.
046 *
047 * @param digester The digester with which this rule is associated
048 * @param name Name of the attribute that will contain the name of the
049 * property to be set
050 * @param value Name of the attribute that will contain the value to which
051 * the property should be set
052 *
053 * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
054 * Use {@link #SetPropertyRule(String name, String value)} instead.
055 */
056 @Deprecated
057 public SetPropertyRule(Digester digester, String name, String value) {
058
059 this(name, value);
060
061 }
062
063 /**
064 * Construct a "set property" rule with the specified name and value
065 * attributes.
066 *
067 * @param name Name of the attribute that will contain the name of the
068 * property to be set
069 * @param value Name of the attribute that will contain the value to which
070 * the property should be set
071 */
072 public SetPropertyRule(String name, String value) {
073
074 this.name = name;
075 this.value = value;
076
077 }
078
079 // ----------------------------------------------------- Instance Variables
080
081
082 /**
083 * The attribute that will contain the property name.
084 */
085 protected String name = null;
086
087
088 /**
089 * The attribute that will contain the property value.
090 */
091 protected String value = null;
092
093
094 // --------------------------------------------------------- Public Methods
095
096
097 /**
098 * Process the beginning of this element.
099 *
100 * @param attributes The attribute list of this element
101 *
102 * @exception NoSuchMethodException if the bean does not
103 * have a writeable property of the specified name
104 */
105 @Override
106 public void begin(Attributes attributes) throws Exception {
107
108 if (attributes.getLength() == 0 ) {
109 return;
110 }
111
112 // Identify the actual property name and value to be used
113 String actualName = null;
114 String actualValue = null;
115 for (int i = 0; i < attributes.getLength(); i++) {
116 String name = attributes.getLocalName(i);
117 if ("".equals(name)) {
118 name = attributes.getQName(i);
119 }
120 String value = attributes.getValue(i);
121 if (name.equals(this.name)) {
122 actualName = value;
123 } else if (name.equals(this.value)) {
124 actualValue = value;
125 }
126 }
127
128 // Get a reference to the top object
129 Object top = digester.peek();
130
131 // Log some debugging information
132 if (digester.log.isDebugEnabled()) {
133 digester.log.debug("[SetPropertyRule]{" + digester.match +
134 "} Set " + top.getClass().getName() + " property " +
135 actualName + " to " + actualValue);
136 }
137
138 // Force an exception if the property does not exist
139 // (BeanUtils.setProperty() silently returns in this case)
140 //
141 // This code should probably use PropertyUtils.isWriteable(),
142 // like SetPropertiesRule does.
143 if (top instanceof DynaBean) {
144 DynaProperty desc =
145 ((DynaBean) top).getDynaClass().getDynaProperty(actualName);
146 if (desc == null) {
147 throw new NoSuchMethodException
148 ("Bean has no property named " + actualName);
149 }
150 } else /* this is a standard JavaBean */ {
151 PropertyDescriptor desc =
152 PropertyUtils.getPropertyDescriptor(top, actualName);
153 if (desc == null) {
154 throw new NoSuchMethodException
155 ("Bean has no property named " + actualName);
156 }
157 }
158
159 // Set the property (with conversion as necessary)
160 BeanUtils.setProperty(top, actualName, actualValue);
161
162 }
163
164
165 /**
166 * Render a printable version of this Rule.
167 */
168 @Override
169 public String toString() {
170
171 StringBuffer sb = new StringBuffer("SetPropertyRule[");
172 sb.append("name=");
173 sb.append(name);
174 sb.append(", value=");
175 sb.append(value);
176 sb.append("]");
177 return (sb.toString());
178
179 }
180
181
182 }