Source code: org/enhydra/xml/dom/DOMAccess.java
1 /*
2 * Enhydra Java Application Server Project
3 *
4 * The contents of this file are subject to the Enhydra Public License
5 * Version 1.1 (the "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy of the License on
7 * the Enhydra web site ( http://www.enhydra.org/ ).
8 *
9 * Software distributed under the License is distributed on an "AS IS"
10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11 * the License for the specific terms governing rights and limitations
12 * under the License.
13 *
14 * The Initial Developer of the Enhydra Application Server is Lutris
15 * Technologies, Inc. The Enhydra Application Server and portions created
16 * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17 * All Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * $Id: DOMAccess.java,v 1.1.2.3 2000/12/06 02:05:43 markd Exp $
22 */
23
24 package org.enhydra.xml.dom;
25
26 import org.w3c.dom.Document;
27 import org.w3c.dom.DocumentType;
28 import org.w3c.dom.Element;
29 import org.w3c.dom.Attr;
30 import org.w3c.dom.Node;
31 import org.enhydra.xml.lazydom.LazyDocument;
32 import org.enhydra.xml.lazydom.LazyParent;
33 import org.enhydra.xml.lazydom.LazyElement;
34 import org.enhydra.xml.lazydom.LazyNode;
35 import org.enhydra.xml.lazydom.LazyAttr;
36 import org.enhydra.xml.xmlc.XMLObject;
37
38 // FIXME: Some the the access funtionallity might be better implemented
39 // in the nodes themselves. Maybe this just belongs in the Document
40 // although they would only be valid in the template document.
41
42 //FIXME: most of this not really tested, don';t export until tests
43 // are written.
44
45 /**
46 * Method to support accessing the LazyDOM without expanding it. This works
47 * both with standard DOMs and LazyDOMs, supporting the development of code
48 * that works with either DOM.
49 * <p>
50 * Most methods come in two flavors, static ones that take the instance
51 * document as an argument, an instance methods that use a document contained
52 * in an instance of this object. Great care should be used if the return
53 * nodes are to be modified, as read-only template nodes maybe returned.
54 * These methods also operate on any W3C DOM.
55 */
56 public final class DOMAccess {
57 /**
58 * Document being accessed.
59 */
60 private Document fDocument;
61
62 /**
63 * Create a object to access a specific document.
64 *
65 * @param document The document to access. if this is a LazyDOM instance
66 * document, access will switch between the instance and template
67 * as appropriate.
68 */
69 public DOMAccess(Document document) {
70 fDocument = document;
71 }
72
73 /**
74 * Access the document type node.
75 * @param document The instance document object.
76 * @return The document type object, or null if there is none.
77 */
78 public static DocumentType accessDocumentType(Document document) {
79 if (document instanceof LazyDocument) {
80 LazyDocument lazyDoc = (LazyDocument)document;
81 if (lazyDoc.isTemplateNode() || lazyDoc.isDocTypeExpanded()) {
82 return lazyDoc.getDoctype();
83 } else {
84 return lazyDoc.getTemplateDocument().getDoctype();
85 }
86 } else {
87 return document.getDoctype();
88 }
89 }
90
91 /**
92 * Access the document type node.
93 * @return The document type object, or null if there is none.
94 */
95 public DocumentType accessDocumentType() {
96 return accessDocumentType(fDocument);
97 }
98
99 /**
100 * Access first child of template node, switching to instance document
101 * if child is expanded.
102 */
103 private static Node accessTemplateFirstChild(LazyDocument lazyDoc,
104 LazyParent lazyParent) {
105 LazyNode templateChild = (LazyNode)lazyParent.getFirstChild();
106 if (templateChild == null) {
107 return null; // no child
108 } else if (lazyDoc.isTemplateNode()) {
109 return templateChild; // Document is a template, not instance
110 } else {
111 LazyNode instanceChild = lazyDoc.getExpandedNode(templateChild.getNodeId());
112 if (instanceChild != null) {
113 return instanceChild;
114 } else {
115 return templateChild;
116 }
117 }
118 }
119
120 /**
121 * Access the first child of a node.
122 *
123 * @param document The instance document object.
124 * @param parent The parent node of the desired child.
125 * @return The first child or null if there is none.
126 */
127 public static Node accessFirstChild(Document document,
128 Node parent) {
129 if (parent instanceof LazyParent) {
130 LazyParent lazyParent = (LazyParent)parent;
131 if (lazyParent.isTemplateNode()) {
132 // parent is template: check if child is expanded
133 return accessTemplateFirstChild((LazyDocument)document,
134 lazyParent);
135 } else if (lazyParent.areChildrenExpanded()) {
136 // expanded instance children, handle as normal
137 return lazyParent.getFirstChild();
138 } else {
139 // switch to template
140 return lazyParent.getTemplateNode().getFirstChild();
141 }
142 } else {
143 // standard DOM or LazyDOM node that is not a LazyParent
144 return parent.getFirstChild();
145 }
146 }
147
148 /**
149 * Access the first child of a node.
150 *
151 * @param parent The parent node of the desired child.
152 * @return The first child or null if there is none.
153 */
154 public Node accessFirstChild(Node parent) {
155 return accessFirstChild(fDocument, parent);
156 }
157
158 /**
159 * Access next sibling child of template node, switching to instance
160 * document if sibling is expanded.
161 */
162 private static Node accessTemplateNextSibling(LazyDocument lazyDoc,
163 LazyNode templateNode) {
164 LazyNode templateSibling = (LazyNode)templateNode.getNextSibling();
165 if (templateSibling == null) {
166 return null; // no sibling
167 } else {
168 LazyNode instanceSibling = lazyDoc.getExpandedNode(templateSibling.getNodeId());
169 if (instanceSibling != null) {
170 return instanceSibling;
171 } else {
172 return templateSibling;
173 }
174 }
175 }
176
177 /**
178 * Access next sibling child of instance node, switching to template
179 * document if sibling is not expanded.
180 */
181 private static Node accessInstanceNextSibling(LazyDocument lazyDoc,
182 LazyNode instanceNode) {
183 if (instanceNode instanceof LazyParent) {
184 // Node is a LazyParent, sibling will be expanded if parent is
185 // expanded. It may or may not be expanded if parent is not
186 // expanded.
187 if (((LazyParent)instanceNode).isParentExpanded()) {
188 return instanceNode.getNextSibling();
189 } else {
190 // Check if sibling is expanded is expanded
191 LazyNode templateNode = instanceNode.getTemplateNode();
192 LazyNode templateSibling = (LazyNode)instanceNode.getNextSibling();
193 if (templateSibling != null) {
194 LazyNode instanceSibling = lazyDoc.getExpandedNode(templateSibling.getNodeId());
195 if (instanceSibling != null) {
196 return instanceSibling;
197 } else {
198 return templateSibling;
199 }
200 } else {
201 return null; // No sibling
202 }
203 }
204 } else {
205 // Node is not a LazyParent, sibling must be expanded
206 return instanceNode.getNextSibling();
207 }
208 }
209
210 /**
211 * Access the next sibling of a node.
212 *
213 * @param document The instance document object.
214 * @param node Get the next sibling of this node
215 * @return The first child or null if there is none.
216 */
217 public static Node accessNextSibling(Document document,
218 Node node) {
219 if (node instanceof LazyNode) {
220 LazyNode lazyNode = (LazyNode)node;
221 if (lazyNode.isTemplateNode()) {
222 // node is template: check if sibling is expanded
223 return accessTemplateNextSibling((LazyDocument)document,
224 lazyNode);
225 } else {
226 return accessInstanceNextSibling((LazyDocument)document,
227 lazyNode);
228 }
229 } else {
230 // standard DOM
231 return node.getNextSibling();
232 }
233 }
234
235 /**
236 * Access the next sibling of a node.
237 *
238 * @param node Get the next sibling of this node
239 * @return The first child or null if there is none.
240 */
241 public Node accessNextSibling(Node node) {
242 return accessNextSibling(fDocument, node);
243 }
244
245 /**
246 * Access the document element of a document.
247 *
248 * @param document The instance document object.
249 * @return The document element.
250 */
251 public static Element accessDocumentElement(Document document) {
252 if (document instanceof LazyDocument) {
253 Node child = accessFirstChild(document, document);
254 while (child != null) {
255 if (child instanceof Element) {
256 break;
257 }
258 child = accessNextSibling(document, child);
259 }
260 return (Element)child;
261 } else {
262 return document.getDocumentElement();
263 }
264 }
265
266 /**
267 * Access the document element of the document.
268 *
269 * @return The document element.
270 */
271 public Element accessDocumentElement() {
272 return accessDocumentElement(fDocument);
273 }
274
275 /**
276 * Access an attribute of an Element.
277 *
278 * @param document The instance document object.
279 * @param element The Element node.
280 * @param namespaceURI The namespace URI, or null if there is none.
281 * @param name The name of the attribute.
282 * @return The attribute node, or null if it does not exist. The value
283 * should be accessed via accessAttributeValue().
284 */
285 public static Attr accessAttribute(Document document,
286 Element element,
287 String namespaceURI,
288 String name) {
289 // Find the element (template or instance) to use to obtain the
290 // attribute
291 Element accessElement;
292 if (element instanceof LazyElement) {
293 LazyElement lazyElement = (LazyElement)element;
294 if (lazyElement.areAttributesExpanded()) {
295 // template or expanded instance, just get attribute
296 accessElement = lazyElement;
297 } else {
298 // instance and attributes not expanded, get from template
299 accessElement = lazyElement.getTemplateElement();
300 }
301 } else {
302 // not a Lazy DOM, just get attribute
303 accessElement = element;
304 }
305
306 // Get with or without namespace
307 if (namespaceURI != null) {
308 return accessElement.getAttributeNodeNS(namespaceURI, name);
309 } else {
310 return accessElement.getAttributeNode(name);
311 }
312 }
313
314 /**
315 * Access an attribute of an Element.
316 *
317 * @param element The Element node.
318 * @param namespaceURI The namespace URI, or null if there is none.
319 * @param name The name of the attribute.
320 * @return The attribute node, or null if it does not exist. The value
321 * should be accessed via accessAttributeValue().
322 */
323 public Attr accessAttribute(Element element,
324 String namespaceURI,
325 String name) {
326 return accessAttribute(fDocument, element, namespaceURI, name);
327 }
328
329 /**
330 * Access the value of an attribute
331 *
332 * @param document The instance document object.
333 * @param attr The Attr node.
334 * @return The value of the attribute, as a string.
335 */
336 public static String accessAttributeValue(Document document,
337 Attr attr) {
338 if (attr instanceof LazyAttr) {
339 LazyAttr lazyAttr = (LazyAttr)attr;
340 if (lazyAttr.areChildrenExpanded()) {
341 // template or expanded instance, just get value
342 return lazyAttr.getValue();
343 } else {
344 // instance and children not expanded, get from template
345 return ((LazyAttr)lazyAttr.getTemplateNode()).getValue();
346 }
347 } else {
348 // not a Lazy DOM, just get the value
349 return attr.getValue();
350 }
351 }
352
353 /**
354 * Access the value of an attribute
355 *
356 * @param attr The Attr node.
357 * @return The value of the attribute, as a string.
358 */
359 public String accessAttributeValue(Attr attr) {
360 return accessAttributeValue(fDocument, attr);
361 }
362
363 /**
364 * If a Node is a LazyDOM template node, expand it.
365 *
366 * @param document The instance document object.
367 * @param node A node of the document or it's template.
368 * @return The expanded node, or the node unchanged
369 * if it is not a LazyDOM template.
370 */
371 public static Node getExpandedNode(Document document,
372 Node node) {
373 if ((node instanceof LazyNode) && ((LazyNode)node).isTemplateNode()) {
374 return (Node)((LazyDocument)document).getNodeById(((LazyNode)node).getNodeId());
375 } else {
376 return node;
377 }
378 }
379
380 /**
381 * If a Node is a LazyDOM template node, expand it.
382 *
383 * @param node A node of the document or it's template.
384 * @return The expanded node, or the node unchanged
385 * if it is not a LazyDOM template.
386 */
387 public Node getExpandedNode(Node node) {
388 return getExpandedNode(fDocument, node);
389 }
390
391 /**
392 * If an Element node is a LazyDOM template, expand it.
393 * This is a special case of <tt>getExpandedNode()</tt>.
394 *
395 * @param document The instance document object.
396 * @param element An element of the document or it's template.
397 * @return The expanded element, or the element unchanged
398 * if it is not a LazyDOM template.
399 */
400 public static Element getExpandedElement(Document document,
401 Element element) {
402 if ((element instanceof LazyElement) && ((LazyElement)element).isTemplateNode()) {
403 return (Element)((LazyDocument)document).getNodeById(((LazyElement)element).getNodeId());
404 } else {
405 return element;
406 }
407 }
408
409 /**
410 * If an Element node is a LazyDOM template, expand it
411 * This is a special case of <tt>getExpandedNode()</tt>.
412 *
413 * @param element An element of the document or template.
414 * @return The expanded element, or the element unchanged
415 * if it is not a LazyDOM template.
416 */
417 public Element getExpandedElement(Element element) {
418 return getExpandedElement(fDocument, element);
419 }
420
421 }