blob: b1ad74cf4770e15df3aff9f8012aa4ae1e59db9a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.axiom.om.impl.common;
import javax.xml.stream.XMLStreamReader;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.OMSourcedElement;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.axiom.om.OMXMLStreamReader;
import org.apache.axiom.om.OMXMLStreamReaderConfiguration;
import org.apache.axiom.om.impl.OMNodeEx;
import org.apache.axiom.om.impl.builder.OMFactoryEx;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.util.OMXMLStreamReaderValidator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public final class OMContainerHelper {
private static final Log log = LogFactory.getLog(OMContainerHelper.class);
private static final OMXMLStreamReaderConfiguration defaultReaderConfiguration = new OMXMLStreamReaderConfiguration();
private OMContainerHelper() {}
public static XMLStreamReader getXMLStreamReader(IContainer container, boolean cache) {
return getXMLStreamReader(container, cache, defaultReaderConfiguration);
}
public static XMLStreamReader getXMLStreamReader(IContainer container, boolean cache, OMXMLStreamReaderConfiguration configuration) {
OMXMLParserWrapper builder = container.getBuilder();
if (builder != null && builder instanceof StAXOMBuilder) {
if (!container.isComplete()) {
if (((StAXOMBuilder) builder).isLookahead()) {
buildNext(container);
}
}
}
// The om tree was built by hand and is already complete
OMXMLStreamReader reader;
boolean done = container.isComplete();
if ((builder == null) && done) {
reader = new OMStAXWrapper(null, container, false, configuration.isPreserveNamespaceContext());
} else {
if ((builder == null) && !cache) {
throw new UnsupportedOperationException(
"This element was not created in a manner to be switched");
}
if (builder != null && builder.isCompleted() && !cache && !done) {
throw new UnsupportedOperationException(
"The parser is already consumed!");
}
reader = new OMStAXWrapper(builder, container, cache, configuration.isPreserveNamespaceContext());
}
if (configuration.isNamespaceURIInterning()) {
reader = new NamespaceURIInterningXMLStreamReaderWrapper(reader);
}
// If debug is enabled, wrap the OMXMLStreamReader in a validator.
// The validator will check for mismatched events to help determine if the OMStAXWrapper
// is functioning correctly. All problems are reported as debug.log messages
if (log.isDebugEnabled()) {
reader =
new OMXMLStreamReaderValidator(reader, // delegate to actual reader
false); // log problems (true will cause exceptions to be thrown)
}
return reader;
}
public static void addChild(IContainer container, OMNode omNode, boolean fromBuilder) {
OMNodeEx child;
if (fromBuilder) {
// If the new child was provided by the builder, we know that it was created by
// the same factory
child = (OMNodeEx)omNode;
} else {
// Careful here: if the child was created by another Axiom implementation, it doesn't
// necessarily implement OMNodeEx
if (omNode.getOMFactory().getMetaFactory() == container.getOMFactory().getMetaFactory()) {
child = (OMNodeEx)omNode;
} else {
child = (OMNodeEx)((OMFactoryEx)container.getOMFactory()).importNode(omNode);
}
if (!container.isComplete()) {
container.build();
}
if (child.getParent() == container && child == container.getLastKnownOMChild()) {
// The child is already the last node.
// We don't need to detach and re-add it.
return;
}
}
if (child.getParent() != null) {
child.detach();
}
child.setParent(container);
if (container.getFirstOMChildIfAvailable() == null) {
container.setFirstChild(child);
} else {
OMNode lastChild = container.getLastKnownOMChild();
child.setPreviousOMSibling(lastChild);
((OMNodeEx)lastChild).setNextOMSibling(child);
}
container.setLastChild(child);
// For a normal OMNode, the incomplete status is
// propogated up the tree.
// However, a OMSourcedElement is self-contained
// (it has an independent parser source).
// So only propogate the incomplete setting if this
// is a normal OMNode
if (!fromBuilder && !child.isComplete() &&
!(child instanceof OMSourcedElement)) {
container.setComplete(false);
}
}
public static void build(IContainer container) {
OMXMLParserWrapper builder = container.getBuilder();
if (builder != null && builder.isCompleted()) {
log.debug("Builder is already complete.");
}
while (!container.isComplete()) {
builder.next();
if (builder.isCompleted() && !container.isComplete()) {
log.debug("Builder is complete. Setting OMObject to complete.");
container.setComplete(true);
}
}
}
public static void buildNext(IParentNode that) {
OMXMLParserWrapper builder = that.getBuilder();
if (builder != null) {
if (((StAXOMBuilder)builder).isClosed()) {
throw new OMException("The builder has already been closed");
} else if (!builder.isCompleted()) {
builder.next();
} else {
// If the builder is suddenly complete, but the completion status of the node
// doesn't change, then this means that we built the wrong nodes
throw new IllegalStateException("Builder is already complete");
}
}
}
public static OMNode getFirstOMChild(IParentNode that) {
OMNode firstChild;
while ((firstChild = that.getFirstOMChildIfAvailable()) == null && !that.isComplete()) {
buildNext(that);
}
return firstChild;
}
}