📄 readcontext.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.read;
import java.beans.IntrospectionException;
import java.util.HashMap;
import org.apache.commons.betwixt.AttributeDescriptor;
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.expression.Context;
import org.apache.commons.betwixt.expression.Updater;
import org.apache.commons.betwixt.strategy.ActionMappingStrategy;
import org.apache.commons.collections.ArrayStack;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.Attributes;
/**
* <p>Extends <code>Context</code> to provide read specific functionality.</p>
* <p>
* Three stacks are used to manage the reading:
* </p>
* <ul>
* <li><strong>Action mapping stack</strong> contains the {@link MappingAction}'s
* used to execute the mapping of the current element and it's ancesters back to the
* document root.</li>
* <li><strong>Result stack</strong> contains the objects which are bound
* to the current element and to each of it's ancester's back to the root</li>
* <li><strong>Element mapping stack</strong> records the names of the element
* and the classes to which they are bound</li>
* </ul>
* @author Robert Burrell Donkina
* @since 0.5
*/
public class ReadContext extends Context {
/** Beans indexed by ID strings */
private HashMap beansById = new HashMap();
/** Classloader to be used to load beans during reading */
private ClassLoader classLoader;
/** The read specific configuration */
private ReadConfiguration readConfiguration;
/** Records the element path together with the locations where classes were mapped*/
private ArrayStack elementMappingStack = new ArrayStack();
/** Contains actions for each element */
private ArrayStack actionMappingStack = new ArrayStack();
/** Stack contains all beans created */
private ArrayStack objectStack = new ArrayStack();
private ArrayStack descriptorStack = new ArrayStack();
private ArrayStack updaterStack = new ArrayStack();
private Class rootClass;
/** The <code>XMLIntrospector</code> to be used to map the xml*/
private XMLIntrospector xmlIntrospector;
/**
* Constructs a <code>ReadContext</code> with the same settings
* as an existing <code>Context</code>.
* @param context not null
* @param readConfiguration not null
*/
public ReadContext(Context context, ReadConfiguration readConfiguration) {
super(context);
this.readConfiguration = readConfiguration;
}
/**
* Constructs a <code>ReadContext</code> with standard log.
* @param bindingConfiguration the dynamic configuration, not null
* @param readConfiguration the extra read configuration not null
*/
public ReadContext(
BindingConfiguration bindingConfiguration,
ReadConfiguration readConfiguration) {
this(
LogFactory.getLog(ReadContext.class),
bindingConfiguration,
readConfiguration);
}
/**
* Base constructor
* @param log log to this Log
* @param bindingConfiguration the dynamic configuration, not null
* @param readConfiguration the extra read configuration not null
*/
public ReadContext(
Log log,
BindingConfiguration bindingConfiguration,
ReadConfiguration readConfiguration) {
super(null, log, bindingConfiguration);
this.readConfiguration = readConfiguration;
}
/**
* Constructs a <code>ReadContext</code>
* with the same settings as an existing <code>Context</code>.
* @param readContext not null
*/
public ReadContext(ReadContext readContext) {
super(readContext);
beansById = readContext.beansById;
classLoader = readContext.classLoader;
readConfiguration = readContext.readConfiguration;
}
/**
* Puts a bean into storage indexed by an (xml) ID.
*
* @param id the ID string of the xml element associated with the bean
* @param bean the Object to store, not null
*/
public void putBean(String id, Object bean) {
beansById.put(id, bean);
}
/**
* Gets a bean from storage by an (xml) ID.
*
* @param id the ID string of the xml element associated with the bean
* @return the Object that the ID references, otherwise null
*/
public Object getBean(String id) {
return beansById.get(id);
}
/**
* Clears the beans indexed by id.
*/
public void clearBeans() {
beansById.clear();
}
/**
* Gets the classloader to be used.
* @return the classloader that should be used to load all classes, possibly null
*/
public ClassLoader getClassLoader() {
return classLoader;
}
/**
* Sets the classloader to be used.
* @param classLoader the ClassLoader to be used, possibly null
*/
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Gets the <code>BeanCreationChange</code> to be used to create beans
* when an element is mapped.
* @return the BeanCreationChain not null
*/
public BeanCreationChain getBeanCreationChain() {
return readConfiguration.getBeanCreationChain();
}
/**
* Gets the strategy used to define default mappings actions
* for elements.
* @return <code>ActionMappingStrategy</code>. not null
*/
public ActionMappingStrategy getActionMappingStrategy() {
return readConfiguration.getActionMappingStrategy();
}
/**
* Pops the top element from the element mapping stack.
* Also removes any mapped class marks below the top element.
*
* @return the name of the element popped
* if there are any more elements on the stack, otherwise null.
* This is the local name if the parser is namespace aware, otherwise the name
*/
public String popElement() {
// since the descriptor stack is populated by pushElement,
// need to ensure that it's correct popped by popElement
if (!descriptorStack.isEmpty()) {
descriptorStack.pop();
}
if (!updaterStack.isEmpty()) {
updaterStack.pop();
}
Object top = null;
if (!elementMappingStack.isEmpty()) {
top = elementMappingStack.pop();
if (top != null) {
if (!(top instanceof String)) {
return popElement();
}
}
}
return (String) top;
}
/**
* Gets the element name for the currently mapped element.
* @return the name of the currently mapped element,
* or null if there has been no element mapped
*/
public String getCurrentElement() {
return (String) elementMappingStack.peek();
}
/**
* Gets the Class that was last mapped, if there is one.
*
* @return the Class last marked as mapped
* or null if no class has been mapped
*/
public Class getLastMappedClass() {
Class lastMapped = null;
for (int i = 0, size = elementMappingStack.size();
i < size;
i++) {
Object entry = elementMappingStack.peek(i);
if (entry instanceof Class) {
lastMapped = (Class) entry;
break;
}
}
return lastMapped;
}
private ElementDescriptor getParentDescriptor() throws IntrospectionException {
ElementDescriptor result = null;
if (descriptorStack.size() > 1) {
result = (ElementDescriptor) descriptorStack.peek(1);
}
return result;
}
/**
* Pushes the given element onto the element mapping stack.
*
* @param elementName the local name if the parser is namespace aware,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -