Source code: org/enhydra/xml/lazydom/LazyDocument.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$
22 */
23
24 package org.enhydra.xml.lazydom;
25
26 import org.w3c.dom.*;
27 import org.apache.xerces.dom.DocumentImpl;
28 import org.enhydra.xml.io.PreFormattedTextDocument;
29 import org.enhydra.xml.io.OutputOptions;
30
31 // FIXME: not sure the Lazy* constructors with TemplateNodes are actually
32 // needed, as we go thorugh the factory methods.
33 //FIXME: If no childred/attributes/etc exist, initialize expanded flag to true.
34 // FIXME: need serializable support.
35 //FIXME: Need clone support.
36 //FIXME: are createXXX(nodeId) really needed.
37
38 /**
39 * A DOM Document that supports lazy instantiation of a template DOM. Nodes
40 * in the instance DOM are created as accessed. This can be either by
41 * traversing the tree or by direct access to a node by id number.
42 * Instantiation of nodes in the middle of the virtual tree is support. Thus
43 * a node can exist without a parent being expanded. This is used by XMLC,
44 * were the dynamic nodes tend to be towards the leaves of the tree.
45 * <p>
46 * Instances contain a reference to a DOM that is a shared template for the
47 * document. Each node in the template is assigned an integer node id that be
48 * used to index tables to directly look up the template of a node created
49 * from the template.
50 * <p>
51 * This DOM also supports associating pre-formatted text with some nodes, which
52 * is used to avoid exprensive string scanning operations during the output
53 * of unmodified nodes.
54 * <p>
55 * When a child of a node is requested, all direct children are expanded.
56 * This eliminates a lot of difficult book keep. Attributes are treated
57 * as a separate set from children, only instantiated when an atttribute
58 * is accessed.
59 *
60 * Expansion of nodes accesed from an existing node works as follows:
61 * <ul>
62 * <li> Lazy nodes have internal flag to indicate if the particular type
63 * of expansion has occured (parent, child, or attribute).
64 * <li> When an access is made, check the flag to see if the expansion has
65 * occured.
66 * <li> If expansion has not occured, call the appropriate LazyDocument
67 * doExpand method, which is synchronized. This method again check
68 * the flag on the node and expands if necessary. Some expansion
69 * are only used by one node class and maybe implemented there,
70 * but still synchronize on the document.
71 * <li> To simplify the book keeping, all children of a node will be expanded
72 * when one is expanded.
73 * <li> When the parent of a node is requested, the parent and all of the other
74 * children will be expanded and linked.
75 * <li> Nodes created using create methods (without node ids), are always
76 * marked as expanded, as they always go through standard DOM methods to
77 * be inserted into the tree.
78 * </ul>
79 *
80 * This coarse-grained locking approach minimizes the number of locks * on the
81 * assumption that collisions do not occur frequently
82 * <p>
83 * To created an extended DOM, one must override both the factory methods that
84 * take strings and those that take node ids.
85 */
86 public class LazyDocument extends DocumentImpl
87 implements LazyParent, PreFormattedTextDocument {
88 /**
89 * Constructor.
90 * @param documentType Document type to associate with this document,
91 * or null if no doctype or should be obtained from template.
92 * @param templateDOM Template DOM, with each node cotaining a node id.
93 * Maybe null if no associated template.
94 */
95 public LazyDocument(DocumentType documentType,
96 TemplateDOM templateDOM) {
97 super(documentType);
98 if (templateDOM != null) {
99 fTemplateDOM = templateDOM;
100 fExpandedNodes = new LazyNode[fTemplateDOM.getMaxNodeId()+1];
101 fExpandedNodes[DOCUMENT_NODE_ID] = this;
102 fTemplateNode = (LazyDocument)fTemplateDOM.getNode(DOCUMENT_NODE_ID);
103 fNodeId = fTemplateNode.getNodeId();
104 } else {
105 // No template, mark as expanded.
106 fDocTypeExpanded = true;
107 fChildrenExpanded = true;
108 fIsTemplateNode = true; // No template, so this must be a template.
109 }
110 }
111
112 /**
113 * Constructor with no argument, for LazyHTMLDocument.
114 */
115 public LazyDocument() {
116 this(null, null);
117 }
118
119 /**
120 * @see Document#getDocumentElement
121 */
122 public Element getDocumentElement() {
123 if (!fChildrenExpanded) {
124 expandChildren();
125 }
126 return super.getDocumentElement();
127 }
128
129 /**
130 * @see Document#DOMImplementation
131 */
132 public DOMImplementation getImplementation() {
133 return LazyDOMImplementation.getDOMImplementation();
134 }
135
136 //-------------------------------------------------------------------------
137 // Document-wide expansion support (FIXME: move to a different class???)
138 //-------------------------------------------------------------------------
139
140 /**
141 * Template document DOM. This is shared by all instances and must not be
142 * modified.
143 */
144 private TemplateDOM fTemplateDOM;
145
146 /**
147 * Table of LazyNodes that have already been expanded, indexed
148 * by nodeId. Entry is null if the node has not been expanded.
149 */
150 private LazyNode[] fExpandedNodes;
151
152 /**
153 * Detection of recursive calls of one of the expansion routines.
154 */
155 private boolean fExpanding = false;
156
157 /**
158 * Flag that an expansion is in progress, which is used to detect
159 * recursion. MUST be synchronized on document.
160 */
161 protected final void enterExpansion() {
162 if (fExpanding) {
163 throw new LazyDOMError("recursive call doing lazy DOM expansion");
164 }
165 fExpanding = true;
166 }
167
168 /**
169 * Flag that an expansion is complete.
170 * MUST be synchronized on document.
171 */
172 protected final void leaveExpansion() {
173 fExpanding = false;
174 }
175
176 /**
177 * Create a new node from a template, placing it in the expanded table.
178 * Uses factory methods so that derived document can override node type.
179 * MUST be synchronized on document.
180 */
181 private LazyNode createLazyNode(int nodeId) {
182 LazyNode template = fTemplateDOM.getNode(nodeId);
183 switch (template.getNodeType()) {
184 case ELEMENT_NODE:
185 return createElement(nodeId);
186 case ATTRIBUTE_NODE:
187 return createAttribute(nodeId);
188 case TEXT_NODE:
189 return createTextNode(nodeId);
190 case CDATA_SECTION_NODE:
191 return createCDATASection(nodeId);
192 case ENTITY_REFERENCE_NODE:
193 return createEntityReference(nodeId);
194 case ENTITY_NODE:
195 return createEntity(nodeId);
196 case PROCESSING_INSTRUCTION_NODE:
197 return createProcessingInstruction(nodeId);
198 case COMMENT_NODE:
199 return createComment(nodeId);
200 case NOTATION_NODE:
201 return createNotation(nodeId);
202 case DOCUMENT_TYPE_NODE:
203 return createDocumentType(nodeId);
204 case DOCUMENT_NODE:
205 case DOCUMENT_FRAGMENT_NODE:
206 throw new LazyDOMError(nodeId, "Can't create node from template of type "
207 + template.getNodeType());
208 default:
209 throw new LazyDOMError(nodeId, "Invalid node type "
210 + template.getNodeType());
211 }
212 }
213
214 /**
215 * Get or create a lazy node, given its id. Expanding if it doesn't
216 * exist. All node creation must go through here so that a derived
217 * document create factory is used.
218 */
219 public final LazyNode getNodeById(int nodeId) {
220 if (fExpandedNodes[nodeId] == null) {
221 synchronized(this) {
222 if (fExpandedNodes[nodeId] == null) {
223 fExpandedNodes[nodeId] = createLazyNode(nodeId);
224 }
225 }
226 }
227 return fExpandedNodes[nodeId];
228 }
229
230 /**
231 * Get or create a node given, the template node.
232 * @see getNodeById
233 */
234 public final LazyNode getNodeFromTemplate(LazyNode template) {
235 return getNodeById(template.getNodeId());
236 }
237
238 /**
239 * Method to expand children of a node once synchronized and fExpanding is
240 * set.
241 * MUST be synchronized on document.
242 */
243 private void expandNodeChildren(LazyParent node) {
244 if (!node.areChildrenExpanded()) {
245 LazyNode template = node.getTemplateNode();
246 for (LazyNode templateChild = (LazyNode)template.getFirstChild();
247 templateChild != null;
248 templateChild = (LazyNode)templateChild.getNextSibling()) {
249 // Ignore doctype if its a child
250 if (!(templateChild instanceof DocumentType)) {
251 LazyNode child = getNodeFromTemplate(templateChild);
252 node.appendChildWhileExpanding(child);
253 if (child instanceof LazyParent) {
254 // Tell child parent is expanded
255 ((LazyParent)child).setParentExpanded();
256 }
257 }
258 }
259 node.setChildrenExpanded();
260 }
261 }
262
263 /**
264 * Do work of expanding the parent of a node, if it is not already
265 * expanded. This also expands the children, as this keeps the expansion
266 * bookkeeping simple and getting a parent not a common operation except to
267 * access a sibling or add a new sibling
268 * Only used internally to this package.
269 */
270 protected synchronized void doExpandParent(LazyParent node) {
271 // Check again for it being expanded now that we are synchronized
272 // getParent used during insertion of new node, so allow for recursion
273 // without actually expanding.
274 if (!node.isParentExpanded() && !fExpanding) {
275 enterExpansion();
276 try {
277 LazyParent parentTemplate = (LazyParent)node.getTemplateNode().getParentNode();
278 if (parentTemplate != null) {
279 expandNodeChildren((LazyParent)getNodeFromTemplate(parentTemplate));
280 }
281 node.setParentExpanded();
282 } finally {
283 leaveExpansion();
284 }
285 }
286 }
287
288 /**
289 * Do work of expanding the children of a node, if they are not already
290 * expanded. Only lazy parent's have a flag for siblings, as data nodes
291 * can never be accessed without going through the parent and expanding
292 * the children.
293 * Only used internally to this package.
294 */
295 protected synchronized void doExpandChildren(LazyParent node) {
296 enterExpansion();
297 try {
298 expandNodeChildren(node);
299 } finally {
300 leaveExpansion();
301 }
302 }
303
304 /**
305 * Get a pointer to a node if its been expanded, otherwise
306 * return null.
307 */
308 public final LazyNode getExpandedNode(int nodeId) {
309 return fExpandedNodes[nodeId];
310 }
311
312 /**
313 * Get a template node, given a node id.
314 */
315 public final LazyNode getTemplateNode(int nodeId) {
316 return fTemplateDOM.getNode(nodeId);
317 }
318
319 //-------------------------------------------------------------------------
320 // LazyDocument specific
321 //-------------------------------------------------------------------------
322
323 /**
324 * Has the DocumentType been expanded?
325 */
326 private boolean fDocTypeExpanded = false;
327
328 /**
329 * Detection of recursive calls of doctype expansion. A seperate
330 * flag, since doctype maybe expanded while expanding attributes.
331 */
332 private boolean fExpandingDocType = false;
333
334 /**
335 * Template for this Document.
336 */
337 private LazyDocument fTemplateNode = null;
338
339 /**
340 * Has the DocumentType been expanded?
341 */
342 public boolean isDocTypeExpanded() {
343 return fDocTypeExpanded;
344 }
345
346 /**
347 * Get the template for this node.
348 * @see LazyNode#getTemplateNode
349 */
350 public LazyDocument getTemplateDocument() {
351 return fTemplateNode;
352 }
353
354 /**
355 * @see Node#cloneNode
356 */
357 public Node cloneNode(boolean deep) {
358 if (deep) {
359 // If children are copied, we must expand now.
360 if (!fDocTypeExpanded) {
361 doExpandDocType();
362 }
363 if (!fChildrenExpanded) {
364 expandChildren();
365 }
366 }
367
368 /**
369 * This does a clone(), must clean up all fields and make
370 * fully expanded.
371 * FIXME: Should support cloning in unexpanded state.
372 */
373 LazyDocument newDocument = (LazyDocument)super.cloneNode(deep);
374 newDocument.fTemplateDOM = null;
375 newDocument.fExpandedNodes = null;
376 newDocument.fDocTypeExpanded = true;
377 newDocument.fChildrenExpanded = true;
378 return newDocument;
379 }
380
381 //-------------------------------------------------------------------------
382 // LazyNode support
383 //-------------------------------------------------------------------------
384
385 /*
386 * Node id for this element.
387 */
388 private int fNodeId = NULL_NODE_ID;
389
390 /**
391 * Is this a template node?
392 */
393 private boolean fIsTemplateNode;
394
395 /*
396 * @see LazyNode#makeTemplateNode
397 */
398 public void makeTemplateNode(int nodeId) {
399 fNodeId = nodeId;
400 fIsTemplateNode = true;
401 }
402
403 /**
404 * @see LazyNode#getNodeId
405 */
406 public int getNodeId() {
407 return fNodeId;
408 }
409
410 /**
411 * @see LazyNode#isTemplateNode
412 */
413 public boolean isTemplateNode() {
414 return fIsTemplateNode;
415 }
416
417 /**
418 * @see LazyNode#getTemplateNode
419 */
420 public LazyNode getTemplateNode() {
421 return fTemplateNode;
422 }
423
424 /**
425 * @see LazyNode#templateClone
426 */
427 public LazyNode templateClone(Document ownerDocument) {
428 throw new LazyDOMError("templateClone not support on LazyDocument node");
429 }
430
431 /**
432 * Set the node value, invalidating the id. All node data is modified
433 * by this routine.
434 * @see org.w3c.dom.Node.setNodeValue
435 */
436 public void setNodeValue(String value) {
437 fNodeId = NULL_NODE_ID;
438 super.setNodeValue(value);
439 }
440
441 //-------------------------------------------------------------------------
442 // LazyParent support
443 //-------------------------------------------------------------------------
444
445 /**
446 * Children expanded flag.
447 * NB: code is special, since there is node parent.
448 */
449 private boolean fChildrenExpanded = false;
450
451 /**
452 * @see LazyParent#isParentExpanded()
453 */
454 public boolean isParentExpanded() {
455 return true;
456 }
457
458 /**
459 * @see LazyParent#setParentExpanded
460 */
461 public void setParentExpanded() {
462 throw new LazyDOMError("setParentExpanded invalid on document");
463 }
464
465 /**
466 * @see LazyParent#setParentWhileExpanding
467 */
468 public void setParentWhileExpanding(Node parent) {
469 throw new LazyDOMError("setParentWhileExpanding invalid on document");
470 }
471
472 /**
473 * @see LazyParent#areChildrenExpanded()
474 */
475 public boolean areChildrenExpanded() {
476 return fChildrenExpanded;
477 }
478
479 /**
480 * @see LazyParent#setChildrenExpanded
481 */
482 public void setChildrenExpanded() {
483 fChildrenExpanded = true;
484 }
485
486 /**
487 * @see LazyParent#appendChildWhileExpanding
488 */
489 public void appendChildWhileExpanding(Node child) {
490 super.insertBefore(child, null);
491 }
492
493 /**
494 * Expand the parent of this element, if it is not already expanded.
495 */
496 private void expandParent() {
497 doExpandParent(this);
498 }
499
500 /**
501 * Expand the children of this element, if they are not already expanded.
502 */
503 private void expandChildren() {
504 doExpandChildren(this);
505 }
506
507 /**
508 * @see org.w3c.dom.Node#getChildNodes
509 */
510 public NodeList getChildNodes() {
511 if (!fChildrenExpanded) {
512 expandChildren();
513 }
514 return super.getChildNodes();
515 }
516
517 /**
518 * @see org.w3c.dom.Node#getFirstChild
519 */
520 public Node getFirstChild() {
521 if (!fChildrenExpanded) {
522 expandChildren();
523 }
524 return super.getFirstChild();
525 }
526
527 /**
528 * @see org.w3c.dom.Node#getLastChild
529 */
530 public Node getLastChild() {
531 if (!fChildrenExpanded) {
532 expandChildren();
533 }
534 return super.getLastChild();
535 }
536
537 /**
538 * @see org.w3c.dom.Node#insertBefore
539 */
540 public Node insertBefore(Node newChild,
541 Node refChild)
542 throws DOMException {
543 if (!fChildrenExpanded) {
544 expandChildren();
545 }
546 return super.insertBefore(newChild, refChild);
547 }
548
549 /**
550 * @see org.w3c.dom.Node#replaceChild
551 */
552 public Node replaceChild(Node newChild,
553 Node oldChild)
554 throws DOMException {
555 if (!fChildrenExpanded) {
556 expandChildren();
557 }
558 return super.replaceChild(newChild, oldChild);
559 }
560
561 /**
562 * @see org.w3c.dom.Node#removeChild
563 */
564 public Node removeChild(Node oldChild)
565 throws DOMException {
566 if (!fChildrenExpanded) {
567 expandChildren();
568 }
569 return super.removeChild(oldChild);
570 }
571
572 /**
573 * @see org.w3c.dom.Node#appendChild
574 */
575 public Node appendChild(Node newChild)
576 throws DOMException {
577 if (!fChildrenExpanded) {
578 expandChildren();
579 }
580 return super.appendChild(newChild);
581 }
582
583 /**
584 * @see org.w3c.dom.Node#hasChildNodes
585 */
586 public boolean hasChildNodes() {
587 if (!fChildrenExpanded) {
588 return fTemplateNode.hasChildNodes();
589 } else {
590 return super.hasChildNodes();
591 }
592 }
593
594 /**
595 * @see org.w3c.dom.Node#normalize
596 */
597 public void normalize() {
598 if (!fChildrenExpanded) {
599 expandChildren();
600 }
601 super.normalize();
602 }
603
604 //-------------------------------------------------------------------------
605 // DocumentType support
606 //-------------------------------------------------------------------------
607
608 /**
609 * Expand the document type if needed.
610 */
611 private synchronized void doExpandDocType() {
612 if (!fDocTypeExpanded) {
613 if (fExpandingDocType) {
614 throw new LazyDOMError("recursive call expanding Lazy DOM DocumentType");
615 }
616 fExpandingDocType = true;
617 try {
618 LazyDocumentType template = (LazyDocumentType)fTemplateNode.getDoctype();
619 if (template != null) {
620 docType = (LazyDocumentType)getNodeFromTemplate(template);
621 }
622 fDocTypeExpanded = true;
623 } finally {
624 fExpandingDocType = false;
625 }
626 }
627 }
628
629 /**
630 * @see Document#getDoctype
631 */
632 public DocumentType getDoctype() {
633 if (!fDocTypeExpanded) {
634 doExpandDocType();
635 }
636 return super.getDoctype();
637 }
638
639 //-------------------------------------------------------------------------
640 // Implemention of node org.w3c.dom.Document factories
641 //-------------------------------------------------------------------------
642
643 /**
644 * @see org.w3c.dom.Document#createElement
645 */
646 public Element createElement(String tagName) throws DOMException {
647 return new LazyElementNoNS(this, null, tagName);
648 }
649
650 /**
651 * @see org.w3c.dom.Document#createTextNode
652 */
653 public Text createTextNode(String data) {
654 return new LazyText(this, null, data);
655 }
656
657 /**
658 * @see org.w3c.dom.Document#createComment
659 */
660 public Comment createComment(String data) {
661 return new LazyComment(this, null, data);
662 }
663
664 /**
665 * @see org.w3c.dom.Document#createCDATASection
666 */
667 public CDATASection createCDATASection(String data) throws DOMException {
668 return new LazyCDATASection(this, null, data);
669 }
670
671 /**
672 * @see org.w3c.dom.Document#createProcessingInstruction
673 */
674 public ProcessingInstruction createProcessingInstruction(String target,
675 String data) {
676 return new LazyProcessingInstruction(this, null, target, data);
677 }
678
679 /**
680 * @see org.w3c.dom.Document#createAttribute
681 */
682 public Attr createAttribute(String name) throws DOMException {
683 return new LazyAttrNoNS(this, null, name);
684 }
685
686 /**
687 * @see org.w3c.dom.Document#createNotation
688 */
689 public Notation createNotation(String name) throws DOMException {
690 return new LazyNotation(this, null, name, null, null);
691 }
692
693 /**
694 * @see org.w3c.dom.Document#createEntityReference
695 */
696 public EntityReference createEntityReference(String name) throws DOMException {
697 return new LazyEntityReference(this, null, name);
698 }
699
700 /**
701 * @see org.w3c.dom.Document#createElementNS
702 */
703 public Element createElementNS(String namespaceURI,
704 String qualifiedName) throws DOMException {
705 return new LazyElementNS(this, null, namespaceURI, qualifiedName);
706 }
707
708 /**
709 * @see org.w3c.dom.Document#createAttributeNS
710 */
711 public Attr createAttributeNS(String namespaceURI,
712 String qualifiedName) throws DOMException {
713 return new LazyAttrNS(this, null, namespaceURI, qualifiedName);
714 }
715
716 /**
717 * Create a new DocumentType object (Non-DOM).
718 * @see DocumentImpl#createDocumentType
719 */
720 public DocumentType createDocumentType(String qualifiedName,
721 String publicID,
722 String systemID,
723 String internalSubset) throws DOMException {
724 return new LazyDocumentType(this, null, qualifiedName, publicID, systemID, internalSubset);
725 }
726
727 /**
728 * Create a new DocumentType object (Non-DOM). This overrides the method
729 * in the Xerces DOM used by importNode().
730 * @see DocumentImpl#createDocumentType
731 */
732 public DocumentType createDocumentType(String qualifiedName,
733 String publicID,
734 String systemID) throws DOMException {
735
736 return new LazyDocumentType(this, null, qualifiedName, publicID, systemID, null);
737
738 }
739 /**
740 * Create a new Entity object (Non-DOM).
741 * @see DocumentImpl#createEntity
742 */
743 public Entity createEntity(String name) throws DOMException {
744 return new LazyEntity(this, null, name, null, null, null);
745 }
746
747 //-------------------------------------------------------------------------
748 // Node id-based node creation methods.
749 //-------------------------------------------------------------------------
750
751 /**
752 * Create a element from a template given its id.
753 * @see org.w3c.dom.Document#createElement
754 */
755 public LazyElement createElement(int nodeId) throws DOMException {
756 Node template = (LazyElement)fTemplateDOM.getNode(nodeId);
757 if (template instanceof LazyElementNS) {
758 return new LazyElementNS(this, (LazyElementNS)template, null, null);
759 } else {
760 return new LazyElementNoNS(this, (LazyElementNoNS)template, null);
761 }
762 }
763
764 /**
765 * Create a text node from a template given its id.
766 * @see org.w3c.dom.Document#createTextNode
767 */
768 public LazyText createTextNode(int nodeId) {
769 return new LazyText(this, (LazyText)fTemplateDOM.getNode(nodeId), null);
770 }
771
772 /**
773 * Create a comment from a template given its id.
774 * @see org.w3c.dom.Document#createComment
775 */
776 public LazyComment createComment(int nodeId) {
777 return new LazyComment(this, (LazyComment)fTemplateDOM.getNode(nodeId), null);
778 }
779
780 /**
781 * Create a CDATASection from a template given its id.
782 * @see org.w3c.dom.Document#createCDATASection
783 */
784 public LazyCDATASection createCDATASection(int nodeId) throws DOMException {
785 return new LazyCDATASection(this, (LazyCDATASection)fTemplateDOM.getNode(nodeId), null);
786 }
787
788 /**
789 * Create a process instruction node from a template given its id.
790 * @see org.w3c.dom.Document#createProcessingInstruction
791 */
792 public LazyProcessingInstruction createProcessingInstruction(int nodeId) {
793 return new LazyProcessingInstruction(this, (LazyProcessingInstruction)fTemplateDOM.getNode(nodeId), null, null);
794 }
795
796 /**
797 * Create an attribute from a template given its id.
798 * @see org.w3c.dom.Document#createAttribute
799 */
800 public LazyAttr createAttribute(int nodeId) throws DOMException {
801 Node template = fTemplateDOM.getNode(nodeId);
802 if (template instanceof LazyAttrNS) {
803 return new LazyAttrNS(this, (LazyAttrNS)template, null, null);
804 } else {
805 return new LazyAttrNoNS(this, (LazyAttrNoNS)fTemplateDOM.getNode(nodeId), null);
806 }
807 }
808
809 /**
810 * Create a notation node from a template given its id.
811 * @see org.w3c.dom.Document#createNotation
812 */
813 public LazyNotation createNotation(int nodeId) throws DOMException {
814 return new LazyNotation(this, (LazyNotation)fTemplateDOM.getNode(nodeId),
815 null, null, null);
816 }
817
818 /**
819 * Create a entity reference from a template given its id.
820 * @see org.w3c.dom.Document#createEntityReference
821 */
822 public LazyEntityReference createEntityReference(int nodeId) throws DOMException {
823 return new LazyEntityReference(this, (LazyEntityReference)fTemplateDOM.getNode(nodeId), null);
824 }
825
826 /**
827 * Create a new DocumentType object (Non-DOM).
828 * @see DocumentImpl#createDocumentType
829 */
830 public LazyDocumentType createDocumentType(int nodeId) throws DOMException {
831 // FIXME: This isn't all that useful, as one can't set doctype after creating
832 // the document.
833 return new LazyDocumentType(this, (LazyDocumentType)fTemplateDOM.getNode(nodeId),
834 null, null, null, null);
835 }
836
837 /**
838 * Create a new Entity object (Non-DOM).
839 * @see DocumentImpl#createEntity
840 */
841 public LazyEntity createEntity(int nodeId) throws DOMException {
842 return new LazyEntity(this, (LazyEntity)fTemplateDOM.getNode(nodeId),
843 null, null, null, null);
844 }
845
846 //-------------------------------------------------------------------------
847 // Template node creation methods.
848 //-------------------------------------------------------------------------
849
850 /**
851 * Create a template element. This will call the derived document create
852 * method.
853 *
854 * @see #createElement(String)
855 * @see org.w3c.dom.Document#createElement
856 */
857 public LazyElement createTemplateElement(String tagName,
858 int nodeId,
859 String preFormattedText) throws DOMException {
860 LazyElement element = (LazyElement)createElement(tagName);
861 element.makeTemplateNode(nodeId, preFormattedText);
862 return element;
863 }
864
865 /**
866 * Create a template text node. This will call the derived document
867 * create method.
868 *
869 * @see #createText(String)
870 * @see org.w3c.dom.Document#createTextNode
871 */
872 public LazyText createTemplateTextNode(String data,
873 int nodeId,
874 String preFormattedText) {
875 LazyText text = (LazyText)createTextNode(data);
876 text.makeTemplateNode(nodeId, preFormattedText);
877 return text;
878 }
879
880 /**
881 * Create a template comment. This will call the derived document create
882 * method.
883 *
884 * @see #createComment(String)
885 * @see org.w3c.dom.Document#createComment
886 */
887 public LazyComment createTemplateComment(String data,
888 int nodeId) {
889 LazyComment comment = (LazyComment)createComment(data);
890 comment.makeTemplateNode(nodeId);
891 return comment;
892 }
893
894 /**
895 * Create a template CDATASection. This will call the derived document
896 * create method.
897 *
898 * @see #createCDataSection(String)
899 * @see org.w3c.dom.Document#createCDATASection
900 */
901 public LazyCDATASection createTemplateCDATASection(String data,
902 int nodeId) throws DOMException {
903 LazyCDATASection cdataSection = (LazyCDATASection)createCDATASection(data);
904 cdataSection.makeTemplateNode(nodeId);
905 return cdataSection;
906 }
907
908 /**
909 * Create a template ProcessingInstruction. This will call the derived
910 * document create method.
911 *
912 * @see #createProcessingInstruction(String,String)
913 * @see org.w3c.dom.Document#createProcessingInstruction
914 */
915 public LazyProcessingInstruction createTemplateProcessingInstruction(String target,
916 String data,
917 int nodeId) {
918 LazyProcessingInstruction pi = (LazyProcessingInstruction)createProcessingInstruction(target, data);
919 pi.makeTemplateNode(nodeId);
920 return pi;
921 }
922
923 /**
924 * Create a template Attr. This will call the derived document create
925 * method.
926 *
927 * @see createAttribute(String)
928 * @see org.w3c.dom.Document#createAttribute
929 */
930 public LazyAttr createTemplateAttribute(String name,
931 int nodeId) throws DOMException {
932 LazyAttr attr = (LazyAttr)createAttribute(name);
933 attr.makeTemplateNode(nodeId);
934 return attr;
935 }
936
937 /**
938 * Create a template Attr. This will call the derived document create
939 * method.
940 *
941 * @see createAttributeNS(String,String)
942 * @see org.w3c.dom.Document#createAttributeNS
943 */
944 public LazyAttr createTemplateAttributeNS(String namespaceURI,
945 String qualifiedName,
946 int nodeId) throws DOMException {
947 LazyAttr attr = (LazyAttr)createAttributeNS(namespaceURI, qualifiedName);
948 attr.makeTemplateNode(nodeId);
949 return attr;
950 }
951
952 /**
953 * Create a template Notation. This will call the derived document create
954 * method.
955 *
956 * @see #createNotation(String)
957 * @see org.w3c.dom.Document#createNotation
958 */
959 public LazyNotation createTemplateNotation(String name,
960 int nodeId) throws DOMException {
961 LazyNotation notation = (LazyNotation) createNotation(name);
962 notation.makeTemplateNode(nodeId);
963 return notation;
964 }
965
966 /**
967 * Create a template EntityReference. This will call the derived document
968 * create method.
969 *
970 * @see #createEntityReference(String)
971 * @see org.w3c.dom.Document#createEntityReference
972 */
973 public LazyEntityReference createTemplateEntityReference(String name,
974 int nodeId) throws DOMException {
975 LazyEntityReference entityRef = (LazyEntityReference)createEntityReference(name);
976 entityRef.makeTemplateNode(nodeId);
977 return entityRef;
978 }
979
980 /**
981 * Create a template Element with namespace. This will call the derived
982 * document create method.
983 *
984 * @see #createElementNS(String,String)
985 * @see org.w3c.dom.Document#createElementNS
986 */
987 public LazyElement createTemplateElementNS(String namespaceURI,
988 String qualifiedName,
989 int nodeId,
990 String preFormattedText) throws DOMException {
991 LazyElement element = (LazyElement)createElementNS(namespaceURI,
992 qualifiedName);
993 element.makeTemplateNode(nodeId, preFormattedText);
994 return element;
995 }
996
997 /**
998 * Create a template Attr with namespace. This will call the derived
999 * document create method.
1000 *
1001 * @see #createAttributeNS(String,String)
1002 * @see org.w3c.dom.Document#createAttributeNS
1003 */
1004 public LazyAttr createAttributeNS(String namespaceURI,
1005 String qualifiedName,
1006 int nodeId) throws DOMException {
1007 LazyAttr attr = (LazyAttr)createAttributeNS(namespaceURI, qualifiedName);
1008 attr.makeTemplateNode(nodeId);
1009 return attr;
1010 }
1011
1012 /**
1013 * Create a template DocumentType.
1014 *
1015 * @see #createDocumentType(String,String,String,String)
1016 * @see DocumentImpl#createDocumentType
1017 */
1018 public LazyDocumentType createTemplateDocumentType(String qualifiedName,
1019 String publicID,
1020 String systemID,
1021 String internalSubset,
1022 int nodeId) throws DOMException {
1023 LazyDocumentType docType = new LazyDocumentType(this, null, qualifiedName, publicID,
1024 systemID, internalSubset);
1025 docType.makeTemplateNode(nodeId);
1026 return docType;
1027 }
1028
1029 /**
1030 * Create a template Entity.
1031 *
1032 * @see #createEntity(String)
1033 * @see DocumentImpl#createEntity
1034 */
1035 public LazyEntity createTemplateEntity(String name,
1036 String publicId,
1037 String systemId,
1038 String notationName,
1039 int nodeId) throws DOMException {
1040 LazyEntity entity = new LazyEntity(this, null, name, publicId,
1041 systemId, notationName);
1042 entity.makeTemplateNode(nodeId);
1043 return entity;
1044 }
1045
1046 //-------------------------------------------------------------------------
1047 // PreFormattedTextDocument specific
1048 //-------------------------------------------------------------------------
1049
1050 /**
1051 * OutputOptions used for creating the preformatted text.
1052 */
1053 private OutputOptions fPreFormatOutputOptions;
1054
1055 /**
1056 * Set the output options that were used to preformat this document.
1057 * @param outputOptions The output options; should be read-only.
1058 */
1059 public void setPreFormatOutputOptions(OutputOptions outputOptions) {
1060 fPreFormatOutputOptions = outputOptions;
1061 }
1062
1063 /**
1064 * @see PreFormattedTextDocument#getPreFormatOutputOptions
1065 */
1066 public OutputOptions getPreFormatOutputOptions() {
1067 return fPreFormatOutputOptions;
1068 }
1069}