KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > template > utility > DOMNodeModel


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.template.utility;
54
55 import freemarker.template.*;
56 import org.w3c.dom.*;
57 import java.util.*;
58
59 /**
60  * A convenient wrapper class for wrapping a Node in the W3C DOM API.
61  * @author <a HREF="mailto:jon@revusky.com">Jonathan Revusky</a>
62  */

63
64 public class DOMNodeModel implements TemplateHashModel {
65
66     static private HashMap equivalenceTable = new HashMap();
67     static {
68         equivalenceTable.put("*", "children");
69         equivalenceTable.put("@*", "attributes");
70     }
71
72     private Node node;
73     private HashMap cache = new HashMap();
74
75     public DOMNodeModel(Node node) {
76         this.node = node;
77     }
78
79     public TemplateModel get(String JavaDoc key) throws TemplateModelException {
80         TemplateModel result = null;
81         if (equivalenceTable.containsKey(key)) {
82             key = (String JavaDoc) equivalenceTable.get(key);
83         }
84         if (cache.containsKey(key)) {
85             result = (TemplateModel) cache.get(key);
86         }
87         if (result == null) {
88             if ("attributes".equals(key)) {
89                 NamedNodeMap attributes = node.getAttributes();
90                 if (attributes != null) {
91                     SimpleHash hash = new SimpleHash();
92                     for (int i = 0; i<attributes.getLength(); i++) {
93                         Attr att = (Attr) attributes.item(i);
94                         hash.put(att.getName(), att.getValue());
95                     }
96                     result = hash;
97                 }
98             }
99             else if (key.charAt(0) == '@') {
100                 if (node instanceof Element) {
101                     String JavaDoc attValue = ((Element) node).getAttribute(key.substring(1));
102                     result = new SimpleScalar(attValue);
103                 }
104                 else {
105                     throw new TemplateModelException("Trying to get an attribute value for a non-element node");
106                 }
107             }
108             else if ("is_element".equals(key)) {
109                 result = (node instanceof Element) ?
110                     TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
111             }
112             else if ("is_text".equals(key)) {
113                 result = (node instanceof Text) ?
114                     TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
115             }
116             else if ("name".equals(key)) {
117                 result = new SimpleScalar(node.getNodeName());
118             }
119             else if ("children".equals(key)) {
120                 result = new NodeListTM(node.getChildNodes());
121             }
122             else if ("parent".equals(key)) {
123                 Node parent = node.getParentNode();
124                 result = (parent == null) ? null : new DOMNodeModel(parent);
125             }
126             else if ("ancestorByName".equals(key)) {
127                 result = new AncestorByName();
128             }
129             else if ("nextSibling".equals(key)) {
130                 Node next = node.getNextSibling();
131                 result = (next == null) ? null : new DOMNodeModel(next);
132             }
133             else if ("previousSibling".equals(key)) {
134                 Node previous = node.getPreviousSibling();
135                 result = (previous == null) ? null : new DOMNodeModel(previous);
136             }
137             else if ("nextSiblingElement".equals(key)) {
138                 Node next = nextSiblingElement(node);
139                 result = (next == null) ? null : new DOMNodeModel(next);
140             }
141             else if ("previousSiblingElement".equals(key)) {
142                 Node previous = previousSiblingElement(node);
143                 result = (previous == null) ? null : new DOMNodeModel(previous);
144             }
145             else if ("nextElement".equals(key)) {
146                 Node next = nextElement(node);
147                 result = (next == null) ? null : new DOMNodeModel(next);
148             }
149             else if ("previousElement".equals(key)) {
150                 Node previous = previousElement(node);
151                 result = (previous == null) ? null : new DOMNodeModel(previous);
152             }
153             else if ("text".equals(key)) {
154                 result = new SimpleScalar(getText(node));
155             }
156             cache.put(key, result);
157         }
158         return result;
159     }
160
161     public boolean isEmpty() {
162         return false;
163     }
164
165     static private String JavaDoc getText(Node node) {
166         String JavaDoc result = "";
167         if (node instanceof Text) {
168             result = ((Text) node).getData();
169         }
170         else if (node instanceof Element) {
171             NodeList children = node.getChildNodes();
172             for (int i= 0; i<children.getLength(); i++) {
173                 result += getText(children.item(i));
174             }
175         }
176         return result;
177     }
178
179     static private Element nextSiblingElement(Node node) {
180         Node next = node;
181         while (next != null) {
182             next = next.getNextSibling();
183             if (next instanceof Element) {
184                 return (Element) next;
185             }
186         }
187         return null;
188     }
189
190     static private Element previousSiblingElement(Node node) {
191         Node previous = node;
192         while (previous != null) {
193             previous = previous.getPreviousSibling();
194             if (previous instanceof Element) {
195                 return (Element) previous;
196             }
197         }
198         return null;
199     }
200
201     static private Element nextElement(Node node) {
202         if (node.hasChildNodes()) {
203             NodeList children = node.getChildNodes();
204             for (int i=0; i<children.getLength();i++) {
205                 Node child = children.item(i);
206                 if (child instanceof Element) {
207                     return (Element) child;
208                 }
209             }
210         }
211         Element nextSiblingElement = nextSiblingElement(node);
212         if (nextSiblingElement != null) {
213             return nextSiblingElement;
214         }
215         Node parent = node.getParentNode();
216         while (parent instanceof Element) {
217             Element next = nextSiblingElement(parent);
218             if (next != null) {
219                 return next;
220             }
221             parent = parent.getParentNode();
222         }
223         return null;
224     }
225
226     static private Element previousElement(Node node) {
227         Element result = previousSiblingElement(node);
228         if (result != null) {
229             return result;
230         }
231         Node parent = node.getParentNode();
232         if (parent instanceof Element) {
233             return (Element) parent;
234         }
235         return null;
236     }
237
238     void setParent(DOMNodeModel parent) {
239         if (parent != null) {
240             cache.put("parent", parent);
241         }
242     }
243
244     String JavaDoc getNodeName() {
245         return node.getNodeName();
246     }
247
248
249     class AncestorByName implements TemplateMethodModel {
250         public Object JavaDoc exec(List arguments) throws TemplateModelException {
251             if (arguments.size() != 1) {
252                 throw new TemplateModelException("Expecting exactly one string argument here");
253             }
254             String JavaDoc nodeName = (String JavaDoc) arguments.get(0);
255             DOMNodeModel ancestor = (DOMNodeModel) DOMNodeModel.this.get("parent");
256             while (ancestor != null) {
257                 if (nodeName.equals(ancestor.getNodeName())) {
258                     return ancestor;
259                 }
260                 ancestor = (DOMNodeModel) ancestor.get("parent");
261             }
262             return null;
263         }
264     }
265
266
267     class NodeListTM implements TemplateSequenceModel, TemplateMethodModel {
268
269         private NodeList nodeList;
270         private TemplateModel[] nodes;
271
272         NodeListTM(NodeList nodeList) {
273             this.nodeList = nodeList;
274             nodes = new TemplateModel[nodeList.getLength()];
275         }
276
277         public TemplateModel get(int index) {
278             DOMNodeModel result = (DOMNodeModel) nodes[index];
279             if (result == null) {
280                 result = new DOMNodeModel(nodeList.item(index));
281                 nodes[index] = result;
282                 result.setParent(DOMNodeModel.this);
283             }
284             return result;
285         }
286
287         public int size() {
288             return nodes.length;
289         }
290
291         public Object JavaDoc exec(List arguments) throws TemplateModelException {
292             if (arguments.size() != 1) {
293                 throw new TemplateModelException("Expecting exactly one string argument here");
294             }
295             if (!(node instanceof Element)) {
296                 throw new TemplateModelException("Expecting element here.");
297             }
298             Element elem = (Element) node;
299             return new NodeListTM(elem.getElementsByTagName((String JavaDoc) arguments.get(0)));
300         }
301     }
302 }
303
304
Popular Tags