KickJava   Java API By Example, From Geeks To Geeks.

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


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.*;
56 import freemarker.core.Environment;
57 import org.w3c.dom.*;
58 import org.w3c.dom.traversal.NodeIterator;
59 import org.apache.xpath.*;
60 import org.apache.xpath.objects.*;
61 import org.apache.xml.utils.PrefixResolver;
62 import java.util.List JavaDoc;
63 import javax.xml.transform.TransformerException JavaDoc;
64
65 /**
66  * Some glue code that bridges the Xalan XPath stuff (that is built into the JDK 1.4.x)
67  * with FreeMarker TemplateModel semantics
68  * @author Jonathan Revusky
69  * @version $Id: XalanXPathSupport.java,v 1.20 2004/01/02 20:20:23 ddekany Exp $
70  */

71
72 class XalanXPathSupport implements XPathSupport {
73     
74     private XPathContext xpathContext = new XPathContext();
75         
76     /* I don't recommend Jaxen...
77     private static final String ERRMSG_RECOMMEND_JAXEN
78             = "(Note that there is no such restriction if you "
79                     + "configure FreeMarker to use Jaxen instead of Xalan.)";
80     */

81     private static final String JavaDoc ERRMSG_EMPTY_NODE_SET
82             = "Cannot perform an XPath query against an empty node set."; /* " + ERRMSG_RECOMMEND_JAXEN;*/
83     
84     synchronized public TemplateModel executeQuery(Object JavaDoc context, String JavaDoc xpathQuery) throws TemplateModelException {
85         if (!(context instanceof Node)) {
86             if (context != null) {
87                 if (isNodeList(context)) {
88                     int cnt = ((List JavaDoc) context).size();
89                     if (cnt != 0) {
90                         throw new TemplateModelException(
91                                 "Cannot perform an XPath query against a node set of " + cnt
92                                 + " nodes. Expecting a single node."/* " + ERRMSG_RECOMMEND_JAXEN*/);
93                     } else {
94                         throw new TemplateModelException(ERRMSG_EMPTY_NODE_SET);
95                     }
96                 } else {
97                     throw new TemplateModelException(
98                             "Cannot perform an XPath query against a " + context.getClass().getName()
99                             + ". Expecting a single org.w3c.dom.Node.");
100                 }
101             } else {
102                 throw new TemplateModelException(ERRMSG_EMPTY_NODE_SET);
103             }
104         }
105         Node node = (Node) context;
106         try {
107             XPath xpath = new XPath(xpathQuery, null, customPrefixResolver, XPath.SELECT, null);
108             int ctxtNode = xpathContext.getDTMHandleFromNode(node);
109             XObject xresult = xpath.execute(xpathContext, ctxtNode, customPrefixResolver);
110             if (xresult instanceof XNodeSet) {
111                 NodeListModel result = new NodeListModel(node);
112                 result.xpathSupport = this;
113                 NodeIterator nodeIterator = xresult.nodeset();
114                 Node n;
115                 do {
116                     n = nodeIterator.nextNode();
117                     if (n != null) {
118                         result.add(n);
119                     }
120                 } while (n != null);
121                 return result.size() == 1 ? result.get(0) : result;
122             }
123             if (xresult instanceof XBoolean) {
124                 return ((XBoolean) xresult).bool() ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
125             }
126             if (xresult instanceof XNull) {
127                 return null;
128             }
129             if (xresult instanceof XString) {
130                 return new SimpleScalar(xresult.toString());
131             }
132             if (xresult instanceof XNumber) {
133                 return new SimpleNumber(new Double JavaDoc(((XNumber) xresult).num()));
134             }
135             throw new TemplateModelException("Cannot deal with type: " + xresult.getClass().getName());
136         } catch (TransformerException JavaDoc te) {
137             throw new TemplateModelException(te);
138         }
139     }
140     
141     private static PrefixResolver customPrefixResolver = new PrefixResolver() {
142         
143         public String JavaDoc getNamespaceForPrefix(String JavaDoc prefix, Node node) {
144             return getNamespaceForPrefix(prefix);
145         }
146         
147         public String JavaDoc getNamespaceForPrefix(String JavaDoc prefix) {
148             if (prefix.equals(Template.DEFAULT_NAMESPACE_PREFIX)) {
149                 return Environment.getCurrentEnvironment().getDefaultNS();
150             }
151             return Environment.getCurrentEnvironment().getNamespaceForPrefix(prefix);
152         }
153         
154         public String JavaDoc getBaseIdentifier() {
155             return null;
156         }
157         
158         public boolean handlesNullPrefixes() {
159             return false;
160         }
161     };
162     
163     /**
164      * Used for generating more intelligent error messages.
165      */

166     private static boolean isNodeList(Object JavaDoc context) {
167         if (context instanceof List JavaDoc) {
168             List JavaDoc ls = (List JavaDoc) context;
169             int ln = ls.size();
170             for (int i = 0; i < ln; i++) {
171                 if (!(ls.get(i) instanceof Node)) {
172                     return false;
173                 }
174             }
175             return true;
176         } else {
177             return false;
178         }
179     }
180 }
Popular Tags