001 /* $Id: SetPropertyRule.java 568192 2007-08-21 16:41:16Z bayard $
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 public SetPropertyRule(Digester digester, String name, String value) {
057
058 this(name, value);
059
060 }
061
062 /**
063 * Construct a "set property" rule with the specified name and value
064 * attributes.
065 *
066 * @param name Name of the attribute that will contain the name of the
067 * property to be set
068 * @param value Name of the attribute that will contain the value to which
069 * the property should be set
070 */
071 public SetPropertyRule(String name, String value) {
072
073 this.name = name;
074 this.value = value;
075
076 }
077
078 // ----------------------------------------------------- Instance Variables
079
080
081 /**
082 * The attribute that will contain the property name.
083 */
084 protected String name = null;
085
086
087 /**
088 * The attribute that will contain the property value.
089 */
090 protected String value = null;
091
092
093 // --------------------------------------------------------- Public Methods
094
095
096 /**
097 * Process the beginning of this element.
098 *
099 * @param attributes The attribute list of this element
100 *
101 * @exception NoSuchMethodException if the bean does not
102 * have a writeable property of the specified name
103 */
104 public void begin(Attributes attributes) throws Exception {
105
106 if (attributes.getLength() == 0 ) {
107 return;
108 }
109
110 // Identify the actual property name and value to be used
111 String actualName = null;
112 String actualValue = null;
113 for (int i = 0; i < attributes.getLength(); i++) {
114 String name = attributes.getLocalName(i);
115 if ("".equals(name)) {
116 name = attributes.getQName(i);
117 }
118 String value = attributes.getValue(i);
119 if (name.equals(this.name)) {
120 actualName = value;
121 } else if (name.equals(this.value)) {
122 actualValue = value;
123 }
124 }
125
126 // Get a reference to the top object
127 Object top = digester.peek();
128
129 // Log some debugging information
130 if (digester.log.isDebugEnabled()) {
131 digester.log.debug("[SetPropertyRule]{" + digester.match +
132 "} Set " + top.getClass().getName() + " property " +
133 actualName + " to " + actualValue);
134 }
135
136 // Force an exception if the property does not exist
137 // (BeanUtils.setProperty() silently returns in this case)
138 //
139 // This code should probably use PropertyUtils.isWriteable(),
140 // like SetPropertiesRule does.
141 if (top instanceof DynaBean) {
142 DynaProperty desc =
143 ((DynaBean) top).getDynaClass().getDynaProperty(actualName);
144 if (desc == null) {
145 throw new NoSuchMethodException
146 ("Bean has no property named " + actualName);
147 }
148 } else /* this is a standard JavaBean */ {
149 PropertyDescriptor desc =
150 PropertyUtils.getPropertyDescriptor(top, actualName);
151 if (desc == null) {
152 throw new NoSuchMethodException
153 ("Bean has no property named " + actualName);
154 }
155 }
156
157 // Set the property (with conversion as necessary)
158 BeanUtils.setProperty(top, actualName, actualValue);
159
160 }
161
162
163 /**
164 * Render a printable version of this Rule.
165 */
166 public String toString() {
167
168 StringBuffer sb = new StringBuffer("SetPropertyRule[");
169 sb.append("name=");
170 sb.append(name);
171 sb.append(", value=");
172 sb.append(value);
173 sb.append("]");
174 return (sb.toString());
175
176 }
177
178
179 }