KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > xml > xhtml > dom > xerces > XHTMLDocumentBase


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999,2000 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57 package org.enhydra.xml.xhtml.dom.xerces;
58
59 /*
60  * Derived from Xerces HTMLDocument implementation.
61  * Author: Assaf Arkin <arkin@exoffice.com>
62  */

63 import java.io.StringWriter JavaDoc;
64 import java.lang.reflect.Constructor JavaDoc;
65 import java.util.HashMap JavaDoc;
66
67 import org.enhydra.apache.html.dom.HTMLAnchorElementImpl;
68 import org.enhydra.apache.xerces.dom.DocumentImpl;
69 import org.enhydra.apache.xerces.dom.NodeImpl;
70 import org.enhydra.xml.io.DocumentInfo;
71 import org.enhydra.xml.xmlc.XMLCError;
72 import org.enhydra.xml.xmlc.dom.HTMLDomFactoryMethods;
73 import org.w3c.dom.DOMException JavaDoc;
74 import org.w3c.dom.DOMImplementation JavaDoc;
75 import org.w3c.dom.DocumentType JavaDoc;
76 import org.w3c.dom.Element JavaDoc;
77 import org.w3c.dom.Node JavaDoc;
78 import org.w3c.dom.NodeList JavaDoc;
79 import org.w3c.dom.html.HTMLCollection;
80 import org.w3c.dom.html.HTMLDocument;
81 import org.w3c.dom.html.HTMLElement;
82 import org.w3c.dom.html.HTMLTitleElement;
83
84 /**
85  * Base class used to implements documents defined in terms of XHTML. This
86  * includes the full XHTML and XHTML modular documents. This defined all of
87  * the HTMLDocument methods plus a framework for creating elements, but no
88  * element definitions themselves.
89  *
90  * @see org.w3c.dom.html.HTMLDocument
91  */

92 public class XHTMLDocumentBase extends DocumentImpl implements HTMLDocument, DocumentInfo {
93     /**
94      * Holds {@link XHTMLCollectionImpl} object with live collection of all
95      * anchors in document. This reference is on demand only once.
96      */

97     private XHTMLCollectionImpl fAnchors;
98
99     /**
100      * Holds {@link XHTMLCollectionImpl} object with live collection of all
101      * forms in document. This reference is on demand only once.
102      */

103     private XHTMLCollectionImpl fForms;
104
105     /**
106      * Holds {@link XHTMLCollectionImpl} object with live collection of all
107      * images in document. This reference is on demand only once.
108      */

109     private XHTMLCollectionImpl fImages;
110
111     /**
112      * Holds {@link XHTMLCollectionImpl} object with live collection of all
113      * links in document. This reference is on demand only once.
114      */

115     private XHTMLCollectionImpl fLinks;
116
117
118     /**
119      * Holds {@link XHTMLCollectionImpl} object with live collection of all
120      * applets in document. This reference is on demand only once.
121      */

122     private XHTMLCollectionImpl fApplets;
123
124     /**
125      * Holds string writer used by direct manipulation operation ({@link #open}.
126      * {@link #write}, etc) to write new contents into the document and parse
127      * that text into a document tree.
128      */

129     private StringWriter JavaDoc fWriter;
130
131     /**
132      * Holds names and classes of HTML element types. When an element with a
133      * particular tag name is created, the matching {@link java.lang.Class}
134      * is used to create the element object. For example, &lt;A&gt; matches
135      * {@link HTMLAnchorElementImpl}. This static table is shared across all
136      * HTML documents.
137      *
138      * @see #createElement
139      */

140     private static HashMap JavaDoc fElementTypes;
141
142     /**
143      * Signature used to locate constructor of HTML element classes. This
144      * static array is shared across all HTML documents.
145      *
146      * @see #createElement
147      */

148     private static final Class JavaDoc[] fElemConstructorSig = new Class JavaDoc[] {
149     XHTMLDocumentBase.class, String JavaDoc.class, String JavaDoc.class
150     };
151
152     /**
153      * Constructor without document type.
154      *
155      * @param elementTypes Map of element names to element classes.
156      */

157     public XHTMLDocumentBase(HashMap JavaDoc elementTypes) {
158     super();
159         fElementTypes = elementTypes;
160     }
161
162     /**
163      * Constructor with document type.
164      */

165     public XHTMLDocumentBase(DocumentType JavaDoc doctype,
166                              HashMap JavaDoc elementTypes) {
167     super(doctype);
168         fElementTypes = elementTypes;
169     }
170
171     /**
172      * Find the direct child element of a node given its name.
173      */

174     private Node JavaDoc getDirectChildElement(String JavaDoc name, Node JavaDoc root) {
175     for (Node JavaDoc child = root.getFirstChild(); child != null;
176         child = child.getNextSibling()) {
177         if ((child instanceof Element JavaDoc)
178                 && child.getNodeName().equals(name)) {
179         return child;
180         }
181     }
182
183     return null;
184     }
185
186     /**
187      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getDocumentElement
188      */

189     public synchronized Element JavaDoc getDocumentElement() {
190     Element JavaDoc html = (Element JavaDoc)getDirectChildElement("html", this);
191     if (html == null) {
192             throw new DOMException JavaDoc(DOMException.HIERARCHY_REQUEST_ERR,
193                                    "<html> document element not found");
194     }
195
196     return html;
197     }
198
199     /**
200      * Obtains the &lt;HEAD&gt; element in the document, creating one if does
201      * not exist before. The &lt;HEAD&gt; element is the first element in the
202      * &lt;HTML&gt; in the document. The &lt;HTML&gt; element is obtained by
203      * calling {@link #getDocumentElement}. If the element does not exist, one
204      * is created.
205      *
206      * @return The &lt;HEAD&gt; element
207      */

208     public synchronized HTMLElement getHead() {
209
210     // Enhydra modified: Original Xerces code tried to reorder nodes to
211
// make things right, which moved around comments to weird locations.
212
// Throwing an error would be more appropriate, but we were afraid of
213
// breaking existing code, so just get the node.
214
// Search for HEAD under HTML element.
215
Element JavaDoc html = getDocumentElement();
216     HTMLElement head = (HTMLElement)getDirectChildElement("head", html);
217
218     if (head == null) {
219         // Head does not exist, create a new one.
220
head = new XHTMLHeadElementImpl(this, html.getNamespaceURI(),
221                                             "head");
222         html.insertBefore(head, html.getFirstChild());
223     }
224
225     return head;
226     }
227
228     /**
229      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getTitle
230      */

231     public synchronized String JavaDoc getTitle() {
232     // Enhydra modified: Original Xerces code is some what strange, it
233
// called getElementsByTagName() twice, but only used the second
234
// result. We assume it' a direct child of HEAD (although more
235
// error checking might be better).
236
HTMLTitleElement title =
237         (HTMLTitleElement)getDirectChildElement("title", getHead());
238
239     if (title == null) {
240         return ""; // No TITLE found, return an empty string.
241
} else {
242         return title.getText();
243     }
244     }
245
246     /**
247      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#setTitle
248      */

249     public synchronized void setTitle(String JavaDoc newTitle) {
250     // Enhydra modified: Original Xerces code used getElementsByTagName()
251
// to find the title. We assume it' a direct child of HEAD (although
252
// more error checking might be better).
253
HTMLElement head = getHead();
254     HTMLTitleElement title =
255         (HTMLTitleElement)getDirectChildElement("title", head);
256
257     if (title == null) {
258         title = new XHTMLTitleElementImpl(this, head.getNamespaceURI(),
259                                               "title");
260     }
261     title.setText(newTitle);
262     }
263
264     /**
265      * Find a BODY or FRAMESET element.
266      */

267     private HTMLElement findBody(Element JavaDoc html) {
268     HTMLElement body = (HTMLElement)getDirectChildElement("body", html);
269     if (body == null) {
270         body = (HTMLElement)getDirectChildElement("frameset", html);
271     }
272
273     return body;
274     }
275
276     /**
277      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getBody
278      */

279     public synchronized HTMLElement getBody() {
280     // Enhydra modified: Original Xerces code tried to reorder nodes to
281
// make things right, which moved around comments to weird locations.
282
// Throwing an error would be more appropriate, but we were afraid of
283
// breaking existing code, so just get the node.
284
// Find BODY or FRAMESET
285
Element JavaDoc html = getDocumentElement();
286     HTMLElement body = findBody(html);
287
288     if (body == null) {
289         // Create new body, and place it a the end of the HTML element.
290
body = new XHTMLBodyElementImpl(this, html.getNamespaceURI(),
291                                             "body");
292         html.appendChild(body);
293     }
294
295     return body;
296     }
297
298     /**
299      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#setBody
300      */

301     public synchronized void setBody(HTMLElement newBody) {
302     // Enhydra modified: Original Xerces code tried to reorder nodes to
303
// make things right, which moved around comments to weird locations.
304
// Throwing an error would be more appropriate, but we were afraid of
305
// breaking existing code, so just get the node.
306
// Find BODY or FRAMESET
307
Element JavaDoc html = getDocumentElement();
308     HTMLElement body = findBody(html);
309
310     if (body == null) {
311         html.appendChild(newBody);
312     } else {
313         html.replaceChild(newBody, body);
314     }
315     }
316
317     /**
318      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getElementById
319      */

320     public synchronized Element JavaDoc getElementById(String JavaDoc elementId) {
321     return getElementById(elementId, this);
322     }
323
324     /**
325      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getElementsByName
326      */

327     public NodeList JavaDoc getElementsByName(String JavaDoc elementName) {
328     return new NameNodeListImpl(this, elementName);
329     }
330
331     /**
332      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getElementsByTagName
333      */

334     public final NodeList JavaDoc getElementsByTagName(String JavaDoc tagName) {
335     return super.getElementsByTagName(tagName);
336     }
337
338     /**
339      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getElementsByTagNameNS
340      */

341     public final NodeList JavaDoc getElementsByTagNameNS(String JavaDoc namespaceURI,
342                                                  String JavaDoc localName) {
343     if (namespaceURI != null && namespaceURI.length() > 0) {
344         return super.getElementsByTagNameNS(namespaceURI,
345                         localName);
346     } else {
347         return super.getElementsByTagName(localName);
348     }
349     }
350
351     /**
352      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#createElementNS
353      */

354     public Element JavaDoc createElementNS(String JavaDoc namespaceURI,
355                    String JavaDoc qualifiedName) {
356         // FIXME: should be a common method for doing this
357
int index = qualifiedName.indexOf(':');
358         String JavaDoc tagName;
359         if (index < 0) {
360             tagName = qualifiedName;
361         } else {
362             tagName = qualifiedName.substring(index+1);
363         }
364         Class JavaDoc elemClass = (Class JavaDoc)fElementTypes.get(tagName);
365         if (elemClass != null) {
366             try {
367                 Constructor JavaDoc cnst = elemClass.getConstructor(fElemConstructorSig);
368                 return (Element JavaDoc)cnst.newInstance(new Object JavaDoc[] {this, namespaceURI, qualifiedName});
369             } catch (Exception JavaDoc except) {
370                 // Need more specific error..
371
throw new XMLCError("failed to construct element for \""
372                                     + qualifiedName + "\"", except);
373             }
374         } else {
375             return new XHTMLElementImpl(this, namespaceURI, qualifiedName);
376         }
377     }
378
379     /**
380      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#createElement
381      */

382     public Element JavaDoc createElement(String JavaDoc tagName) throws DOMException JavaDoc {
383         return createElementNS(null, tagName);
384     }
385
386     /**
387      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getReferrer
388      */

389     public String JavaDoc getReferrer() {
390     // Information not available on server side.
391
return null;
392     }
393
394     /**
395      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getDomain
396      */

397     public String JavaDoc getDomain() {
398     // Information not available on server side.
399
return null;
400     }
401
402     /**
403      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getURL
404      */

405     public String JavaDoc getURL() {
406     // Information not available on server side.
407
return null;
408     }
409
410     /**
411      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getCookie
412      */

413     public String JavaDoc getCookie() {
414     // Information not available on server side.
415
return null;
416     }
417
418     /**
419      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#setCookie
420      */

421     public void setCookie(String JavaDoc cookie) {
422     // Information not available on server side.
423
}
424
425     /**
426      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getImages
427      */

428     public HTMLCollection getImages() {
429     // For more information see HTMLCollection#collectionMatch
430
if (fImages == null) {
431         fImages = new XHTMLCollectionImpl(getBody(),
432                           XHTMLCollectionImpl.IMAGE);
433     }
434
435     return fImages;
436     }
437
438     /**
439      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getApplets
440      */

441     public HTMLCollection getApplets() {
442     // For more information see HTMLCollection#collectionMatch
443
if (fApplets == null) {
444         fApplets = new XHTMLCollectionImpl(getBody(),
445                            XHTMLCollectionImpl.APPLET);
446     }
447
448     return fApplets;
449     }
450
451     /**
452      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getLinks
453      */

454     public HTMLCollection getLinks() {
455     // For more information see HTMLCollection#collectionMatch
456
if (fLinks == null) {
457         fLinks = new XHTMLCollectionImpl(getBody(),
458                          XHTMLCollectionImpl.LINK);
459     }
460
461     return fLinks;
462     }
463
464     /**
465      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getForms
466      */

467     public HTMLCollection getForms() {
468     // For more information see HTMLCollection#collectionMatch
469
if (fForms == null) {
470         fForms = new XHTMLCollectionImpl(getBody(),
471                          XHTMLCollectionImpl.FORM);
472     }
473
474     return fForms;
475     }
476
477     /**
478      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#getAnchors
479      */

480     public HTMLCollection getAnchors() {
481     // For more information see HTMLCollection#collectionMatch
482
if (fAnchors == null) {
483         fAnchors = new XHTMLCollectionImpl(getBody(),
484                            XHTMLCollectionImpl.ANCHOR);
485     }
486
487     return fAnchors;
488     }
489
490     /**
491      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#optn
492      */

493     public void open() {
494     // When called an in-memory is prepared. The document tree is still
495
// accessible the old way, until this writer is closed.
496
if (fWriter == null) {
497         fWriter = new StringWriter JavaDoc();
498     }
499     }
500
501     /**
502      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#close
503      */

504     public void close() {
505     // ! NOT IMPLEMENTED, REQUIRES PARSER !
506
if (fWriter != null) {
507         fWriter = null;
508     }
509     }
510
511     /**
512      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#write
513      */

514     public void write(String JavaDoc text) {
515     // Write a string into the in-memory writer.
516
if (fWriter != null) {
517         fWriter.write(text);
518     }
519     }
520
521     /**
522      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#writeln
523      */

524     public void writeln(String JavaDoc text) {
525     // Write a line into the in-memory writer.
526
if (fWriter != null) {
527         fWriter.write(text + "\n");
528     }
529     }
530
531     /**
532      * @see org.enhydra.apache.html.dom.HTMLDocumentImpl#cloneNode
533      */

534     public Node JavaDoc cloneNode(boolean deep) {
535     XHTMLDocumentImpl clone;
536     NodeImpl node;
537
538     clone = new XHTMLDocumentImpl();
539     if (deep) {
540         node = (NodeImpl) getFirstChild();
541
542         while (node != null) {
543         clone.appendChild(clone.importNode(node, true));
544         node = (NodeImpl) node.getNextSibling();
545         }
546     }
547
548     return clone;
549     }
550
551     /**
552      * overload in order to return the correct dom implementation for XHTML
553      * @see org.enhydra.apache.xerces.dom.DocumentImpl#getImplementation
554      */

555     public DOMImplementation JavaDoc getImplementation() {
556         return XHTMLDOMImplementationImpl.getDOMImplementation();
557     }
558
559     /**
560      * Recursive method retreives an element by its <code>id</code> attribute.
561      * Called by {@link #getElementById(String)}.
562      *
563      * @param elementId The <code>id</code> value to look for
564      * @return The node in which to look for
565      */

566     private Element JavaDoc getElementById(String JavaDoc elementId, Node JavaDoc node) {
567     Node JavaDoc child;
568     Element JavaDoc result;
569
570     child = node.getFirstChild();
571
572     while (child != null) {
573         if (child instanceof Element JavaDoc) {
574         if (elementId.equals(((Element JavaDoc) child).getAttribute("id"))) {
575             return (Element JavaDoc) child;
576         }
577         result = getElementById(elementId, child);
578         if (result != null) {
579             return result;
580         }
581         }
582         child = child.getNextSibling();
583     }
584
585     return null;
586     }
587     public boolean isURLAttribute(Element JavaDoc element, String JavaDoc attrName)
588     {
589         return HTMLDomFactoryMethods.isURLAttribute(element, attrName);
590     }
591
592 }
593
Popular Tags