1   /*
2    * Copyright 2006 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.xml.xpath;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  import javax.xml.parsers.DocumentBuilder;
25  import javax.xml.parsers.DocumentBuilderFactory;
26  
27  import junit.framework.TestCase;
28  import org.springframework.util.StringUtils;
29  import org.w3c.dom.DOMException;
30  import org.w3c.dom.Document;
31  import org.w3c.dom.Node;
32  import org.xml.sax.SAXException;
33  
34  public abstract class AbstractXPathExpressionFactoryTestCase extends TestCase {
35  
36      private Document noNamespacesDocument;
37  
38      private Document namespacesDocument;
39  
40      private Map namespaces = new HashMap();
41  
42      protected void setUp() throws Exception {
43          namespaces.put("prefix1", "namespace1");
44          namespaces.put("prefix2", "namespace2");
45          DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
46          documentBuilderFactory.setNamespaceAware(true);
47          DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
48          InputStream inputStream = getClass().getResourceAsStream("nonamespaces.xml");
49          try {
50              noNamespacesDocument = documentBuilder.parse(inputStream);
51          }
52          finally {
53              inputStream.close();
54          }
55          inputStream = getClass().getResourceAsStream("namespaces.xml");
56          try {
57              namespacesDocument = documentBuilder.parse(inputStream);
58          }
59          finally {
60              inputStream.close();
61          }
62      }
63  
64      public void testEvaluateAsBooleanInvalidNamespaces() throws IOException, SAXException {
65          XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:otherchild", namespaces);
66          boolean result = expression.evaluateAsBoolean(namespacesDocument);
67          assertFalse("Invalid result [" + result + "]", result);
68      }
69  
70      public void testEvaluateAsBooleanInvalidNoNamespaces() throws IOException, SAXException {
71          XPathExpression expression = createXPathExpression("/root/otherchild");
72          boolean result = expression.evaluateAsBoolean(noNamespacesDocument);
73          assertFalse("Invalid result [" + result + "]", result);
74      }
75  
76      public void testEvaluateAsBooleanNamespaces() throws IOException, SAXException {
77          XPathExpression expression =
78                  createXPathExpression("/prefix1:root/prefix2:child/prefix2:boolean/text()", namespaces);
79          boolean result = expression.evaluateAsBoolean(namespacesDocument);
80          assertTrue("Invalid result", result);
81      }
82  
83      public void testEvaluateAsBooleanNoNamespaces() throws IOException, SAXException {
84          XPathExpression expression = createXPathExpression("/root/child/boolean/text()");
85          boolean result = expression.evaluateAsBoolean(noNamespacesDocument);
86          assertTrue("Invalid result", result);
87      }
88  
89      public void testEvaluateAsDoubleInvalidNamespaces() throws IOException, SAXException {
90          XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:otherchild", namespaces);
91          double result = expression.evaluateAsNumber(noNamespacesDocument);
92          assertTrue("Invalid result [" + result + "]", Double.isNaN(result));
93      }
94  
95      public void testEvaluateAsDoubleInvalidNoNamespaces() throws IOException, SAXException {
96          XPathExpression expression = createXPathExpression("/root/otherchild");
97          double result = expression.evaluateAsNumber(noNamespacesDocument);
98          assertTrue("Invalid result [" + result + "]", Double.isNaN(result));
99      }
100 
101     public void testEvaluateAsDoubleNamespaces() throws IOException, SAXException {
102         XPathExpression expression =
103                 createXPathExpression("/prefix1:root/prefix2:child/prefix2:number/text()", namespaces);
104         double result = expression.evaluateAsNumber(namespacesDocument);
105         assertEquals("Invalid result", 42D, result, 0D);
106     }
107 
108     public void testEvaluateAsDoubleNoNamespaces() throws IOException, SAXException {
109         XPathExpression expression = createXPathExpression("/root/child/number/text()");
110         double result = expression.evaluateAsNumber(noNamespacesDocument);
111         assertEquals("Invalid result", 42D, result, 0D);
112     }
113 
114     public void testEvaluateAsNodeInvalidNamespaces() throws IOException, SAXException {
115         XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:otherchild", namespaces);
116         Node result = expression.evaluateAsNode(namespacesDocument);
117         assertNull("Invalid result [" + result + "]", result);
118     }
119 
120     public void testEvaluateAsNodeInvalidNoNamespaces() throws IOException, SAXException {
121         XPathExpression expression = createXPathExpression("/root/otherchild");
122         Node result = expression.evaluateAsNode(noNamespacesDocument);
123         assertNull("Invalid result [" + result + "]", result);
124     }
125 
126     public void testEvaluateAsNodeNamespaces() throws IOException, SAXException {
127         XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:child", namespaces);
128         Node result = expression.evaluateAsNode(namespacesDocument);
129         assertNotNull("Invalid result", result);
130         assertEquals("Invalid localname", "child", result.getLocalName());
131     }
132 
133     public void testEvaluateAsNodeNoNamespaces() throws IOException, SAXException {
134         XPathExpression expression = createXPathExpression("/root/child");
135         Node result = expression.evaluateAsNode(noNamespacesDocument);
136         assertNotNull("Invalid result", result);
137         assertEquals("Invalid localname", "child", result.getLocalName());
138     }
139 
140     public void testEvaluateAsNodeListNamespaces() throws IOException, SAXException {
141         XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:child/*", namespaces);
142         List results = expression.evaluateAsNodeList(namespacesDocument);
143         assertNotNull("Invalid result", results);
144         assertEquals("Invalid amount of results", 3, results.size());
145     }
146 
147     public void testEvaluateAsNodeListNoNamespaces() throws IOException, SAXException {
148         XPathExpression expression = createXPathExpression("/root/child/*");
149         List results = expression.evaluateAsNodeList(noNamespacesDocument);
150         assertNotNull("Invalid result", results);
151         assertEquals("Invalid amount of results", 3, results.size());
152     }
153 
154     public void testEvaluateAsStringInvalidNamespaces() throws IOException, SAXException {
155         XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:otherchild", namespaces);
156         String result = expression.evaluateAsString(namespacesDocument);
157         assertFalse("Invalid result [" + result + "]", StringUtils.hasText(result));
158     }
159 
160     public void testEvaluateAsStringInvalidNoNamespaces() throws IOException, SAXException {
161         XPathExpression expression = createXPathExpression("/root/otherchild");
162         String result = expression.evaluateAsString(noNamespacesDocument);
163         assertFalse("Invalid result [" + result + "]", StringUtils.hasText(result));
164     }
165 
166     public void testEvaluateAsStringNamespaces() throws IOException, SAXException {
167         XPathExpression expression =
168                 createXPathExpression("/prefix1:root/prefix2:child/prefix2:text/text()", namespaces);
169         String result = expression.evaluateAsString(namespacesDocument);
170         assertEquals("Invalid result", "text", result);
171     }
172 
173     public void testEvaluateAsStringNoNamespaces() throws IOException, SAXException {
174         XPathExpression expression = createXPathExpression("/root/child/text/text()");
175         String result = expression.evaluateAsString(noNamespacesDocument);
176         assertEquals("Invalid result", "text", result);
177     }
178 
179     public void testEvaluateAsObject() throws Exception {
180         XPathExpression expression = createXPathExpression("/root/child");
181         String result = (String) expression.evaluateAsObject(noNamespacesDocument, new NodeMapper() {
182             public Object mapNode(Node node, int nodeNum) throws DOMException {
183                 return node.getLocalName();
184             }
185         });
186         assertNotNull("Invalid result", result);
187         assertEquals("Invalid localname", "child", result);
188     }
189 
190     public void testEvaluate() throws Exception {
191         XPathExpression expression = createXPathExpression("/root/child/*");
192         List results = expression.evaluate(noNamespacesDocument, new NodeMapper() {
193             public Object mapNode(Node node, int nodeNum) throws DOMException {
194                 return node.getLocalName();
195             }
196         });
197         assertNotNull("Invalid result", results);
198         assertEquals("Invalid amount of results", 3, results.size());
199         assertEquals("Invalid first result", "text", results.get(0));
200         assertEquals("Invalid first result", "number", results.get(1));
201         assertEquals("Invalid first result", "boolean", results.get(2));
202     }
203 
204     public void testInvalidExpression() {
205         try {
206             createXPathExpression("\\");
207             fail("No XPathParseException thrown");
208         }
209         catch (XPathParseException ex) {
210             // Expected behaviour
211         }
212     }
213 
214     protected abstract XPathExpression createXPathExpression(String expression);
215 
216     protected abstract XPathExpression createXPathExpression(String expression, Map namespaces);
217 }