
org.enhydra.xml.dom.DOMAccess Maven / Gradle / Ivy
/*
* Enhydra Java Application Server Project
*
* The contents of this file are subject to the Enhydra Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License on
* the Enhydra web site ( http://www.enhydra.org/ ).
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific terms governing rights and limitations
* under the License.
*
* The Initial Developer of the Enhydra Application Server is Lutris
* Technologies, Inc. The Enhydra Application Server and portions created
* by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
* All Rights Reserved.
*
* Contributor(s):
*
* $Id: DOMAccess.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
*/
package org.enhydra.xml.dom;
import org.enhydra.xml.lazydom.LazyAttr;
import org.enhydra.xml.lazydom.LazyDocument;
import org.enhydra.xml.lazydom.LazyElement;
import org.enhydra.xml.lazydom.LazyNode;
import org.enhydra.xml.lazydom.LazyParent;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
// FIXME: Some the the access funtionallity might be better implemented
// in the nodes themselves. Maybe this just belongs in the Document
// although they would only be valid in the template document.
//FIXME: most of this not really tested, don';t export until tests
// are written.
/**
* Method to support accessing the LazyDOM without expanding it. This works
* both with standard DOMs and LazyDOMs, supporting the development of code
* that works with either DOM.
*
* Most methods come in two flavors, static ones that take the instance
* document as an argument, an instance methods that use a document contained
* in an instance of this object. Great care should be used if the return
* nodes are to be modified, as read-only template nodes maybe returned.
* These methods also operate on any W3C DOM.
*/
public final class DOMAccess {
/**
* Document being accessed.
*/
private Document fDocument;
/**
* Create a object to access a specific document.
*
* @param document The document to access. if this is a LazyDOM instance
* document, access will switch between the instance and template
* as appropriate.
*/
public DOMAccess(Document document) {
fDocument = document;
}
/**
* Access the document type node.
* @param document The instance document object.
* @return The document type object, or null if there is none.
*/
public static DocumentType accessDocumentType(Document document) {
if (document instanceof LazyDocument) {
LazyDocument lazyDoc = (LazyDocument)document;
if (lazyDoc.isTemplateNode() || lazyDoc.isDocTypeExpanded()) {
return lazyDoc.getDoctype();
} else {
return lazyDoc.getTemplateDocument().getDoctype();
}
} else {
return document.getDoctype();
}
}
/**
* Access the document type node.
* @return The document type object, or null if there is none.
*/
public DocumentType accessDocumentType() {
return accessDocumentType(fDocument);
}
/**
* Access first child of template node, switching to instance document
* if child is expanded.
*/
private static Node accessTemplateFirstChild(LazyDocument lazyDoc,
LazyParent lazyParent) {
LazyNode templateChild = (LazyNode)lazyParent.getFirstChild();
if (templateChild == null) {
return null; // no child
} else if (lazyDoc.isTemplateNode()) {
return templateChild; // Document is a template, not instance
} else {
LazyNode instanceChild = lazyDoc.getExpandedNode(templateChild.getNodeId());
if (instanceChild != null) {
return instanceChild;
} else {
return templateChild;
}
}
}
/**
* Access the first child of a node.
*
* @param document The instance document object.
* @param parent The parent node of the desired child.
* @return The first child or null if there is none.
*/
public static Node accessFirstChild(Document document,
Node parent) {
if (parent instanceof LazyParent) {
LazyParent lazyParent = (LazyParent)parent;
if (lazyParent.isTemplateNode()) {
// parent is template: check if child is expanded
return accessTemplateFirstChild((LazyDocument)document,
lazyParent);
} else if (lazyParent.areChildrenExpanded()) {
// expanded instance children, handle as normal
return lazyParent.getFirstChild();
} else {
// switch to template
return lazyParent.getTemplateNode().getFirstChild();
}
} else {
// standard DOM or LazyDOM node that is not a LazyParent
return parent.getFirstChild();
}
}
/**
* Access the first child of a node.
*
* @param parent The parent node of the desired child.
* @return The first child or null if there is none.
*/
public Node accessFirstChild(Node parent) {
return accessFirstChild(fDocument, parent);
}
/**
* Access next sibling child of template node, switching to instance
* document if sibling is expanded.
*/
private static Node accessTemplateNextSibling(LazyDocument lazyDoc,
LazyNode templateNode) {
LazyNode templateSibling = (LazyNode)templateNode.getNextSibling();
if (templateSibling == null) {
return null; // no sibling
} else {
LazyNode instanceSibling = lazyDoc.getExpandedNode(templateSibling.getNodeId());
if (instanceSibling != null) {
return instanceSibling;
} else {
return templateSibling;
}
}
}
/**
* Access next sibling child of instance node, switching to template
* document if sibling is not expanded.
*/
private static Node accessInstanceNextSibling(LazyDocument lazyDoc,
LazyNode instanceNode) {
if (instanceNode instanceof LazyParent) {
// Node is a LazyParent, sibling will be expanded if parent is
// expanded. It may or may not be expanded if parent is not
// expanded.
if (((LazyParent)instanceNode).isParentExpanded()) {
return instanceNode.getNextSibling();
} else {
// Check if sibling is expanded is expanded
LazyNode templateNode = instanceNode.getTemplateNode();
LazyNode templateSibling = (LazyNode)instanceNode.getNextSibling();
if (templateSibling != null) {
LazyNode instanceSibling = lazyDoc.getExpandedNode(templateSibling.getNodeId());
if (instanceSibling != null) {
return instanceSibling;
} else {
return templateSibling;
}
} else {
return null; // No sibling
}
}
} else {
// Node is not a LazyParent, sibling must be expanded
return instanceNode.getNextSibling();
}
}
/**
* Access the next sibling of a node.
*
* @param document The instance document object.
* @param node Get the next sibling of this node
* @return The first child or null if there is none.
*/
public static Node accessNextSibling(Document document,
Node node) {
if (node instanceof LazyNode) {
LazyNode lazyNode = (LazyNode)node;
if (lazyNode.isTemplateNode()) {
// node is template: check if sibling is expanded
return accessTemplateNextSibling((LazyDocument)document,
lazyNode);
} else {
return accessInstanceNextSibling((LazyDocument)document,
lazyNode);
}
} else {
// standard DOM
return node.getNextSibling();
}
}
/**
* Access the next sibling of a node.
*
* @param node Get the next sibling of this node
* @return The first child or null if there is none.
*/
public Node accessNextSibling(Node node) {
return accessNextSibling(fDocument, node);
}
/**
* Access the document element of a document.
*
* @param document The instance document object.
* @return The document element.
*/
public static Element accessDocumentElement(Document document) {
if (document instanceof LazyDocument) {
Node child = accessFirstChild(document, document);
while (child != null) {
if (child instanceof Element) {
break;
}
child = accessNextSibling(document, child);
}
return (Element)child;
} else {
return document.getDocumentElement();
}
}
/**
* Access the document element of the document.
*
* @return The document element.
*/
public Element accessDocumentElement() {
return accessDocumentElement(fDocument);
}
/**
* Access an attribute of an Element.
*
* @param document The instance document object.
* @param element The Element node.
* @param namespaceURI The namespace URI, or null if there is none.
* @param name The name of the attribute.
* @return The attribute node, or null if it does not exist. The value
* should be accessed via accessAttributeValue().
*/
public static Attr accessAttribute(Document document,
Element element,
String namespaceURI,
String name) {
// Find the element (template or instance) to use to obtain the
// attribute
Element accessElement;
if (element instanceof LazyElement) {
LazyElement lazyElement = (LazyElement)element;
if (lazyElement.areAttributesExpanded()) {
// template or expanded instance, just get attribute
accessElement = lazyElement;
} else {
// instance and attributes not expanded, get from template
accessElement = lazyElement.getTemplateElement();
}
} else {
// not a Lazy DOM, just get attribute
accessElement = element;
}
// Get with or without namespace
if (namespaceURI != null) {
return accessElement.getAttributeNodeNS(namespaceURI, name);
} else {
return accessElement.getAttributeNode(name);
}
}
/**
* Access an attribute of an Element.
*
* @param element The Element node.
* @param namespaceURI The namespace URI, or null if there is none.
* @param name The name of the attribute.
* @return The attribute node, or null if it does not exist. The value
* should be accessed via accessAttributeValue().
*/
public Attr accessAttribute(Element element,
String namespaceURI,
String name) {
return accessAttribute(fDocument, element, namespaceURI, name);
}
/**
* Access the value of an attribute
*
* @param document The instance document object.
* @param attr The Attr node.
* @return The value of the attribute, as a string.
*/
public static String accessAttributeValue(Document document,
Attr attr) {
if (attr instanceof LazyAttr) {
LazyAttr lazyAttr = (LazyAttr)attr;
if (lazyAttr.areChildrenExpanded()) {
// template or expanded instance, just get value
return lazyAttr.getValue();
} else {
// instance and children not expanded, get from template
return ((LazyAttr)lazyAttr.getTemplateNode()).getValue();
}
} else {
// not a Lazy DOM, just get the value
return attr.getValue();
}
}
/**
* Access the value of an attribute
*
* @param attr The Attr node.
* @return The value of the attribute, as a string.
*/
public String accessAttributeValue(Attr attr) {
return accessAttributeValue(fDocument, attr);
}
/**
* If a Node is a LazyDOM template node, expand it.
*
* @param document The instance document object.
* @param node A node of the document or it's template.
* @return The expanded node, or the node unchanged
* if it is not a LazyDOM template.
*/
public static Node getExpandedNode(Document document,
Node node) {
if ((node instanceof LazyNode) && ((LazyNode)node).isTemplateNode()) {
return (Node)((LazyDocument)document).getNodeById(((LazyNode)node).getNodeId());
} else {
return node;
}
}
/**
* If a Node is a LazyDOM template node, expand it.
*
* @param node A node of the document or it's template.
* @return The expanded node, or the node unchanged
* if it is not a LazyDOM template.
*/
public Node getExpandedNode(Node node) {
return getExpandedNode(fDocument, node);
}
/**
* If an Element node is a LazyDOM template, expand it.
* This is a special case of getExpandedNode().
*
* @param document The instance document object.
* @param element An element of the document or it's template.
* @return The expanded element, or the element unchanged
* if it is not a LazyDOM template.
*/
public static Element getExpandedElement(Document document,
Element element) {
if ((element instanceof LazyElement) && ((LazyElement)element).isTemplateNode()) {
return (Element)((LazyDocument)document).getNodeById(((LazyElement)element).getNodeId());
} else {
return element;
}
}
/**
* If an Element node is a LazyDOM template, expand it
* This is a special case of getExpandedNode().
*
* @param element An element of the document or template.
* @return The expanded element, or the element unchanged
* if it is not a LazyDOM template.
*/
public Element getExpandedElement(Element element) {
return getExpandedElement(fDocument, element);
}
}