001: /* $Id: SetPropertyRule.java 471661 2006-11-06 08:09:25Z skitching $
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: package org.apache.commons.digester;
020:
021: import java.beans.PropertyDescriptor;
022:
023: import org.apache.commons.beanutils.BeanUtils;
024: import org.apache.commons.beanutils.DynaBean;
025: import org.apache.commons.beanutils.DynaProperty;
026: import org.apache.commons.beanutils.PropertyUtils;
027: import org.xml.sax.Attributes;
028:
029: /**
030: * Rule implementation that sets an individual property on the object at the
031: * top of the stack, based on attributes with specified names.
032: */
033:
034: public class SetPropertyRule extends Rule {
035:
036: // ----------------------------------------------------------- Constructors
037:
038: /**
039: * Construct a "set property" rule with the specified name and value
040: * attributes.
041: *
042: * @param digester The digester with which this rule is associated
043: * @param name Name of the attribute that will contain the name of the
044: * property to be set
045: * @param value Name of the attribute that will contain the value to which
046: * the property should be set
047: *
048: * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
049: * Use {@link #SetPropertyRule(String name, String value)} instead.
050: */
051: public SetPropertyRule(Digester digester, String name, String value) {
052:
053: this (name, value);
054:
055: }
056:
057: /**
058: * Construct a "set property" rule with the specified name and value
059: * attributes.
060: *
061: * @param name Name of the attribute that will contain the name of the
062: * property to be set
063: * @param value Name of the attribute that will contain the value to which
064: * the property should be set
065: */
066: public SetPropertyRule(String name, String value) {
067:
068: this .name = name;
069: this .value = value;
070:
071: }
072:
073: // ----------------------------------------------------- Instance Variables
074:
075: /**
076: * The attribute that will contain the property name.
077: */
078: protected String name = null;
079:
080: /**
081: * The attribute that will contain the property value.
082: */
083: protected String value = null;
084:
085: // --------------------------------------------------------- Public Methods
086:
087: /**
088: * Process the beginning of this element.
089: *
090: * @param attributes The attribute list of this element
091: *
092: * @exception NoSuchMethodException if the bean does not
093: * have a writeable property of the specified name
094: */
095: public void begin(Attributes attributes) throws Exception {
096:
097: // Identify the actual property name and value to be used
098: String actualName = null;
099: String actualValue = null;
100: for (int i = 0; i < attributes.getLength(); i++) {
101: String name = attributes.getLocalName(i);
102: if ("".equals(name)) {
103: name = attributes.getQName(i);
104: }
105: String value = attributes.getValue(i);
106: if (name.equals(this .name)) {
107: actualName = value;
108: } else if (name.equals(this .value)) {
109: actualValue = value;
110: }
111: }
112:
113: // Get a reference to the top object
114: Object top = digester.peek();
115:
116: // Log some debugging information
117: if (digester.log.isDebugEnabled()) {
118: digester.log.debug("[SetPropertyRule]{" + digester.match
119: + "} Set " + top.getClass().getName()
120: + " property " + actualName + " to " + actualValue);
121: }
122:
123: // Force an exception if the property does not exist
124: // (BeanUtils.setProperty() silently returns in this case)
125: //
126: // This code should probably use PropertyUtils.isWriteable(),
127: // like SetPropertiesRule does.
128: if (top instanceof DynaBean) {
129: DynaProperty desc = ((DynaBean) top).getDynaClass()
130: .getDynaProperty(actualName);
131: if (desc == null) {
132: throw new NoSuchMethodException(
133: "Bean has no property named " + actualName);
134: }
135: } else /* this is a standard JavaBean */{
136: PropertyDescriptor desc = PropertyUtils
137: .getPropertyDescriptor(top, actualName);
138: if (desc == null) {
139: throw new NoSuchMethodException(
140: "Bean has no property named " + actualName);
141: }
142: }
143:
144: // Set the property (with conversion as necessary)
145: BeanUtils.setProperty(top, actualName, actualValue);
146:
147: }
148:
149: /**
150: * Render a printable version of this Rule.
151: */
152: public String toString() {
153:
154: StringBuffer sb = new StringBuffer("SetPropertyRule[");
155: sb.append("name=");
156: sb.append(name);
157: sb.append(", value=");
158: sb.append(value);
159: sb.append("]");
160: return (sb.toString());
161:
162: }
163:
164: }
|