1   /*
2    * Copyright 2005-2010 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 org.springframework.util.StringUtils;
28  
29  import org.junit.Assert;
30  import org.junit.Before;
31  import org.junit.Test;
32  import org.w3c.dom.DOMException;
33  import org.w3c.dom.Document;
34  import org.w3c.dom.Node;
35  import org.xml.sax.SAXException;
36  
37  public abstract class AbstractXPathExpressionFactoryTestCase {
38  
39      private Document noNamespacesDocument;
40  
41      private Document namespacesDocument;
42  
43      private Map<String, String> namespaces = new HashMap<String, String>();
44  
45      @Before
46      public void setUp() throws Exception {
47          namespaces.put("prefix1", "namespace1");
48          namespaces.put("prefix2", "namespace2");
49          DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
50          documentBuilderFactory.setNamespaceAware(true);
51          DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
52          InputStream inputStream = getClass().getResourceAsStream("nonamespaces.xml");
53          try {
54              noNamespacesDocument = documentBuilder.parse(inputStream);
55          }
56          finally {
57              inputStream.close();
58          }
59          inputStream = getClass().getResourceAsStream("namespaces.xml");
60          try {
61              namespacesDocument = documentBuilder.parse(inputStream);
62          }
63          finally {
64              inputStream.close();
65          }
66      }
67  
68      @Test
69      public void testEvaluateAsBooleanInvalidNamespaces() throws IOException, SAXException {
70          XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:otherchild", namespaces);
71          boolean result = expression.evaluateAsBoolean(namespacesDocument);
72          Assert.assertFalse("Invalid result [" + result + "]", result);
73      }
74  
75      @Test
76      public void testEvaluateAsBooleanInvalidNoNamespaces() throws IOException, SAXException {
77          XPathExpression expression = createXPathExpression("/root/otherchild");
78          boolean result = expression.evaluateAsBoolean(noNamespacesDocument);
79          Assert.assertFalse("Invalid result [" + result + "]", result);
80      }
81  
82      @Test
83      public void testEvaluateAsBooleanNamespaces() throws IOException, SAXException {
84          XPathExpression expression =
85                  createXPathExpression("/prefix1:root/prefix2:child/prefix2:boolean/text()", namespaces);
86          boolean result = expression.evaluateAsBoolean(namespacesDocument);
87          Assert.assertTrue("Invalid result", result);
88      }
89  
90      @Test
91      public void testEvaluateAsBooleanNoNamespaces() throws IOException, SAXException {
92          XPathExpression expression = createXPathExpression("/root/child/boolean/text()");
93          boolean result = expression.evaluateAsBoolean(noNamespacesDocument);
94          Assert.assertTrue("Invalid result", result);
95      }
96  
97      @Test
98      public void testEvaluateAsDoubleInvalidNamespaces() throws IOException, SAXException {
99          XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:otherchild", namespaces);
100         double result = expression.evaluateAsNumber(noNamespacesDocument);
101         Assert.assertTrue("Invalid result [" + result + "]", Double.isNaN(result));
102     }
103 
104     @Test
105     public void testEvaluateAsDoubleInvalidNoNamespaces() throws IOException, SAXException {
106         XPathExpression expression = createXPathExpression("/root/otherchild");
107         double result = expression.evaluateAsNumber(noNamespacesDocument);
108         Assert.assertTrue("Invalid result [" + result + "]", Double.isNaN(result));
109     }
110 
111     @Test
112     public void testEvaluateAsDoubleNamespaces() throws IOException, SAXException {
113         XPathExpression expression =
114                 createXPathExpression("/prefix1:root/prefix2:child/prefix2:number/text()", namespaces);
115         double result = expression.evaluateAsNumber(namespacesDocument);
116         Assert.assertEquals("Invalid result", 42D, result, 0D);
117     }
118 
119     @Test
120     public void testEvaluateAsDoubleNoNamespaces() throws IOException, SAXException {
121         XPathExpression expression = createXPathExpression("/root/child/number/text()");
122         double result = expression.evaluateAsNumber(noNamespacesDocument);
123         Assert.assertEquals("Invalid result", 42D, result, 0D);
124     }
125 
126     @Test
127     public void testEvaluateAsNodeInvalidNamespaces() throws IOException, SAXException {
128         XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:otherchild", namespaces);
129         Node result = expression.evaluateAsNode(namespacesDocument);
130         Assert.assertNull("Invalid result [" + result + "]", result);
131     }
132 
133     @Test
134     public void testEvaluateAsNodeInvalidNoNamespaces() throws IOException, SAXException {
135         XPathExpression expression = createXPathExpression("/root/otherchild");
136         Node result = expression.evaluateAsNode(noNamespacesDocument);
137         Assert.assertNull("Invalid result [" + result + "]", result);
138     }
139 
140     @Test
141     public void testEvaluateAsNodeNamespaces() throws IOException, SAXException {
142         XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:child", namespaces);
143         Node result = expression.evaluateAsNode(namespacesDocument);
144         Assert.assertNotNull("Invalid result", result);
145         Assert.assertEquals("Invalid localname", "child", result.getLocalName());
146     }
147 
148     @Test
149     public void testEvaluateAsNodeNoNamespaces() throws IOException, SAXException {
150         XPathExpression expression = createXPathExpression("/root/child");
151         Node result = expression.evaluateAsNode(noNamespacesDocument);
152         Assert.assertNotNull("Invalid result", result);
153         Assert.assertEquals("Invalid localname", "child", result.getLocalName());
154     }
155 
156     @Test
157     public void testEvaluateAsNodeListNamespaces() throws IOException, SAXException {
158         XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:child/*", namespaces);
159         List<Node> results = expression.evaluateAsNodeList(namespacesDocument);
160         Assert.assertNotNull("Invalid result", results);
161         Assert.assertEquals("Invalid amount of results", 3, results.size());
162     }
163 
164     @Test
165     public void testEvaluateAsNodeListNoNamespaces() throws IOException, SAXException {
166         XPathExpression expression = createXPathExpression("/root/child/*");
167         List<Node> results = expression.evaluateAsNodeList(noNamespacesDocument);
168         Assert.assertNotNull("Invalid result", results);
169         Assert.assertEquals("Invalid amount of results", 3, results.size());
170     }
171 
172     @Test
173     public void testEvaluateAsStringInvalidNamespaces() throws IOException, SAXException {
174         XPathExpression expression = createXPathExpression("/prefix1:root/prefix2:otherchild", namespaces);
175         String result = expression.evaluateAsString(namespacesDocument);
176         Assert.assertFalse("Invalid result [" + result + "]", StringUtils.hasText(result));
177     }
178 
179     @Test
180     public void testEvaluateAsStringInvalidNoNamespaces() throws IOException, SAXException {
181         XPathExpression expression = createXPathExpression("/root/otherchild");
182         String result = expression.evaluateAsString(noNamespacesDocument);
183         Assert.assertFalse("Invalid result [" + result + "]", StringUtils.hasText(result));
184     }
185 
186     @Test
187     public void testEvaluateAsStringNamespaces() throws IOException, SAXException {
188         XPathExpression expression =
189                 createXPathExpression("/prefix1:root/prefix2:child/prefix2:text/text()", namespaces);
190         String result = expression.evaluateAsString(namespacesDocument);
191         Assert.assertEquals("Invalid result", "text", result);
192     }
193 
194     @Test
195     public void testEvaluateAsStringNoNamespaces() throws IOException, SAXException {
196         XPathExpression expression = createXPathExpression("/root/child/text/text()");
197         String result = expression.evaluateAsString(noNamespacesDocument);
198         Assert.assertEquals("Invalid result", "text", result);
199     }
200 
201     @Test
202     public void testEvaluateAsObject() throws Exception {
203         XPathExpression expression = createXPathExpression("/root/child");
204         String result = expression.evaluateAsObject(noNamespacesDocument, new NodeMapper<String>() {
205             public String mapNode(Node node, int nodeNum) throws DOMException {
206                 return node.getLocalName();
207             }
208         });
209         Assert.assertNotNull("Invalid result", result);
210         Assert.assertEquals("Invalid localname", "child", result);
211     }
212 
213     @Test
214     public void testEvaluate() throws Exception {
215         XPathExpression expression = createXPathExpression("/root/child/*");
216         List<String> results = expression.evaluate(noNamespacesDocument, new NodeMapper<String>() {
217             public String mapNode(Node node, int nodeNum) throws DOMException {
218                 return node.getLocalName();
219             }
220         });
221         Assert.assertNotNull("Invalid result", results);
222         Assert.assertEquals("Invalid amount of results", 3, results.size());
223         Assert.assertEquals("Invalid first result", "text", results.get(0));
224         Assert.assertEquals("Invalid first result", "number", results.get(1));
225         Assert.assertEquals("Invalid first result", "boolean", results.get(2));
226     }
227 
228     @Test
229     public void testInvalidExpression() {
230         try {
231             createXPathExpression("\\");
232             Assert.fail("No XPathParseException thrown");
233         }
234         catch (XPathParseException ex) {
235             // Expected behaviour
236         }
237     }
238 
239     protected abstract XPathExpression createXPathExpression(String expression);
240 
241     protected abstract XPathExpression createXPathExpression(String expression, Map<String, String> namespaces);
242 }