⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 beanreader.java

📁 JAVA 文章管理系统源码
💻 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.beans.IntrospectionException;
import java.util.HashSet;
import java.util.Set;

import javax.xml.parsers.SAXParser;

import org.apache.commons.betwixt.BindingConfiguration;
import org.apache.commons.betwixt.ElementDescriptor;
import org.apache.commons.betwixt.XMLBeanInfo;
import org.apache.commons.betwixt.XMLIntrospector;
import org.apache.commons.betwixt.io.read.ReadConfiguration;
import org.apache.commons.betwixt.io.read.ReadContext;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.ExtendedBaseRules;
import org.apache.commons.digester.RuleSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.XMLReader;

/** <p><code>BeanReader</code> reads a tree of beans from an XML document.</p>
  *
  * <p>Call {@link #registerBeanClass(Class)} or {@link #registerBeanClass(String, Class)}
  * to add rules to map a bean class.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  */
public class BeanReader extends Digester {

    /** Introspector used */
    private XMLIntrospector introspector = new XMLIntrospector();    
    /** Log used for logging (Doh!) */
    private Log log = LogFactory.getLog( BeanReader.class );
    /** The registered classes */
    private Set registeredClasses = new HashSet();
    /** Dynamic binding configuration settings */
    private BindingConfiguration bindingConfiguration = new BindingConfiguration();
    /** Reading specific configuration settings */
    private ReadConfiguration readConfiguration = new ReadConfiguration();
    
    /**
     * Construct a new BeanReader with default properties.
     */
    public BeanReader() {
    	// TODO: now we require extended rules may need to document this
    	setRules(new ExtendedBaseRules());
    }

    /**
     * Construct a new BeanReader, allowing a SAXParser to be passed in.  This
     * allows BeanReader to be used in environments which are unfriendly to
     * JAXP1.1 (such as WebLogic 6.0).  Thanks for the request to change go to
     * James House (james@interobjective.com).  This may help in places where
     * you are able to load JAXP 1.1 classes yourself.
     *
     * @param parser use this <code>SAXParser</code>
     */
    public BeanReader(SAXParser parser) {
        super(parser);
		setRules(new ExtendedBaseRules());
    }

    /**
     * Construct a new BeanReader, allowing an XMLReader to be passed in.  This
     * allows BeanReader to be used in environments which are unfriendly to
     * JAXP1.1 (such as WebLogic 6.0).  Note that if you use this option you
     * have to configure namespace and validation support yourself, as these
     * properties only affect the SAXParser and emtpy constructor.
     *
     * @param reader use this <code>XMLReader</code> as source for SAX events
     */
    public BeanReader(XMLReader reader) {
        super(reader);
		setRules(new ExtendedBaseRules());
    }

    
    /** 
     * <p>Register a bean class and add mapping rules for this bean class.</p>
     * 
     * <p>A bean class is introspected when it is registered.
     * It will <strong>not</strong> be introspected again even if the introspection
     * settings are changed.
     * If re-introspection is required, then {@link #deregisterBeanClass} must be called 
     * and the bean re-registered.</p>
     *
     * <p>A bean class can only be registered once. 
     * If the same class is registered a second time, this registration will be ignored.
     * In order to change a registration, call {@link #deregisterBeanClass} 
     * before calling this method.</p>
     *
     * <p>All the rules required to digest this bean are added when this method is called.
     * Other rules that you want to execute before these should be added before this
     * method is called. 
     * Those that should be executed afterwards, should be added afterwards.</p>
     *
     * @param beanClass the <code>Class</code> to be registered
     * @throws IntrospectionException if the bean introspection fails
     */
    public void registerBeanClass(Class beanClass) throws IntrospectionException {
        if ( ! registeredClasses.contains( beanClass ) ) {
            if ( log.isTraceEnabled() ) {
                log.trace( "Registering class " + beanClass );
            }
            registeredClasses.add( beanClass );
            
            // introspect and find the ElementDescriptor to use as the root
            XMLBeanInfo xmlInfo = introspector.introspect( beanClass );
            ElementDescriptor elementDescriptor = xmlInfo.getElementDescriptor();        

            String path = elementDescriptor.getQualifiedName();
            if (log.isTraceEnabled()) {
                log.trace("Added path: " + path + ", mapped to: " + beanClass.getName());
            }
            addBeanCreateRule( path, elementDescriptor, beanClass );
            
        } else {
            if ( log.isWarnEnabled() ) {
                log.warn("Cannot add class "  + beanClass.getName() + " since it already exists");
            }
        }
    }
    
    /** 
     * <p>Registers a bean class  
     * and add mapping rules for this bean class at the given path expression.</p>
     * 
     * 
     * <p>A bean class is introspected when it is registered.
     * It will <strong>not</strong> be introspected again even if the introspection
     * settings are changed.
     * If re-introspection is required, then {@link #deregisterBeanClass} must be called 
     * and the bean re-registered.</p>
     *
     * <p>A bean class can only be registered once. 
     * If the same class is registered a second time, this registration will be ignored.
     * In order to change a registration, call {@link #deregisterBeanClass} 
     * before calling this method.</p>
     *
     * <p>All the rules required to digest this bean are added when this method is called.
     * Other rules that you want to execute before these should be added before this
     * method is called. 
     * Those that should be executed afterwards, should be added afterwards.</p>
     *
     * @param path the xml path expression where the class is to registered. 
     * This should be in digester path notation
     * @param beanClass the <code>Class</code> to be registered
     * @throws IntrospectionException if the bean introspection fails
     */
    public void registerBeanClass(String path, Class beanClass) throws IntrospectionException {
        if ( ! registeredClasses.contains( beanClass ) ) {
            registeredClasses.add( beanClass );
            
            // introspect and find the ElementDescriptor to use as the root
            XMLBeanInfo xmlInfo = introspector.introspect( beanClass );
            ElementDescriptor elementDescriptor = xmlInfo.getElementDescriptor();        

            addBeanCreateRule( path, elementDescriptor, beanClass );
        } else {
            if ( log.isWarnEnabled() ) {
                log.warn("Cannot add class "  + beanClass.getName() + " since it already exists");
            }
        }
    }
    
    /**
     * <p>Flush all registered bean classes.
     * This allows all bean classes to be re-registered 
     * by a subsequent calls to <code>registerBeanClass</code>.</p>
     *
     * <p><strong>Note</strong> that deregistering a bean does <strong>not</strong>
     * remove the Digester rules associated with that bean.</p>
     * @since 0.5
     */
    public void flushRegisteredBeanClasses() {    
        registeredClasses.clear();
    }
    
    /**
     * <p>Remove the given class from the register.
     * Calling this method will allow the bean class to be re-registered 
     * by a subsequent call to <code>registerBeanClass</code>.
     * This allows (for example) a bean to be reintrospected after a change
     * to the introspection settings.</p>
     *
     * <p><strong>Note</strong> that deregistering a bean does <strong>not</strong>
     * remove the Digester rules associated with that bean.</p>
     *
     * @param beanClass the <code>Class</code> to remove from the set of registered bean classes
     * @since 0.5 
     */
    public void deregisterBeanClass( Class beanClass ) {
        registeredClasses.remove( beanClass );
    }
    
    // Properties
    //-------------------------------------------------------------------------        

    /**
     * <p> Get the introspector used. </p>
     *
     * <p> The {@link XMLBeanInfo} used to map each bean is 
     * created by the <code>XMLIntrospector</code>.
     * One way in which the mapping can be customized is by 
     * altering the <code>XMLIntrospector</code>. </p>
     * 
     * @return the <code>XMLIntrospector</code> used for the introspection
     */
    public XMLIntrospector getXMLIntrospector() {
        return introspector;
    }
    

    /**
     * <p> Set the introspector to be used. </p>
     *
     * <p> The {@link XMLBeanInfo} used to map each bean is 
     * created by the <code>XMLIntrospector</code>.
     * One way in which the mapping can be customized is by 
     * altering the <code>XMLIntrospector</code>. </p>
     *
     * @param introspector use this introspector
     */
    public void setXMLIntrospector(XMLIntrospector introspector) {
        this.introspector = introspector;
    }

    /**
     * <p> Get the current level for logging. </p>
     *
     * @return the <code>Log</code> implementation this class logs to
     */ 
    public Log getLog() {
        return log;
    }

    /**
     * <p> Set the current logging level. </p>
     *
     * @param log the <code>Log</code>implementation to use for logging
     */ 
    public void setLog(Log log) {
        this.log = log;
        setLogger(log);
    }
    
    /** 
     * Should the reader use <code>ID</code> attributes to match beans.
     *
     * @return true if <code>ID</code> and <code>IDREF</code> 
     * attributes should be used to match instances
     * @deprecated 0.5 use {@link BindingConfiguration#getMapIDs}
     */
    public boolean getMatchIDs() {
        return getBindingConfiguration().getMapIDs();
    }
    
    /**
     * Set whether the read should use <code>ID</code> attributes to match beans.
     *
     * @param matchIDs pass true if <code>ID</code>'s should be matched
     * @deprecated 0.5 use {@link BindingConfiguration#setMapIDs}
     */
    public void setMatchIDs(boolean matchIDs) {
        getBindingConfiguration().setMapIDs( matchIDs );
    }
    
    /**
     * Gets the dynamic configuration setting to be used for bean reading.
     * @return the BindingConfiguration settings, not null
     * @since 0.5
     */
    public BindingConfiguration getBindingConfiguration() {
        return bindingConfiguration;
    }
    
    /**
     * Sets the dynamic configuration setting to be used for bean reading.
     * @param bindingConfiguration the BindingConfiguration settings, not null
     * @since 0.5
     */
    public void setBindingConfiguration( BindingConfiguration bindingConfiguration ) {
        this.bindingConfiguration = bindingConfiguration;
    }
    
    /**
     * Gets read specific configuration details.
     * @return the ReadConfiguration, not null
     * @since 0.5
     */
    public ReadConfiguration getReadConfiguration() {
        return readConfiguration;
    }
    
    /**
     * Sets the read specific configuration details.
     * @param readConfiguration not null
     * @since 0.5
     */
    public void setReadConfiguration( ReadConfiguration readConfiguration ) {
        this.readConfiguration = readConfiguration;
    }
        
    // Implementation methods
    //-------------------------------------------------------------------------    
    
    /** 
     * Adds a new bean create rule for the specified path
     *
     * @param path the digester path at which this rule should be added
     * @param elementDescriptor the <code>ElementDescriptor</code> describes the expected element 
     * @param beanClass the <code>Class</code> of the bean created by this rule
     */
    protected void addBeanCreateRule( 
                                    String path, 
                                    ElementDescriptor elementDescriptor, 
                                    Class beanClass ) {
        if (log.isTraceEnabled()) {
            log.trace("Adding BeanRuleSet for " + beanClass);
        }
        RuleSet ruleSet = new BeanRuleSet( 
                                            introspector, 
                                            path ,  
                                            elementDescriptor, 
                                            beanClass, 
                                            makeContext());
        addRuleSet( ruleSet );
    }
        
    /**
      * Factory method for new contexts.
      * Ensure that they are correctly configured.
      * @return the ReadContext created, not null
      */
    private ReadContext makeContext() {
        return new ReadContext( log, bindingConfiguration, readConfiguration );
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -