KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > ext > dom > NodeOutputter


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

52  
53 package freemarker.ext.dom;
54
55 import freemarker.template.utility.StringUtil;
56 import freemarker.template.Template;
57 import freemarker.core.Environment;
58 import java.util.*;
59 import org.w3c.dom.*;
60
61 class NodeOutputter {
62     
63     private Element contextNode;
64     private Environment env;
65     private String JavaDoc defaultNS;
66     private boolean hasDefaultNS;
67     private boolean explicitDefaultNSPrefix;
68     private HashMap namespacesToPrefixLookup = new HashMap();
69     private String JavaDoc namespaceDecl;
70     
71     NodeOutputter(Node node) {
72         if (node instanceof Element) {
73             setContext((Element) node);
74         }
75         else if (node instanceof Attr) {
76             setContext(((Attr) node).getOwnerElement());
77         }
78         else if (node instanceof Document) {
79             setContext(((Document) node).getDocumentElement());
80         }
81     }
82     
83     private void setContext(Element contextNode) {
84         this.contextNode = contextNode;
85         this.env = Environment.getCurrentEnvironment();
86         this.defaultNS = env.getDefaultNS();
87         this.hasDefaultNS = defaultNS != null && defaultNS.length() >0;
88         namespacesToPrefixLookup.put(null, "");
89         namespacesToPrefixLookup.put("", "");
90         buildPrefixLookup(contextNode);
91         if (!explicitDefaultNSPrefix && hasDefaultNS) {
92             namespacesToPrefixLookup.put(defaultNS, "");
93         }
94         constructNamespaceDecl();
95     }
96     
97     private void buildPrefixLookup(Node n) {
98         String JavaDoc nsURI = n.getNamespaceURI();
99         if (nsURI != null && nsURI.length() >0) {
100             String JavaDoc prefix = env.getPrefixForNamespace(nsURI);
101             namespacesToPrefixLookup.put(nsURI, prefix);
102         } else if (hasDefaultNS && n.getNodeType() == Node.ELEMENT_NODE) {
103             namespacesToPrefixLookup.put(defaultNS, Template.DEFAULT_NAMESPACE_PREFIX);
104             explicitDefaultNSPrefix = true;
105         } else if (n.getNodeType() == Node.ATTRIBUTE_NODE && hasDefaultNS && defaultNS.equals(nsURI)) {
106             namespacesToPrefixLookup.put(defaultNS, Template.DEFAULT_NAMESPACE_PREFIX);
107             explicitDefaultNSPrefix = true;
108         }
109         NodeList childNodes = n.getChildNodes();
110         for (int i = 0; i<childNodes.getLength(); i++) {
111             buildPrefixLookup(childNodes.item(i));
112         }
113     }
114     
115     private void constructNamespaceDecl() {
116         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
117         if (explicitDefaultNSPrefix) {
118             buf.append(" xmlns=\"");
119             buf.append(defaultNS);
120             buf.append("\"");
121         }
122         for (Iterator it = namespacesToPrefixLookup.keySet().iterator(); it.hasNext();) {
123             String JavaDoc nsURI = (String JavaDoc) it.next();
124             if (nsURI == null || nsURI.length() == 0) {
125                 continue;
126             }
127             String JavaDoc prefix = (String JavaDoc) namespacesToPrefixLookup.get(nsURI);
128             if (prefix == null) {
129                 // Okay, let's auto-assign a prefix.
130
// Should we do this??? (REVISIT)
131
for (int i=0;i<26;i++) {
132                     char[] cc = new char[1];
133                     cc[0] = (char) ('a' + i);
134                     prefix = new String JavaDoc(cc);
135                     if (env.getNamespaceForPrefix(prefix) == null) {
136                         break;
137                     }
138                     prefix = null;
139                 }
140                 if (prefix == null) {
141                     throw new RuntimeException JavaDoc("This will almost never happen!");
142                 }
143                 namespacesToPrefixLookup.put(nsURI, prefix);
144             }
145             buf.append(" xmlns");
146             if (prefix.length() >0) {
147                 buf.append(":");
148                 buf.append(prefix);
149             }
150             buf.append("=\"");
151             buf.append(nsURI);
152             buf.append("\"");
153         }
154         this.namespaceDecl = buf.toString();
155     }
156     
157     private void outputQualifiedName(Node n, StringBuffer JavaDoc buf) {
158         String JavaDoc nsURI = n.getNamespaceURI();
159         if (nsURI == null || nsURI.length() == 0) {
160             buf.append(n.getNodeName());
161         } else {
162             String JavaDoc prefix = (String JavaDoc) namespacesToPrefixLookup.get(nsURI);
163             if (prefix == null) {
164                 //REVISIT!
165
buf.append(n.getNodeName());
166             } else {
167                 if (prefix.length() > 0) {
168                     buf.append(prefix);
169                     buf.append(':');
170                 }
171                 buf.append(n.getLocalName());
172             }
173         }
174     }
175     
176     void outputContent(Node n, StringBuffer JavaDoc buf) {
177         switch(n.getNodeType()) {
178             case Node.ATTRIBUTE_NODE: {
179                 if (((Attr) n).getSpecified()) {
180                     buf.append(' ');
181                     outputQualifiedName(n, buf);
182                     buf.append("=\"")
183                        .append(StringUtil.XMLEncQAttr(n.getNodeValue()))
184                        .append('"');
185                 }
186                 break;
187             }
188             case Node.COMMENT_NODE: {
189                 buf.append("<!--").append(n.getNodeValue()).append("-->");
190                 break;
191             }
192             case Node.DOCUMENT_NODE: {
193                 outputContent(n.getChildNodes(), buf);
194                 break;
195             }
196             case Node.DOCUMENT_TYPE_NODE: {
197                 buf.append("<!DOCTYPE ").append(n.getNodeName());
198                 DocumentType dt = (DocumentType)n;
199                 if(dt.getPublicId() != null) {
200                     buf.append(" PUBLIC \"").append(dt.getPublicId()).append('"');
201                 }
202                 if(dt.getSystemId() != null) {
203                     buf.append(" \"").append(dt.getSystemId()).append('"');
204                 }
205                 if(dt.getInternalSubset() != null) {
206                     buf.append(" [").append(dt.getInternalSubset()).append(']');
207                 }
208                 buf.append('>');
209                 break;
210             }
211             case Node.ELEMENT_NODE: {
212                 buf.append('<');
213                 outputQualifiedName(n, buf);
214                 if (n == contextNode) {
215                     buf.append(namespaceDecl);
216                 }
217                 outputContent(n.getAttributes(), buf);
218                 NodeList children = n.getChildNodes();
219                 if (children.getLength() == 0) {
220                     buf.append(" />");
221                 } else {
222                     buf.append('>');
223                     outputContent(n.getChildNodes(), buf);
224                     buf.append("</");
225                     outputQualifiedName(n, buf);
226                     buf.append('>');
227                 }
228                 break;
229             }
230             case Node.ENTITY_NODE: {
231                 outputContent(n.getChildNodes(), buf);
232                 break;
233             }
234             case Node.ENTITY_REFERENCE_NODE: {
235                 buf.append('&').append(n.getNodeName()).append(';');
236                 break;
237             }
238             case Node.PROCESSING_INSTRUCTION_NODE: {
239                 buf.append("<?").append(n.getNodeName()).append(' ').append(n.getNodeValue()).append("?>");
240                 break;
241             }
242             /*
243                         case Node.CDATA_SECTION_NODE: {
244                             buf.append("<![CDATA[").append(n.getNodeValue()).append("]]>");
245                             break;
246                         }*/

247             case Node.CDATA_SECTION_NODE:
248             case Node.TEXT_NODE: {
249                 buf.append(StringUtil.XMLEncNQG(n.getNodeValue()));
250                 break;
251             }
252         }
253     }
254
255     void outputContent(NodeList nodes, StringBuffer JavaDoc buf) {
256         for(int i = 0; i < nodes.getLength(); ++i) {
257             outputContent(nodes.item(i), buf);
258         }
259     }
260     
261     void outputContent(NamedNodeMap nodes, StringBuffer JavaDoc buf) {
262         for(int i = 0; i < nodes.getLength(); ++i) {
263             Node n = nodes.item(i);
264             if (n.getNodeType() != Node.ATTRIBUTE_NODE
265                 || (!n.getNodeName().startsWith("xmlns:") && !n.getNodeName().equals("xmlns")))
266             {
267                 outputContent(n, buf);
268             }
269         }
270     }
271     
272     String JavaDoc getOpeningTag(Element element) {
273         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
274         buf.append('<');
275         outputQualifiedName(element, buf);
276         buf.append(namespaceDecl);
277         outputContent(element.getAttributes(), buf);
278         buf.append('>');
279         return buf.toString();
280     }
281     
282     String JavaDoc getClosingTag(Element element) {
283         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
284         buf.append("</");
285         outputQualifiedName(element, buf);
286         buf.append('>');
287         return buf.toString();
288     }
289 }
290
Popular Tags