📄 beancreaterule.java
字号:
/*
* Copyright 2001-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.betwixt.io;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.betwixt.AttributeDescriptor;
import org.apache.commons.betwixt.ElementDescriptor;
import org.apache.commons.betwixt.XMLBeanInfo;
import org.apache.commons.betwixt.XMLIntrospector;
import org.apache.commons.betwixt.digester.XMLIntrospectorHelper;
import org.apache.commons.betwixt.expression.Context;
import org.apache.commons.betwixt.expression.MethodUpdater;
import org.apache.commons.betwixt.expression.Updater;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.Rules;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.Attributes;
/** <p><code>BeanCreateRule</code> is a Digester Rule for creating beans
* from the betwixt XML metadata.</p>
*
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
* @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
* @deprecated 0.5 this Rule does not allowed good integration with other Rules -
* use {@link BeanRuleSet} instead.
*/
public class BeanCreateRule extends Rule {
/** Logger */
private static Log log = LogFactory.getLog( BeanCreateRule.class );
/**
* Set log to be used by <code>BeanCreateRule</code> instances
* @param aLog the <code>Log</code> implementation for this class to log to
*/
public static void setLog(Log aLog) {
log = aLog;
}
/** The descriptor of this element */
private ElementDescriptor descriptor;
/** The Context used when evaluating Updaters */
private Context context;
/** Have we added our child rules to the digester? */
private boolean addedChildren;
/** In this begin-end loop did we actually create a new bean */
private boolean createdBean;
/** The type of the bean to create */
private Class beanClass;
/** The prefix added to digester rules */
private String pathPrefix;
/** Use id's to match beans? */
private boolean matchIDs = true;
/** allows an attribute to be specified to overload the types of beans used */
private String classNameAttribute = "className";
/**
* Convenience constructor which uses <code>ID's</code> for matching.
*
* @param descriptor the <code>ElementDescriptor</code> describing the element mapped
* @param beanClass the <code>Class</code> to be created
* @param pathPrefix the digester style path
*/
public BeanCreateRule(
ElementDescriptor descriptor,
Class beanClass,
String pathPrefix ) {
this( descriptor, beanClass, pathPrefix, true );
}
/**
* Constructor taking a class.
*
* @param descriptor the <code>ElementDescriptor</code> describing the element mapped
* @param beanClass the <code>Class</code> to be created
* @param pathPrefix the digester style path
* @param matchIDs should <code>ID</code>/<code>IDREF</code>'s be used for matching
*/
public BeanCreateRule(
ElementDescriptor descriptor,
Class beanClass,
String pathPrefix,
boolean matchIDs ) {
this(
descriptor,
beanClass,
new Context(),
pathPrefix,
matchIDs);
}
/**
* Convenience constructor which uses <code>ID's</code> for matching.
*
* @param descriptor the <code>ElementDescriptor</code> describing the element mapped
* @param beanClass the <code>Class</code> to be created
*/
public BeanCreateRule( ElementDescriptor descriptor, Class beanClass ) {
this( descriptor, beanClass, true );
}
/**
* Constructor uses standard qualified name.
*
* @param descriptor the <code>ElementDescriptor</code> describing the element mapped
* @param beanClass the <code>Class</code> to be created
* @param matchIDs should <code>ID</code>/<code>IDREF</code>'s be used for matching
*/
public BeanCreateRule( ElementDescriptor descriptor, Class beanClass, boolean matchIDs ) {
this( descriptor, beanClass, descriptor.getQualifiedName() + "/" , matchIDs );
}
/**
* Convenience constructor which uses <code>ID's</code> for match.
*
* @param descriptor the <code>ElementDescriptor</code> describing the element mapped
* @param context the <code>Context</code> to be used to evaluate expressions
* @param pathPrefix the digester path prefix
*/
public BeanCreateRule(
ElementDescriptor descriptor,
Context context,
String pathPrefix ) {
this( descriptor, context, pathPrefix, true );
}
/**
* Constructor taking a context.
*
* @param descriptor the <code>ElementDescriptor</code> describing the element mapped
* @param context the <code>Context</code> to be used to evaluate expressions
* @param pathPrefix the digester path prefix
* @param matchIDs should <code>ID</code>/<code>IDREF</code>'s be used for matching
*/
public BeanCreateRule(
ElementDescriptor descriptor,
Context context,
String pathPrefix,
boolean matchIDs ) {
this(
descriptor,
descriptor.getSingularPropertyType(),
context,
pathPrefix,
matchIDs );
}
/**
* Base constructor (used by other constructors).
*
* @param descriptor the <code>ElementDescriptor</code> describing the element mapped
* @param beanClass the <code>Class</code> of the bean to be created
* @param context the <code>Context</code> to be used to evaluate expressions
* @param pathPrefix the digester path prefix
* @param matchIDs should <code>ID</code>/<code>IDREF</code>'s be used for matching
*/
private BeanCreateRule(
ElementDescriptor descriptor,
Class beanClass,
Context context,
String pathPrefix,
boolean matchIDs ) {
this.descriptor = descriptor;
this.context = context;
this.beanClass = beanClass;
this.pathPrefix = pathPrefix;
this.matchIDs = matchIDs;
if (log.isTraceEnabled()) {
log.trace("Created bean create rule");
log.trace("Descriptor=" + descriptor);
log.trace("Class=" + beanClass);
log.trace("Path prefix=" + pathPrefix);
}
}
// Rule interface
//-------------------------------------------------------------------------
/**
* Process the beginning of this element.
*
* @param attributes The attribute list of this element
*/
public void begin(Attributes attributes) {
log.debug( "Called with descriptor: " + descriptor
+ " propertyType: " + descriptor.getPropertyType() );
if (log.isTraceEnabled()) {
int attributesLength = attributes.getLength();
if (attributesLength > 0) {
log.trace("Attributes:");
}
for (int i=0, size=attributesLength; i<size; i++) {
log.trace("Local:" + attributes.getLocalName(i));
log.trace("URI:" + attributes.getURI(i));
log.trace("QName:" + attributes.getQName(i));
}
}
// XXX: if a single rule instance gets reused and nesting occurs
// XXX: we should probably use a stack of booleans to test if we created a bean
// XXX: or let digester take nulls, which would be easier for us ;-)
createdBean = false;
Object instance = null;
if ( beanClass != null ) {
instance = createBean(attributes);
if ( instance != null ) {
createdBean = true;
context.setBean( instance );
digester.push(instance);
// if we are a reference to a type we should lookup the original
// as this ElementDescriptor will be 'hollow' and have no child attributes/elements.
// XXX: this should probably be done by the NodeDescriptors...
ElementDescriptor typeDescriptor = getElementDescriptor( descriptor );
//ElementDescriptor typeDescriptor = descriptor;
// iterate through all attributes
AttributeDescriptor[] attributeDescriptors
= typeDescriptor.getAttributeDescriptors();
if ( attributeDescriptors != null ) {
for ( int i = 0, size = attributeDescriptors.length; i < size; i++ ) {
AttributeDescriptor attributeDescriptor = attributeDescriptors[i];
// The following isn't really the right way to find the attribute
// but it's quite robust.
// The idea is that you try both namespace and local name first
// and if this returns null try the qName.
String value = attributes.getValue(
attributeDescriptor.getURI(),
attributeDescriptor.getLocalName()
);
if (value == null) {
value = attributes.getValue(attributeDescriptor.getQualifiedName());
}
if (log.isTraceEnabled()) {
log.trace("Attr URL:" + attributeDescriptor.getURI());
log.trace("Attr LocalName:" + attributeDescriptor.getLocalName() );
log.trace(value);
}
Updater updater = attributeDescriptor.getUpdater();
log.trace(updater);
if ( updater != null && value != null ) {
updater.update( context, value );
}
}
}
addChildRules();
// add bean for ID matching
if ( matchIDs ) {
// XXX need to support custom ID attribute names
// XXX i have a feeling that the current mechanism might need to change
// XXX so i'm leaving this till later
String id = attributes.getValue( "id" );
if ( id != null ) {
getBeansById().put( id, instance );
}
}
}
}
}
/**
* Process the end of this element.
*/
public void end() {
if ( createdBean ) {
// force any setters of the parent bean to be called for this new bean instance
Updater updater = descriptor.getUpdater();
Object instance = context.getBean();
Object top = digester.pop();
if (digester.getCount() == 0) {
context.setBean(null);
}else{
context.setBean( digester.peek() );
}
if ( updater != null ) {
if ( log.isDebugEnabled() ) {
log.debug( "Calling updater for: " + descriptor + " with: "
+ instance + " on bean: " + context.getBean() );
}
updater.update( context, instance );
} else {
if ( log.isDebugEnabled() ) {
log.debug( "No updater for: " + descriptor + " with: "
+ instance + " on bean: " + context.getBean() );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -