View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jxpath.ri;
18  
19  import org.apache.commons.jxpath.JXPathContext;
20  import org.apache.commons.jxpath.JXPathTestCase;
21  import org.apache.commons.jxpath.ri.compiler.Constant;
22  import org.apache.commons.jxpath.ri.compiler.CoreFunction;
23  import org.apache.commons.jxpath.ri.compiler.CoreOperationAdd;
24  import org.apache.commons.jxpath.ri.compiler.CoreOperationAnd;
25  import org.apache.commons.jxpath.ri.compiler.CoreOperationDivide;
26  import org.apache.commons.jxpath.ri.compiler.CoreOperationEqual;
27  import org.apache.commons.jxpath.ri.compiler.CoreOperationGreaterThan;
28  import org.apache.commons.jxpath.ri.compiler.CoreOperationGreaterThanOrEqual;
29  import org.apache.commons.jxpath.ri.compiler.CoreOperationLessThan;
30  import org.apache.commons.jxpath.ri.compiler.CoreOperationLessThanOrEqual;
31  import org.apache.commons.jxpath.ri.compiler.CoreOperationMod;
32  import org.apache.commons.jxpath.ri.compiler.CoreOperationMultiply;
33  import org.apache.commons.jxpath.ri.compiler.CoreOperationNegate;
34  import org.apache.commons.jxpath.ri.compiler.CoreOperationNotEqual;
35  import org.apache.commons.jxpath.ri.compiler.CoreOperationOr;
36  import org.apache.commons.jxpath.ri.compiler.CoreOperationSubtract;
37  import org.apache.commons.jxpath.ri.compiler.CoreOperationUnion;
38  import org.apache.commons.jxpath.ri.compiler.ExpressionPath;
39  import org.apache.commons.jxpath.ri.compiler.ExtensionFunction;
40  import org.apache.commons.jxpath.ri.compiler.LocationPath;
41  import org.apache.commons.jxpath.ri.compiler.NameAttributeTest;
42  import org.apache.commons.jxpath.ri.compiler.VariableReference;
43  
44  /**
45   * Test compiler.
46   *
47   * @author Dmitri Plotnikov
48   * @version $Revision: 779915 $ $Date: 2009-05-29 12:23:40 +0200 (Fr, 29 Mai 2009) $
49   */
50  
51  public class JXPathCompiledExpressionTest extends JXPathTestCase {
52  
53      public void testConstant() {
54          assertXPathExpression("1", Constant.class);
55          assertXPathExpression("1.5", Constant.class);
56          assertXPathExpression("'foo'", Constant.class);
57      }
58      
59      public void testCoreFunction() {
60          assertXPathExpression("last()", CoreFunction.class);
61          assertXPathExpression("position()", CoreFunction.class);
62          assertXPathExpression("count(book)", CoreFunction.class);
63          assertXPathExpression("id(13)", CoreFunction.class);
64          assertXPathExpression("local-name()", CoreFunction.class);
65          assertXPathExpression("local-name(book)", CoreFunction.class);
66          assertXPathExpression("namespace-uri()", CoreFunction.class);
67          assertXPathExpression("namespace-uri(book)", CoreFunction.class);
68          assertXPathExpression("name()", CoreFunction.class);
69          assertXPathExpression("name(book)", CoreFunction.class);
70          assertXPathExpression("string(3)", CoreFunction.class);
71          assertXPathExpression("concat('a', 'b')", CoreFunction.class);
72          assertXPathExpression("starts-with('a', 'b')", CoreFunction.class);
73          assertXPathExpression("ends-with('a', 'b')", CoreFunction.class);
74          assertXPathExpression("contains('a', 'b')", CoreFunction.class);
75          assertXPathExpression("substring-before('a', 1)", CoreFunction.class);
76          assertXPathExpression("substring-after('a', 2)", CoreFunction.class);
77          assertXPathExpression("substring('a', 2)", CoreFunction.class);
78          assertXPathExpression("substring('a', 2, 3)", CoreFunction.class);
79          assertXPathExpression("string-length('a')", CoreFunction.class);
80          assertXPathExpression("normalize-space('a')", CoreFunction.class);
81          assertXPathExpression("translate('a', 'b', 'c')", CoreFunction.class);
82          assertXPathExpression("boolean('true')", CoreFunction.class);
83          assertXPathExpression("not(1)", CoreFunction.class);
84          assertXPathExpression("true()", CoreFunction.class);
85          assertXPathExpression("false()", CoreFunction.class);
86          assertXPathExpression("lang('fr')", CoreFunction.class);
87          assertXPathExpression("number('12')", CoreFunction.class);
88          assertXPathExpression("sum(book/price)", CoreFunction.class);
89          assertXPathExpression("floor(11.4)", CoreFunction.class);
90          assertXPathExpression("ceiling(11.4)", CoreFunction.class);
91          assertXPathExpression("round(11.4)", CoreFunction.class);
92          assertXPathExpression("key('title', 'Hobbit')", CoreFunction.class);
93          assertXPathExpression("format-number(12, '##')", CoreFunction.class);
94      }
95      
96      public void testCoreOperationAnd() {
97          assertXPathExpression("2 and 4", CoreOperationAnd.class);
98          assertXPathExpression("2 > 1 and 4 < 5", CoreOperationAnd.class);
99      }
100         
101     public void testCoreOperationOr() {
102         assertXPathExpression("2 or 4", CoreOperationOr.class);
103         assertXPathExpression("2 > 1 or 4 < 5", CoreOperationOr.class);
104         assertXPathExpression("1 > 1 and 2 <= 2 or 3 = 4", CoreOperationOr.class);
105     }
106 
107     public void testCoreOperationEqual() {
108         assertXPathExpression("2 = 4", CoreOperationEqual.class);
109         assertXPathExpression("2 + 1 = 3", CoreOperationEqual.class);
110     }
111     
112     public void testCoreOperationNameAttributeTest() {
113         assertXPathExpression("@name = 'bar'", NameAttributeTest.class);
114     }
115 
116     public void testCoreOperationNotEqual() {
117         assertXPathExpression("2 != 4", CoreOperationNotEqual.class);
118         assertXPathExpression("2 + 1 != 3", CoreOperationNotEqual.class);
119     }
120 
121     public void testCoreOperationLessThan() {
122         assertXPathExpression("3<4", CoreOperationLessThan.class, "3 < 4");
123         assertXPathExpression("3<(2>=1)", CoreOperationLessThan.class, "3 < (2 >= 1)");
124     }
125     
126     public void testCoreOperationLessThanOrEqual() {
127         assertXPathExpression("3<=4", CoreOperationLessThanOrEqual.class, "3 <= 4");
128         assertXPathExpression("3<=(2>=1)", CoreOperationLessThanOrEqual.class, "3 <= (2 >= 1)");
129     }
130 
131     public void testCoreOperationGreaterThan() {
132         assertXPathExpression("3>4", CoreOperationGreaterThan.class, "3 > 4");
133         assertXPathExpression("3>(2>=1)", CoreOperationGreaterThan.class, "3 > (2 >= 1)");
134         assertXPathExpression("1 > (1 and 2 <= (2 or 3) = 4)", CoreOperationGreaterThan.class);
135     }
136     
137     public void testCoreOperationGreaterThanOrEqual() {
138         assertXPathExpression("3>=4", CoreOperationGreaterThanOrEqual.class, "3 >= 4");
139         assertXPathExpression("3>=(2>=1)", CoreOperationGreaterThanOrEqual.class, "3 >= (2 >= 1)");
140     }
141 
142     public void testCoreOperationDivide() {
143         assertXPathExpression("2 div 4", CoreOperationDivide.class);
144         assertXPathExpression("2|3 div -3", CoreOperationDivide.class, "2 | 3 div -3");
145     }
146 
147     public void testCoreOperationMod() {
148         assertXPathExpression("2 mod 4", CoreOperationMod.class);
149         assertXPathExpression("2|3 mod -3", CoreOperationMod.class, "2 | 3 mod -3");
150     }
151 
152     public void testCoreOperationMultiply() {
153         assertXPathExpression("2*4", CoreOperationMultiply.class, "2 * 4");
154         assertXPathExpression("2*(3 + 1)", CoreOperationMultiply.class, "2 * (3 + 1)");
155     }
156     
157     public void testCoreOperationMinus() {
158         assertXPathExpression("1 - 1", CoreOperationSubtract.class);
159         assertXPathExpression("1 - 1 - 2", CoreOperationSubtract.class);
160         assertXPathExpression("1 - (1 - 2)", CoreOperationSubtract.class);
161     }
162     
163     public void testCoreOperationSum() {
164         assertXPathExpression("3 + 1 + 4", CoreOperationAdd.class);
165         assertXPathExpression("(3 + 1) + 4", CoreOperationAdd.class, "3 + 1 + 4");
166         assertXPathExpression("3 + (1 + 4)", CoreOperationAdd.class, "3 + 1 + 4");
167         assertXPathExpression("3 + -1", CoreOperationAdd.class, "3 + -1");
168         assertXPathExpression("2*-3 + -1", CoreOperationAdd.class, "2 * -3 + -1");
169     }
170     
171     public void testCoreOperationUnaryMinus() {
172         assertXPathExpression("-3", CoreOperationNegate.class);
173         assertXPathExpression("-(3 + 1)", CoreOperationNegate.class);
174     }
175 
176     public void testCoreOperationUnion() {
177         assertXPathExpression("3 | 1 | 4", CoreOperationUnion.class);
178     }
179     
180     public void testExpressionPath() {
181         assertXPathExpression("$x/foo/bar", ExpressionPath.class);
182         assertXPathExpression("(2 + 2)/foo/bar", ExpressionPath.class);
183         assertXPathExpression("$x[3][2 + 2]/foo/bar", ExpressionPath.class);
184     }
185     
186     public void testExtensionFunction() {
187         assertXPathExpression("my:function(3, other.function())", ExtensionFunction.class);
188     }
189  
190     public void testLocationPathAxisSelf() {
191         assertXPathExpression("self::foo:bar", LocationPath.class);
192         assertXPathExpression(".", LocationPath.class);
193     }
194     
195     public void testLocationPathAxisChild() {
196         assertXPathExpression("child::foo:bar", LocationPath.class, "foo:bar");
197         assertXPathExpression("foo:bar", LocationPath.class);
198         assertXPathExpression("/foo:bar", LocationPath.class);
199         assertXPathExpression("/foo/bar", LocationPath.class);
200         assertXPathExpression("*", LocationPath.class);
201         assertXPathExpression("foo:*", LocationPath.class);
202     }
203     
204     public void testLocationPathAxisParent() {
205         assertXPathExpression("parent::foo:bar", LocationPath.class);
206         assertXPathExpression("..", LocationPath.class);
207     }
208     
209     public void testLocationPathAxisAttribute() {
210         assertXPathExpression("attribute::foo:bar", LocationPath.class, "@foo:bar");
211         assertXPathExpression("@foo:bar", LocationPath.class);
212         assertXPathExpression("../@foo:bar", LocationPath.class);
213         assertXPathExpression("@*", LocationPath.class);
214         assertXPathExpression("@*[last()]", LocationPath.class);
215     }
216     
217     public void testLocationPathAxisDescendant() {
218         assertXPathExpression("descendant::foo:bar", LocationPath.class);
219     }
220     
221     public void testLocationPathAxisDescendantOrSelf() {
222         assertXPathExpression("descendant-or-self::foo:bar", LocationPath.class);
223         assertXPathExpression("//foo", LocationPath.class);
224         assertXPathExpression("foo//bar", LocationPath.class);
225     }
226     
227     public void testLocationPathAxisOther() {
228         assertXPathExpression("ancestor::foo:bar", LocationPath.class);
229         assertXPathExpression("ancestor-or-self::foo:bar", LocationPath.class);
230         assertXPathExpression("namespace::foo:bar", LocationPath.class);
231         assertXPathExpression("preceding::foo:bar", LocationPath.class);
232         assertXPathExpression("preceding-sibling::foo:bar", LocationPath.class);
233         assertXPathExpression("following::foo:bar", LocationPath.class);
234         assertXPathExpression("following-sibling::foo:bar", LocationPath.class);
235     }
236     
237     public void testLocationPathNodeTest() {
238         assertXPathExpression("node()", LocationPath.class);
239         assertXPathExpression("text()", LocationPath.class);
240         assertXPathExpression("comment()", LocationPath.class);
241         assertXPathExpression("processing-instruction()", LocationPath.class);
242         assertXPathExpression("processing-instruction('test')", LocationPath.class);
243     }
244     
245     public void testVariableReference() {
246         assertXPathExpression("$x", VariableReference.class);
247         assertXPathExpression("$x:y", VariableReference.class);
248     }
249     
250     /**
251      * Compiles the xpath into an Expression, checks the expression
252      * class, converts the expression to string and checks that the string
253      * matches the expected one.
254      */
255     private void assertXPathExpression(String xpath, Class expectedClass, String expected) {
256         JXPathCompiledExpression expression = (JXPathCompiledExpression) JXPathContext.compile(xpath);
257         
258         assertEquals("Expression class for " + xpath, expectedClass, expression.getExpression().getClass());
259         assertEquals("Expression toString() for " + xpath, expected, expression.getExpression().toString());
260     }
261     
262     private void assertXPathExpression(String xpath, Class expectedClass) {
263         assertXPathExpression(xpath, expectedClass, xpath);
264     }
265     
266 }