📄 setnestedpropertiesrule.java
字号:
/* $Id: SetNestedPropertiesRule.java,v 1.8 2004/05/10 06:52:50 skitching Exp $
*
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.digester;
import java.util.List;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.HashMap;
import java.beans.PropertyDescriptor;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.beanutils.PropertyUtils;
import org.xml.sax.Attributes;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* <p>Rule implementation that sets properties on the object at the top of the
* stack, based on child elements with names matching properties on that
* object.</p>
*
* <p>Example input that can be processed by this rule:</p>
* <pre>
* [widget]
* [height]7[/height]
* [width]8[/width]
* [label]Hello, world[/label]
* [/widget]
* </pre>
*
* <p>This rule supports custom mapping of attribute names to property names.
* The default mapping for particular attributes can be overridden by using
* {@link #SetNestedPropertiesRule(String[] elementNames,
* String[] propertyNames)}.
* This allows child elements to be mapped to properties with different names.
* Certain elements can also be marked to be ignored.</p>
*
* <p>A very similar effect can be achieved using a combination of the
* <code>BeanPropertySetterRule</code> and the <code>ExtendedBaseRules</code>
* rules manager; this <code>Rule</code>, however, works fine with the default
* <code>RulesBase</code> rules manager.</p>
*
* <p><b>Implementation Notes</b></p>
*
* <p>This class works by creating its own simple Rules implementation. When
* begin is invoked on this rule, the digester's current rules object is
* replaced by a custom one. When end is invoked for this rule, the original
* rules object is restored. The digester rules objects therefore behave in
* a stack-like manner.</p>
*
* <p>For each child element encountered, the custom Rules implementation
* ensures that a special AnyChildRule instance is included in the matches
* returned to the digester, and it is this rule instance that is responsible
* for setting the appropriate property on the target object (if such a property
* exists). The effect is therefore like a "trailing wildcard pattern". The
* custom Rules implementation also returns the matches provided by the
* underlying Rules implementation for the same pattern, so other rules
* are not "disabled" during processing of a SetNestedPropertiesRule.</p>
*
* @since 1.6
*/
public class SetNestedPropertiesRule extends Rule {
/**
* Dummy object that can be placed in collections to indicate an
* ignored property when null cannot be used for that purpose.
*/
private static final String PROP_IGNORE = "ignore-me";
private Log log = null;
private AnyChildRule anyChildRule = new AnyChildRule();
private AnyChildRules newRules = new AnyChildRules(anyChildRule);
private Rules oldRules = null;
private boolean trimData = true;
private boolean allowUnknownChildElements = false;
private HashMap elementNames = new HashMap();
// ----------------------------------------------------------- Constructors
/**
* Base constructor.
*/
public SetNestedPropertiesRule() {
// nothing to set up
}
/**
* <p>Convenience constructor overrides the mapping for just one property.</p>
*
* <p>For details about how this works, see
* {@link #SetNestedPropertiesRule(String[] elementNames,
* String[] propertyNames)}.</p>
*
* @param elementName map the child element to match
* @param propertyName to a property with this name
*/
public SetNestedPropertiesRule(String elementName, String propertyName) {
elementNames.put(elementName, propertyName);
}
/**
* <p>Constructor allows element->property mapping to be overriden.</p>
*
* <p>Two arrays are passed in.
* One contains the element names and the other the property names.
* The element name / property name pairs are match by position
* In order words, the first string in the element name list matches
* to the first string in the property name list and so on.</p>
*
* <p>If a property name is null or the element name has no matching
* property name, then this indicates that the element should be ignored.</p>
*
* <h5>Example One</h5>
* <p> The following constructs a rule that maps the <code>alt-city</code>
* element to the <code>city</code> property and the <code>alt-state</code>
* to the <code>state</code> property.
* All other child elements are mapped as usual using exact name matching.
* <code><pre>
* SetNestedPropertiesRule(
* new String[] {"alt-city", "alt-state"},
* new String[] {"city", "state"});
* </pre></code>
*
* <h5>Example Two</h5>
* <p> The following constructs a rule that maps the <code>class</code>
* element to the <code>className</code> property.
* The element <code>ignore-me</code> is not mapped.
* All other elements are mapped as usual using exact name matching.
* <code><pre>
* SetPropertiesRule(
* new String[] {"class", "ignore-me"},
* new String[] {"className"});
* </pre></code>
*
* @param elementNames names of elements to map
* @param propertyNames names of properties mapped to
*/
public SetNestedPropertiesRule(String[] elementNames, String[] propertyNames) {
for (int i=0, size=elementNames.length; i<size; i++) {
String propName = null;
if (i < propertyNames.length) {
propName = propertyNames[i];
}
if (propName == null) {
this.elementNames.put(elementNames[i], PROP_IGNORE);
}
else {
this.elementNames.put(elementNames[i], propName);
}
}
}
// --------------------------------------------------------- Public Methods
/** Invoked when rule is added to digester. */
public void setDigester(Digester digester) {
super.setDigester(digester);
log = digester.getLogger();
anyChildRule.setDigester(digester);
}
/**
* When set to true, any text within child elements will have leading
* and trailing whitespace removed before assignment to the target
* object. The default value for this attribute is true.
*/
public void setTrimData(boolean trimData) {
this.trimData = trimData;
}
/** See {@link #setTrimData}. */
public boolean getTrimData() {
return trimData;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -