001: /*
002: ItsNat Java Web Application Framework
003: Copyright (C) 2007 Innowhere Software Services S.L., Spanish Company
004: Author: Jose Maria Arranz Santamaria
005:
006: This program is free software: you can redistribute it and/or modify
007: it under the terms of the GNU Affero General Public License as published by
008: the Free Software Foundation, either version 3 of the License, or
009: (at your option) any later version. See the GNU Affero General Public
010: License for more details. See the copy of the GNU Affero General Public License
011: included in this program. If not, see <http://www.gnu.org/licenses/>.
012: */
013:
014: package org.itsnat.impl.core.html;
015:
016: import java.io.StringReader;
017: import org.itsnat.impl.core.MarkupTemplateVersionDelegateImpl;
018: import org.itsnat.impl.core.DocFragmentTemplateVersionImpl;
019: import org.itsnat.impl.core.MarkupContainerImpl;
020: import org.itsnat.impl.core.dom.parse.HTMLParserUtil;
021: import org.itsnat.impl.core.domutil.ItsNatDOMUtilInternal;
022: import org.w3c.dom.Document;
023: import org.w3c.dom.DocumentFragment;
024: import org.w3c.dom.Node;
025: import org.w3c.dom.html.HTMLBodyElement;
026: import org.w3c.dom.html.HTMLDocument;
027: import org.w3c.dom.html.HTMLElement;
028: import org.w3c.dom.html.HTMLHeadElement;
029: import org.xml.sax.InputSource;
030:
031: /**
032: *
033: * @author jmarranz
034: */
035: public class HTMLDocFragmentTemplateVersionImpl extends
036: DocFragmentTemplateVersionImpl {
037: protected DocumentFragment templateDocFragmentHead;
038: protected DocumentFragment templateDocFragmentBody;
039:
040: /**
041: * Creates a new instance of HTMLDocFragmentTemplateVersionImpl
042: */
043: public HTMLDocFragmentTemplateVersionImpl(
044: HTMLDocFragmentTemplateImpl docTemplate, long timeStamp) {
045: super (docTemplate, timeStamp);
046:
047: HTMLDocument templateHtmlDoc = (HTMLDocument) templateDoc;
048:
049: HTMLTemplateVersionDelegateImpl
050: .normalizeContent(templateHtmlDoc); // Normalizamos después del cacheado pues sólo nos interesa normalizar aquello que es dinámico y por tanto debe coincidir exactamente el DOM cliente y servidor, además es más rápido pues las partes cacheadas son nodos de texto
051:
052: HTMLHeadElement head = ItsNatDOMUtilInternal
053: .getHead(templateHtmlDoc);
054: HTMLBodyElement body = (HTMLBodyElement) templateHtmlDoc
055: .getBody();
056:
057: // Tenemos la seguridad de que hay <head> y <body> pues el parser normaliza siempre el HTML incluyéndolos
058: // Hay que recordar que tras el crear el DocumentFragment el <head> y el <body> quedan vacíos.
059: this .templateDocFragmentHead = extractChildrenToDocFragment(head);
060: this .templateDocFragmentBody = extractChildrenToDocFragment(body);
061:
062: this .templateDoc = null; // Para evitar que se use
063: }
064:
065: protected void doCacheDocument() {
066: HTMLDocument templateHtmlDoc = (HTMLDocument) templateDoc;
067:
068: HTMLHeadElement head = ItsNatDOMUtilInternal
069: .getHead(templateHtmlDoc);
070: HTMLBodyElement body = (HTMLBodyElement) templateHtmlDoc
071: .getBody();
072:
073: // Cacheamos los elementos hijos del <head> y el <body> para evitar
074: // que en el caso de ser cacheados ellos mismos queden con único nodo
075: // de text. El problema es que al que al obtener los DocumentFragment template
076: // estos quedarían como un simple nodo de texto en donde el padre (el <head>
077: // o el <body>) se han perdido, y en el cacheado es importante que el
078: // elemento contenedor verdadero sea el padre el contenido cacheado.
079:
080: inspectChildNodesToCache(head);
081: inspectChildNodesToCache(body);
082: }
083:
084: public static DocumentFragment convertHTMLFragment(String source,
085: Document docTarget, String encoding) {
086: // No merece la pena cachear ni similares pues es llamado únicamente
087: // para soportar los mutations events en el cliente (y sincronizar en el servidor)
088: // que sólo funcionan en FireFox vamos que su uso en el mundo real será una rareza.
089: // Se puede usar también el método parser(InputSource,DocumentFragment)
090: // del parser de cyberneko que será más ligero pues no crea un Document
091: // pero no vale la pena por lo anterior.
092:
093: StringBuffer htmlCode = new StringBuffer();
094: htmlCode.append("<html><head>");
095: htmlCode.append("<meta content=\"text/html; charset="
096: + encoding + "\" http-equiv=\"Content-Type\" />");
097: htmlCode.append("</head><body>");
098: htmlCode.append(source);
099: htmlCode.append("</body></html>");
100: StringReader reader = new StringReader(htmlCode.toString());
101: HTMLDocument doc = (HTMLDocument) HTMLParserUtil.parse(
102: new InputSource(reader), encoding);
103: HTMLTemplateVersionDelegateImpl.normalizeContent(doc);
104: DocumentFragment fragment = doc.createDocumentFragment();
105: HTMLElement body = doc.getBody();
106: Node child = body.getFirstChild();
107: while (child != null) {
108: fragment.appendChild(child); // Al insertar se quita del documento
109: child = body.getFirstChild();
110: }
111: fragment = (DocumentFragment) docTarget.importNode(fragment,
112: true);
113: return fragment;
114: }
115:
116: public DocumentFragment loadDocumentFragmentHead(
117: MarkupContainerImpl target) {
118: return loadDocumentFragment(templateDocFragmentHead, target);
119: }
120:
121: public DocumentFragment loadDocumentFragmentBody(
122: MarkupContainerImpl target) {
123: return loadDocumentFragment(templateDocFragmentBody, target);
124: }
125:
126: public DocumentFragment loadDocumentFragment(
127: MarkupContainerImpl target) {
128: return loadDocumentFragmentBody(target);
129: }
130:
131: protected MarkupTemplateVersionDelegateImpl createMarkupTemplateVersionDelegate() {
132: return new HTMLTemplateVersionDelegateImpl(this);
133: }
134: }
|