blob: 0fa92f7e1cfb7343f88c89f2073b67356cba6e46 [file] [log] [blame]
/*
* Copyright 2004,2005 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.axiom.om.impl.llom;
import org.apache.axiom.om.*;
import org.apache.axiom.om.impl.MTOMXMLStreamWriter;
import org.apache.axiom.om.impl.OMContainerEx;
import org.apache.axiom.om.impl.OMNodeEx;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.impl.llom.factory.OMLinkedListImplFactory;
import org.apache.axiom.om.util.StAXUtils;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.io.OutputStream;
import java.io.Writer;
/**
* Class OMNodeImpl
*/
public abstract class OMNodeImpl implements OMNode, OMNodeEx {
/**
* Field parent
*/
protected OMContainerEx parent;
/**
* Field nextSibling
*/
protected OMNodeImpl nextSibling;
/**
* Field previousSibling
*/
protected OMNodeImpl previousSibling;
/**
* Field builder
*/
protected OMXMLParserWrapper builder;
/**
* Field done
*/
protected boolean done = false;
/**
* Field nodeType
*/
protected int nodeType;
protected OMFactory factory;
/**
* Constructor OMNodeImpl
* @param factory The <code>OMFactory</code> that created this
*/
public OMNodeImpl(OMFactory factory) {
this.factory = factory;
}
/**
* For a node to exist there must be a parent.
*
* @param parent Parent <code>OMContainer</code> of this node
* @param factory The <code>OMFactory</code> that created this
*/
public OMNodeImpl(OMContainer parent, OMFactory factory, boolean done) {
this.done = done;
this.factory = factory;
if ((parent != null)) {
this.parent = (OMContainerEx) parent;
parent.addChild(this);
}
}
/**
* Returns the immediate parent of the node. Parent is always an Element.
*
* @return Returns OMContainer.
* @throws OMException
*/
public OMContainer getParent() {
return parent;
}
/**
* Method setParent.
*
* @param element
*/
public void setParent(OMContainer element) {
if ((this.parent) == element) {
return;
}
//If we are asked to assign a new parent in place
//of an existing one. We should detach this node
//from the previous parent.
if (element!=null){
if (this.parent != null) {
this.detach();
}
this.parent = (OMContainerEx) element;
}else{
this.parent = null;
}
}
/**
* Returns the next sibling. This can be an OMAttribute or
* OMText or OMElement for others.
*
* @return Returns OMNode.
* @throws org.apache.axiom.om.OMException
*
*/
public OMNode getNextOMSibling() throws OMException {
if ((nextSibling == null) && (parent != null) && !parent.isComplete()) {
parent.buildNext();
}
return nextSibling;
}
/**
* Method setNextOMSibling.
*
* @param node
*/
public void setNextOMSibling(OMNode node) {
if (node ==null || node.getOMFactory() instanceof OMLinkedListImplFactory) {
this.nextSibling = (OMNodeImpl) node;
} else {
this.nextSibling = (OMNodeImpl)importNode(node);
}
this.nextSibling = (OMNodeImpl) node;
}
/**
* Indicates whether parser has parsed this information item completely or not.
* If some information is not available in the item, one has to check this
* attribute to make sure that, this item has been parsed completely or not.
*
* @return Returns boolean.
*/
public boolean isComplete() {
return done;
}
/**
* Method setComplete.
*
* @param state
*/
public void setComplete(boolean state) {
this.done = state;
if(parent != null){
if(!done) {
parent.setComplete(false);
}else if(parent instanceof OMElementImpl){
((OMElementImpl) parent).notifyChildComplete();
}
}
}
/**
* Removes this information item and its children, from the model completely.
*
* @throws OMException
*/
public OMNode detach() throws OMException {
if (parent == null) {
throw new OMException(
"Elements that doesn't have a parent can not be detached");
}
OMNodeImpl nextSibling = (OMNodeImpl) getNextOMSibling();
if (previousSibling == null) {
parent.setFirstChild(nextSibling);
} else {
((OMNodeEx) getPreviousOMSibling()).setNextOMSibling(nextSibling);
}
if (nextSibling != null) {
nextSibling.setPreviousOMSibling(getPreviousOMSibling());
}
if ((parent instanceof OMElementImpl) && ((OMElementImpl) parent).lastChild == this) {
((OMElementImpl) parent).lastChild = getPreviousOMSibling();
}
this.parent = null;
return this;
}
/**
* Inserts a sibling just after the current information item.
*
* @param sibling
* @throws OMException
*/
public void insertSiblingAfter(OMNode sibling) throws OMException {
if (parent == null) {
throw new OMException("Parent can not be null");
}else if(this == sibling){
throw new OMException("Inserting self as the sibling is not allowed");
}
((OMNodeEx) sibling).setParent(parent);
if (sibling instanceof OMNodeImpl) {
OMNodeImpl siblingImpl = (OMNodeImpl) sibling;
if (nextSibling == null) {
getNextOMSibling();
}
siblingImpl.setPreviousOMSibling(this);
if (nextSibling != null) {
nextSibling.setPreviousOMSibling(sibling);
}
((OMNodeEx) sibling).setNextOMSibling(nextSibling);
nextSibling = siblingImpl;
}
}
/**
* Inserts a sibling just before the current information item.
*
* @param sibling
* @throws OMException
*/
public void insertSiblingBefore(OMNode sibling) throws OMException {
if (parent == null) {
throw new OMException("Parent can not be null");
} else if(this == sibling){
throw new OMException("Inserting self as the sibling is not allowed");
}
if (sibling instanceof OMNodeImpl) {
OMNodeImpl siblingImpl = (OMNodeImpl) sibling;
siblingImpl.nextSibling = this;
if (previousSibling == null) {
parent.setFirstChild(siblingImpl);
siblingImpl.previousSibling = null;
} else {
siblingImpl.setParent(parent);
previousSibling.setNextOMSibling(siblingImpl);
siblingImpl.setPreviousOMSibling(previousSibling);
}
previousSibling = siblingImpl;
}
}
/**
* Gets the type of node, as this is the super class of all the nodes.
*
* @return Returns the type of node as indicated by {@link #setType}
* @see #setType
*/
public int getType() {
return nodeType;
}
/**
* Method setType.
*
* @param nodeType
* @throws OMException
*/
public void setType(int nodeType) throws OMException {
this.nodeType = nodeType;
}
/**
* Gets the previous sibling.
*
* @return boolean
*/
public OMNode getPreviousOMSibling() {
return previousSibling;
}
/**
* Method setPreviousOMSibling.
*
* @param previousSibling
*/
public void setPreviousOMSibling(OMNode previousSibling) {
if (previousSibling ==null || previousSibling.getOMFactory() instanceof OMLinkedListImplFactory) {
this.previousSibling = (OMNodeImpl) previousSibling;
} else {
this.previousSibling = (OMNodeImpl)importNode(previousSibling);
}
}
/**
* Parses this node and builds the object structure in memory.
* However a node, created programmatically, will have done set to true by
* default and this will cause populateyourself not to work properly!
*
* @throws OMException
*/
public void build() throws OMException {
while (!done) {
builder.next();
}
}
/**
* Parses this node and builds the object structure in memory. AXIOM
* supports two levels of deffered building. First is deffered building of
* AXIOM using StAX. Second level is the deffered building of attachments.
* AXIOM reads in the attachements from the stream only when user asks by
* calling getDataHandler(). build() method builds the OM without the
* attachments. buildAll() builds the OM together with attachement data.
* This becomes handy when user wants to free the input stream.
*/
public void buildWithAttachments() {
if (!this.done) {
this.build();
}
}
/**
* Serializes the node with caching.
*
* @param xmlWriter
* @throws javax.xml.stream.XMLStreamException
*/
public void serialize(XMLStreamWriter xmlWriter) throws XMLStreamException {
MTOMXMLStreamWriter writer = new MTOMXMLStreamWriter(xmlWriter);
internalSerialize(writer);
writer.flush();
}
/**
* Serializes the node without caching.
*
* @param xmlWriter
* @throws javax.xml.stream.XMLStreamException
*
*/
public void serializeAndConsume(XMLStreamWriter xmlWriter) throws XMLStreamException {
MTOMXMLStreamWriter writer = new MTOMXMLStreamWriter(xmlWriter);
internalSerializeAndConsume(writer);
writer.flush();
}
/**
* Serializes the node with caching.
*
* @param writer
* @throws XMLStreamException
*/
public void internalSerialize(XMLStreamWriter writer) throws XMLStreamException {
throw new RuntimeException("Not implemented yet!");
}
/**
* Serializes the node without caching.
*
* @param writer
* @throws XMLStreamException
*/
public void internalSerializeAndConsume(XMLStreamWriter writer) throws XMLStreamException {
throw new RuntimeException("Not implemented yet!");
}
public void serialize(OutputStream output) throws XMLStreamException {
serialize(StAXUtils.createXMLStreamWriter(output));
}
public void serialize(Writer writer) throws XMLStreamException {
serialize(StAXUtils.createXMLStreamWriter(writer));
}
public void serializeAndConsume(OutputStream output) throws XMLStreamException {
serializeAndConsume(StAXUtils.createXMLStreamWriter(output));
}
public void serializeAndConsume(Writer writer) throws XMLStreamException {
serializeAndConsume(StAXUtils.createXMLStreamWriter(writer));
}
public void serialize(OutputStream output, OMOutputFormat format) throws XMLStreamException {
MTOMXMLStreamWriter writer = new MTOMXMLStreamWriter(output, format);
internalSerialize(writer);
writer.flush();
}
public void serialize(Writer writer2, OMOutputFormat format) throws XMLStreamException {
MTOMXMLStreamWriter writer = new MTOMXMLStreamWriter(StAXUtils.createXMLStreamWriter(writer2));
writer.setOutputFormat(format);
internalSerialize(writer);
writer.flush();
}
public void serializeAndConsume(OutputStream output, OMOutputFormat format) throws XMLStreamException {
MTOMXMLStreamWriter writer = new MTOMXMLStreamWriter(output, format);
internalSerializeAndConsume(writer);
writer.flush();
}
public void serializeAndConsume(Writer writer2, OMOutputFormat format) throws XMLStreamException {
MTOMXMLStreamWriter writer = new MTOMXMLStreamWriter(StAXUtils.createXMLStreamWriter(writer2));
writer.setOutputFormat(format);
internalSerializeAndConsume(writer);
writer.flush();
}
public OMFactory getOMFactory() {
return this.factory;
}
/**
* This method is intended only to be used by Axiom intenals when merging Objects
* from different Axiom implementations to the LLOM implementation.
*
* @param child
*/
protected OMNode importNode(OMNode child)
{
int type = child.getType();
switch (type) {
case (OMNode.ELEMENT_NODE):
{
OMElement childElement = (OMElement) child;
OMElement newElement = (new StAXOMBuilder(this.factory, childElement
.getXMLStreamReader())).getDocumentElement();
newElement.buildWithAttachments();
return newElement;
}
case (OMNode.TEXT_NODE):
{
OMText importedText = (OMText) child;
OMText newText;
if (importedText.isBinary()) {
boolean isOptimize = importedText.isOptimized();
newText = this.factory.createOMText(importedText
.getDataHandler(), isOptimize);
}
else if (importedText.getNamespace()!=null)
{
newText = this.factory.createOMText(null,importedText.getTextAsQName(),importedText.getType());
}
else if (importedText.isCharacters()) {
newText = this.factory.createOMText(null, importedText
.getTextCharacters(), importedText.getType());
} else {
newText = this.factory.createOMText(null, importedText
.getText()/*, importedText.getOMNodeType()*/);
}
return newText;
}
case (OMNode.PI_NODE): {
OMProcessingInstruction importedPI = (OMProcessingInstruction) child;
OMProcessingInstruction newPI = this.factory
.createOMProcessingInstruction(null, importedPI
.getTarget(), importedPI.getValue());
return newPI;
}
case (OMNode.COMMENT_NODE): {
OMComment importedComment = (OMComment) child;
OMComment newComment = this.factory.createOMComment(null,
importedComment.getValue());
return newComment;
}
case (OMNode.DTD_NODE) :{
OMDocType importedDocType = (OMDocType)child;
OMDocType newDocType = this.factory.createOMDocType(null,importedDocType.getValue());
return newDocType;
}
default: {
throw new UnsupportedOperationException("Not Implemented Yet for the given node type");
}
}
}
}