/*
* Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
*
* This software is open source.
* See the bottom of this file for the licence.
*/
package org.dom4j.tree;
import java.util.
ArrayList;
import java.util.
Iterator;
import java.util.
List;
import org.dom4j.
Attribute;
import org.dom4j.
Branch;
import org.dom4j.
Document;
import org.dom4j.
DocumentFactory;
import org.dom4j.
Element;
import org.dom4j.
IllegalAddException;
import org.dom4j.
Namespace;
import org.dom4j.
Node;
import org.dom4j.
ProcessingInstruction;
import org.dom4j.
QName;
/**
* <p>
* <code>DefaultElement</code> is the default DOM4J default implementation of
* an XML element.
* </p>
*
* @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
* @version $Revision: 1.59 $
*/
public class
DefaultElement extends
AbstractElement {
/** The <code>DocumentFactory</code> instance used by default */
private static final transient
DocumentFactory DOCUMENT_FACTORY =
DocumentFactory.
getInstance();
/** The <code>QName</code> for this element */
private
QName qname;
/**
* Stores the parent branch of this node which is either a Document if this
* element is the root element in a document, or another Element if it is a
* child of the root document, or null if it has not been added to a
* document yet.
*/
private
Branch parentBranch;
/**
* Stores null for no content, a Node for a single content node or a List
* for multiple content nodes. The List will be lazily constructed when
* required.
*/
private
Object content;
/** Lazily constructes list of attributes */
private
Object attributes;
public
DefaultElement(
String name) {
this.
qname =
DOCUMENT_FACTORY.
createQName(
name);
}
public
DefaultElement(
QName qname) {
this.
qname =
qname;
}
public
DefaultElement(
QName qname, int
attributeCount) {
this.
qname =
qname;
if (
attributeCount > 1) {
this.
attributes = new
ArrayList(
attributeCount);
}
}
public
DefaultElement(
String name,
Namespace namespace) {
this.
qname =
DOCUMENT_FACTORY.
createQName(
name,
namespace);
}
public
Element getParent() {
Element result = null;
if (
parentBranch instanceof
Element) {
result = (
Element)
parentBranch;
}
return
result;
}
public void
setParent(
Element parent) {
if (
parentBranch instanceof
Element || (
parent != null)) {
parentBranch =
parent;
}
}
public
Document getDocument() {
if (
parentBranch instanceof
Document) {
return (
Document)
parentBranch;
} else if (
parentBranch instanceof
Element) {
Element parent = (
Element)
parentBranch;
return
parent.
getDocument();
}
return null;
}
public void
setDocument(
Document document) {
if (
parentBranch instanceof
Document || (
document != null)) {
parentBranch =
document;
}
}
public boolean
supportsParent() {
return true;
}
public
QName getQName() {
return
qname;
}
public void
setQName(
QName name) {
this.
qname =
name;
}
public
String getText() {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
return super.getText();
} else {
if (
contentShadow != null) {
return
getContentAsText(
contentShadow);
} else {
return "";
}
}
}
public
String getStringValue() {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
int
size =
list.
size();
if (
size > 0) {
if (
size == 1) {
// optimised to avoid StringBuffer creation
return
getContentAsStringValue(
list.
get(0));
} else {
StringBuffer buffer = new
StringBuffer();
for (int
i = 0;
i <
size;
i++) {
Object node =
list.
get(
i);
String string =
getContentAsStringValue(
node);
if (
string.
length() > 0) {
if (
USE_STRINGVALUE_SEPARATOR) {
if (
buffer.
length() > 0) {
buffer.
append(' ');
}
}
buffer.
append(
string);
}
}
return
buffer.
toString();
}
}
} else {
if (
contentShadow != null) {
return
getContentAsStringValue(
contentShadow);
}
}
return "";
}
public
Object clone() {
DefaultElement answer = (
DefaultElement) super.clone();
if (
answer != this) {
answer.
content = null;
answer.
attributes = null;
answer.
appendAttributes(this);
answer.
appendContent(this);
}
return
answer;
}
public
Namespace getNamespaceForPrefix(
String prefix) {
if (
prefix == null) {
prefix = "";
}
if (
prefix.
equals(
getNamespacePrefix())) {
return
getNamespace();
} else if (
prefix.
equals("xml")) {
return
Namespace.
XML_NAMESPACE;
} else {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Object object =
list.
get(
i);
if (
object instanceof
Namespace) {
Namespace namespace = (
Namespace)
object;
if (
prefix.
equals(
namespace.
getPrefix())) {
return
namespace;
}
}
}
} else if (
contentShadow instanceof
Namespace) {
Namespace namespace = (
Namespace)
contentShadow;
if (
prefix.
equals(
namespace.
getPrefix())) {
return
namespace;
}
}
}
Element parent =
getParent();
if (
parent != null) {
Namespace answer =
parent.
getNamespaceForPrefix(
prefix);
if (
answer != null) {
return
answer;
}
}
if ((
prefix == null) || (
prefix.
length() <= 0)) {
return
Namespace.
NO_NAMESPACE;
}
return null;
}
public
Namespace getNamespaceForURI(
String uri) {
if ((
uri == null) || (
uri.
length() <= 0)) {
return
Namespace.
NO_NAMESPACE;
} else if (
uri.
equals(
getNamespaceURI())) {
return
getNamespace();
} else {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Object object =
list.
get(
i);
if (
object instanceof
Namespace) {
Namespace namespace = (
Namespace)
object;
if (
uri.
equals(
namespace.
getURI())) {
return
namespace;
}
}
}
} else if (
contentShadow instanceof
Namespace) {
Namespace namespace = (
Namespace)
contentShadow;
if (
uri.
equals(
namespace.
getURI())) {
return
namespace;
}
}
Element parent =
getParent();
if (
parent != null) {
return
parent.
getNamespaceForURI(
uri);
}
return null;
}
}
public
List declaredNamespaces() {
BackedList answer =
createResultList();
// if (getNamespaceURI().length() > 0) {
//
// answer.addLocal(getNamespace());
//
// }
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Object object =
list.
get(
i);
if (
object instanceof
Namespace) {
answer.
addLocal(
object);
}
}
} else {
if (
contentShadow instanceof
Namespace) {
answer.
addLocal(
contentShadow);
}
}
return
answer;
}
public
List additionalNamespaces() {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
int
size =
list.
size();
BackedList answer =
createResultList();
for (int
i = 0;
i <
size;
i++) {
Object object =
list.
get(
i);
if (
object instanceof
Namespace) {
Namespace namespace = (
Namespace)
object;
if (!
namespace.
equals(
getNamespace())) {
answer.
addLocal(
namespace);
}
}
}
return
answer;
} else {
if (
contentShadow instanceof
Namespace) {
Namespace namespace = (
Namespace)
contentShadow;
if (
namespace.
equals(
getNamespace())) {
return
createEmptyList();
}
return
createSingleResultList(
namespace);
} else {
return
createEmptyList();
}
}
}
public
List additionalNamespaces(
String defaultNamespaceURI) {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
BackedList answer =
createResultList();
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Object object =
list.
get(
i);
if (
object instanceof
Namespace) {
Namespace namespace = (
Namespace)
object;
if (!
defaultNamespaceURI.
equals(
namespace.
getURI())) {
answer.
addLocal(
namespace);
}
}
}
return
answer;
} else {
if (
contentShadow instanceof
Namespace) {
Namespace namespace = (
Namespace)
contentShadow;
if (!
defaultNamespaceURI.
equals(
namespace.
getURI())) {
return
createSingleResultList(
namespace);
}
}
}
return
createEmptyList();
}
// Processing instruction API
public
List processingInstructions() {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
BackedList answer =
createResultList();
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Object object =
list.
get(
i);
if (
object instanceof
ProcessingInstruction) {
answer.
addLocal(
object);
}
}
return
answer;
} else {
if (
contentShadow instanceof
ProcessingInstruction) {
return
createSingleResultList(
contentShadow);
}
return
createEmptyList();
}
}
public
List processingInstructions(
String target) {
final
Object shadow =
content;
if (
shadow instanceof
List) {
List list = (
List)
shadow;
BackedList answer =
createResultList();
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Object object =
list.
get(
i);
if (
object instanceof
ProcessingInstruction) {
ProcessingInstruction pi = (
ProcessingInstruction)
object;
if (
target.
equals(
pi.
getName())) {
answer.
addLocal(
pi);
}
}
}
return
answer;
} else {
if (
shadow instanceof
ProcessingInstruction) {
ProcessingInstruction pi = (
ProcessingInstruction)
shadow;
if (
target.
equals(
pi.
getName())) {
return
createSingleResultList(
pi);
}
}
return
createEmptyList();
}
}
public
ProcessingInstruction processingInstruction(
String target) {
final
Object shadow =
content;
if (
shadow instanceof
List) {
List list = (
List)
shadow;
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Object object =
list.
get(
i);
if (
object instanceof
ProcessingInstruction) {
ProcessingInstruction pi = (
ProcessingInstruction)
object;
if (
target.
equals(
pi.
getName())) {
return
pi;
}
}
}
} else {
if (
shadow instanceof
ProcessingInstruction) {
ProcessingInstruction pi = (
ProcessingInstruction)
shadow;
if (
target.
equals(
pi.
getName())) {
return
pi;
}
}
}
return null;
}
public boolean
removeProcessingInstruction(
String target) {
final
Object shadow =
content;
if (
shadow instanceof
List) {
List list = (
List)
shadow;
for (
Iterator iter =
list.
iterator();
iter.
hasNext();) {
Object object =
iter.
next();
if (
object instanceof
ProcessingInstruction) {
ProcessingInstruction pi = (
ProcessingInstruction)
object;
if (
target.
equals(
pi.
getName())) {
iter.
remove();
return true;
}
}
}
} else {
if (
shadow instanceof
ProcessingInstruction) {
ProcessingInstruction pi = (
ProcessingInstruction)
shadow;
if (
target.
equals(
pi.
getName())) {
this.
content = null;
return true;
}
}
}
return false;
}
public
Element element(
String name) {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Object object =
list.
get(
i);
if (
object instanceof
Element) {
Element element = (
Element)
object;
if (
name.
equals(
element.
getName())) {
return
element;
}
}
}
} else {
if (
contentShadow instanceof
Element) {
Element element = (
Element)
contentShadow;
if (
name.
equals(
element.
getName())) {
return
element;
}
}
}
return null;
}
public
Element element(
QName qName) {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Object object =
list.
get(
i);
if (
object instanceof
Element) {
Element element = (
Element)
object;
if (
qName.
equals(
element.
getQName())) {
return
element;
}
}
}
} else {
if (
contentShadow instanceof
Element) {
Element element = (
Element)
contentShadow;
if (
qName.
equals(
element.
getQName())) {
return
element;
}
}
}
return null;
}
public
Element element(
String name,
Namespace namespace) {
return
element(
getDocumentFactory().
createQName(
name,
namespace));
}
public void
setContent(
List content) {
contentRemoved();
if (
content instanceof
ContentListFacade) {
content = ((
ContentListFacade)
content).
getBackingList();
}
if (
content == null) {
this.
content = null;
} else {
int
size =
content.
size();
List newContent =
createContentList(
size);
for (int
i = 0;
i <
size;
i++) {
Object object =
content.
get(
i);
if (
object instanceof
Node) {
Node node = (
Node)
object;
Element parent =
node.
getParent();
if ((
parent != null) && (
parent != this)) {
node = (
Node)
node.
clone();
}
newContent.
add(
node);
childAdded(
node);
} else if (
object != null) {
String text =
object.
toString();
Node node =
getDocumentFactory().
createText(
text);
newContent.
add(
node);
childAdded(
node);
}
}
this.
content =
newContent;
}
}
public void
clearContent() {
if (
content != null) {
contentRemoved();
content = null;
}
}
public
Node node(int
index) {
if (
index >= 0) {
final
Object contentShadow =
content;
Object node;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
if (
index >=
list.
size()) {
return null;
}
node =
list.
get(
index);
} else {
node = (
index == 0) ?
contentShadow : null;
}
if (
node != null) {
if (
node instanceof
Node) {
return (
Node)
node;
} else {
return new
DefaultText(
node.
toString());
}
}
}
return null;
}
public int
indexOf(
Node node) {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
return
list.
indexOf(
node);
} else {
if ((
contentShadow != null) &&
contentShadow.
equals(
node)) {
return 0;
} else {
return -1;
}
}
}
public int
nodeCount() {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
return
list.
size();
} else {
return (
contentShadow != null) ? 1 : 0;
}
}
public
Iterator nodeIterator() {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
return
list.
iterator();
} else {
if (
contentShadow != null) {
return
createSingleIterator(
contentShadow);
} else {
return
EMPTY_ITERATOR;
}
}
}
public
List attributes() {
return new
ContentListFacade(this,
attributeList());
}
public void
setAttributes(
List attributes) {
if (
attributes instanceof
ContentListFacade) {
attributes = ((
ContentListFacade)
attributes).
getBackingList();
}
this.
attributes =
attributes;
}
public
Iterator attributeIterator() {
final
Object attributesShadow = this.
attributes;
if (
attributesShadow instanceof
List) {
List list = (
List)
attributesShadow;
return
list.
iterator();
} else if (
attributesShadow != null) {
return
createSingleIterator(
attributesShadow);
} else {
return
EMPTY_ITERATOR;
}
}
public
Attribute attribute(int
index) {
final
Object attributesShadow = this.
attributes;
if (
attributesShadow instanceof
List) {
List list = (
List)
attributesShadow;
return (
Attribute)
list.
get(
index);
} else if ((
attributesShadow != null) && (
index == 0)) {
return (
Attribute)
attributesShadow;
} else {
return null;
}
}
public int
attributeCount() {
final
Object attributesShadow = this.
attributes;
if (
attributesShadow instanceof
List) {
List list = (
List)
attributesShadow;
return
list.
size();
} else {
return (
attributesShadow != null) ? 1 : 0;
}
}
public
Attribute attribute(
String name) {
final
Object attributesShadow = this.
attributes;
if (
attributesShadow instanceof
List) {
List list = (
List)
attributesShadow;
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Attribute attribute = (
Attribute)
list.
get(
i);
if (
name.
equals(
attribute.
getName())) {
return
attribute;
}
}
} else if (
attributesShadow != null) {
Attribute attribute = (
Attribute)
attributesShadow;
if (
name.
equals(
attribute.
getName())) {
return
attribute;
}
}
return null;
}
public
Attribute attribute(
QName qName) {
final
Object attributesShadow = this.
attributes;
if (
attributesShadow instanceof
List) {
List list = (
List)
attributesShadow;
int
size =
list.
size();
for (int
i = 0;
i <
size;
i++) {
Attribute attribute = (
Attribute)
list.
get(
i);
if (
qName.
equals(
attribute.
getQName())) {
return
attribute;
}
}
} else if (
attributesShadow != null) {
Attribute attribute = (
Attribute)
attributesShadow;
if (
qName.
equals(
attribute.
getQName())) {
return
attribute;
}
}
return null;
}
public
Attribute attribute(
String name,
Namespace namespace) {
return
attribute(
getDocumentFactory().
createQName(
name,
namespace));
}
public void
add(
Attribute attribute) {
if (
attribute.
getParent() != null) {
String message = "The Attribute already has an existing parent \""
+
attribute.
getParent().
getQualifiedName() + "\"";
throw new
IllegalAddException(this,
attribute,
message);
}
if (
attribute.
getValue() == null) {
// try remove a previous attribute with the same
// name since adding an attribute with a null value
// is equivalent to removing it.
Attribute oldAttribute =
attribute(
attribute.
getQName());
if (
oldAttribute != null) {
remove(
oldAttribute);
}
} else {
if (
attributes == null) {
attributes =
attribute;
} else {
attributeList().
add(
attribute);
}
childAdded(
attribute);
}
}
public boolean
remove(
Attribute attribute) {
boolean
answer = false;
final
Object attributesShadow = this.
attributes;
if (
attributesShadow instanceof
List) {
List list = (
List)
attributesShadow;
answer =
list.
remove(
attribute);
if (!
answer) {
// we may have a copy of the attribute
Attribute copy =
attribute(
attribute.
getQName());
if (
copy != null) {
list.
remove(
copy);
answer = true;
}
}
} else if (
attributesShadow != null) {
if (
attribute.
equals(
attributesShadow)) {
this.
attributes = null;
answer = true;
} else {
// we may have a copy of the attribute
Attribute other = (
Attribute)
attributesShadow;
if (
attribute.
getQName().
equals(
other.
getQName())) {
attributes = null;
answer = true;
}
}
}
if (
answer) {
childRemoved(
attribute);
}
return
answer;
}
// Implementation methods
// -------------------------------------------------------------------------
protected void
addNewNode(
Node node) {
final
Object contentShadow =
content;
if (
contentShadow == null) {
this.
content =
node;
} else {
if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
list.
add(
node);
} else {
List list =
createContentList();
list.
add(
contentShadow);
list.
add(
node);
this.
content =
list;
}
}
childAdded(
node);
}
protected boolean
removeNode(
Node node) {
boolean
answer = false;
final
Object contentShadow =
content;
if (
contentShadow != null) {
if (
contentShadow ==
node) {
this.
content = null;
answer = true;
} else if (
contentShadow instanceof
List) {
List list = (
List)
contentShadow;
answer =
list.
remove(
node);
}
}
if (
answer) {
childRemoved(
node);
}
return
answer;
}
protected
List contentList() {
final
Object contentShadow =
content;
if (
contentShadow instanceof
List) {
return (
List)
contentShadow;
} else {
List list =
createContentList();
if (
contentShadow != null) {
list.
add(
contentShadow);
}
this.
content =
list;
return
list;
}
}
protected
List attributeList() {
final
Object attributesShadow = this.
attributes;
if (
attributesShadow instanceof
List) {
return (
List)
attributesShadow;
} else if (
attributesShadow != null) {
List list =
createAttributeList();
list.
add(
attributesShadow);
this.
attributes =
list;
return
list;
} else {
List list =
createAttributeList();
this.
attributes =
list;
return
list;
}
}
protected
List attributeList(int
size) {
final
Object attributesShadow = this.
attributes;
if (
attributesShadow instanceof
List) {
return (
List)
attributesShadow;
} else if (
attributesShadow != null) {
List list =
createAttributeList(
size);
list.
add(
attributesShadow);
this.
attributes =
list;
return
list;
} else {
List list =
createAttributeList(
size);
this.
attributes =
list;
return
list;
}
}
protected void
setAttributeList(
List attributeList) {
this.
attributes =
attributeList;
}
protected
DocumentFactory getDocumentFactory() {
DocumentFactory factory =
qname.
getDocumentFactory();
return (
factory != null) ?
factory :
DOCUMENT_FACTORY;
}
}
/*
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain copyright statements and
* notices. Redistributions must also contain a copy of this document.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name "DOM4J" must not be used to endorse or promote products derived
* from this Software without prior written permission of MetaStuff, Ltd. For
* written permission, please contact dom4j-info@metastuff.com.
*
* 4. Products derived from this Software may not be called "DOM4J" nor may
* "DOM4J" appear in their names without prior written permission of MetaStuff,
* Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
*
* 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
*
* THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
*/