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.compiler;
18  
19  import java.text.DecimalFormatSymbols;
20  import java.util.Arrays;
21  import java.util.List;
22  
23  import org.apache.commons.jxpath.ExtendedKeyManager;
24  import org.apache.commons.jxpath.IdentityManager;
25  import org.apache.commons.jxpath.JXPathContext;
26  import org.apache.commons.jxpath.JXPathTestCase;
27  import org.apache.commons.jxpath.KeyManager;
28  import org.apache.commons.jxpath.NodeSet;
29  import org.apache.commons.jxpath.Pointer;
30  import org.apache.commons.jxpath.TestMixedModelBean;
31  import org.apache.commons.jxpath.Variables;
32  import org.apache.commons.jxpath.ri.model.NodePointer;
33  
34  /**
35   * Test basic functionality of JXPath - core functions.
36   *
37   * @author Dmitri Plotnikov
38   * @version $Revision: 779915 $ $Date: 2009-05-29 12:23:40 +0200 (Fr, 29 Mai 2009) $
39   */
40  public class CoreFunctionTest extends JXPathTestCase {
41      private JXPathContext context;
42  
43      public void setUp() {
44          if (context == null) {
45              context = JXPathContext.newContext(new TestMixedModelBean());
46              Variables vars = context.getVariables();
47              vars.declareVariable("nan", new Double(Double.NaN));
48              vars.declareVariable("bool_true", new Boolean("true"));
49              vars.declareVariable("bool_false", new Boolean("false"));
50          }
51      }
52  
53      public void testCoreFunctions() {
54          assertXPathValue(context, "string(2)", "2");
55          assertXPathValue(context, "string($nan)", "NaN");
56          assertXPathValue(context, "string(-$nan)", "NaN");
57          assertXPathValue(context, "string(-2 div 0)", "-Infinity");
58          assertXPathValue(context, "string(2 div 0)", "Infinity");
59          assertXPathValue(context, "concat('a', 'b', 'c')", "abc");
60          assertXPathValue(context, "starts-with('abc', 'ab')", Boolean.TRUE);
61          assertXPathValue(context, "starts-with('xabc', 'ab')", Boolean.FALSE);
62          assertXPathValue(context, "ends-with('abc', 'bc')", Boolean.TRUE);
63          assertXPathValue(context, "ends-with('xabc', 'ab')", Boolean.FALSE);
64          assertXPathValue(context, "contains('xabc', 'ab')", Boolean.TRUE);
65          assertXPathValue(context, "contains('xabc', 'ba')", Boolean.FALSE);
66          assertXPathValue(
67              context,
68              "substring-before('1999/04/01', '/')",
69              "1999");
70          assertXPathValue(
71              context,
72              "substring-after('1999/04/01', '/')",
73              "04/01");
74          assertXPathValue(context, "substring('12345', 2, 3)", "234");
75          assertXPathValue(context, "substring('12345', 2)", "2345");
76          assertXPathValue(context, "substring('12345', 1.5, 2.6)", "234");
77          assertXPathValue(context, "substring('12345', 0, 3)", "12");
78          assertXPathValue(context, "substring('12345', 0 div 0, 3)", "");
79          assertXPathValue(context, "substring('12345', 1, 0 div 0)", "");
80          assertXPathValue(context, "substring('12345', -42, 1 div 0)", "12345");
81          assertXPathValue(context, "substring('12345', -1 div 0, 1 div 0)", "");
82          assertXPathValue(context, "substring('12345', 6, 6)", "");
83          assertXPathValue(context, "substring('12345', 7, 8)", "");
84          assertXPathValue(context, "substring('12345', 7)", "");
85          assertXPathValue(context, "string-length('12345')", new Double(5));
86          assertXPathValue(context, "normalize-space(' abc  def  ')", "abc def");
87          assertXPathValue(context, "normalize-space('abc def')", "abc def");
88          assertXPathValue(context, "normalize-space('   ')", "");
89          assertXPathValue(context, "translate('--aaa--', 'abc-', 'ABC')", "AAA");
90          assertXPathValue(context, "boolean(1)", Boolean.TRUE);
91          assertXPathValue(context, "boolean(0)", Boolean.FALSE);
92          assertXPathValue(context, "boolean('x')", Boolean.TRUE);
93          assertXPathValue(context, "boolean('')", Boolean.FALSE);
94          assertXPathValue(context, "boolean(/list)", Boolean.TRUE);
95          assertXPathValue(context, "boolean(/list[position() < 1])", Boolean.FALSE);
96  
97          assertXPathValue(context, "true()", Boolean.TRUE);
98          assertXPathValue(context, "false()", Boolean.FALSE);
99          assertXPathValue(context, "not(false())", Boolean.TRUE);
100         assertXPathValue(context, "not(true())", Boolean.FALSE);
101         assertXPathValue(context, "null()", null);        
102         assertXPathValue(context, "number('1')", new Double(1));
103         assertXPathValue(context, "number($bool_true)", new Double(1));
104         assertXPathValue(context, "number($bool_false)", new Double(0));
105         assertXPathValue(context, "floor(1.5)", new Double(1));
106         assertXPathValue(context, "floor(-1.5)", new Double(-2));
107         assertXPathValue(context, "ceiling(1.5)", new Double(2));
108         assertXPathValue(context, "ceiling(-1.5)", new Double(-1));
109         assertXPathValue(context, "round(1.5)", new Double(2));
110         assertXPathValue(context, "round(-1.5)", new Double(-1));
111 
112         assertXPathValue(context, "floor('NaN')", new Double(Double.NaN));
113         assertXPathValue(context, "floor(-2 div 0)", new Double(Double.NEGATIVE_INFINITY));
114         assertXPathValue(context, "floor(2 div 0)", new Double(Double.POSITIVE_INFINITY));
115         assertXPathValue(context, "ceiling('NaN')", new Double(Double.NaN));
116         assertXPathValue(context, "ceiling(-2 div 0)", new Double(Double.NEGATIVE_INFINITY));
117         assertXPathValue(context, "ceiling(2 div 0)", new Double(Double.POSITIVE_INFINITY));
118         assertXPathValue(context, "round('NaN')", new Double(Double.NaN));
119         assertXPathValue(context, "round(-2 div 0)", new Double(Double.NEGATIVE_INFINITY));
120         assertXPathValue(context, "round(2 div 0)", new Double(Double.POSITIVE_INFINITY));
121     }
122 
123     public void testIDFunction() {
124         context.setIdentityManager(new IdentityManager() {
125             public Pointer getPointerByID(JXPathContext context, String id) {
126                 NodePointer ptr = (NodePointer) context.getPointer("/document");
127                 ptr = ptr.getValuePointer();
128                 return ptr.getPointerByID(context, id);
129             }
130         });
131 
132         assertXPathValueAndPointer(
133             context,
134             "id(101)//street",
135             "Tangerine Drive",
136             "id('101')/address[1]/street[1]");
137 
138         assertXPathPointerLenient(
139             context,
140             "id(105)/address/street",
141             "id(105)/address/street");
142     }
143 
144     public void testKeyFunction() {
145         context.setKeyManager(new KeyManager() {
146             public Pointer getPointerByKey(
147                 JXPathContext context,
148                 String key,
149                 String value) 
150             {
151                 return NodePointer.newNodePointer(null, "42", null);
152             }
153         });
154 
155         assertXPathValue(context, "key('a', 'b')", "42");
156     }
157 
158     public void testExtendedKeyFunction() {
159         context.setKeyManager(new ExtendedKeyManager() {
160             public Pointer getPointerByKey(JXPathContext context, String key,
161                     String value) {
162                 return NodePointer.newNodePointer(null, "incorrect", null);
163             }
164 
165             public NodeSet getNodeSetByKey(JXPathContext context,
166                     String keyName, Object keyValue) {
167                 return new NodeSet() {
168 
169                     public List getNodes() {
170                         return Arrays.asList(new Object[] { "53", "64" });
171                     }
172 
173                     public List getPointers() {
174                         return Arrays.asList(new NodePointer[] {
175                                 NodePointer.newNodePointer(null, "53", null),
176                                 NodePointer.newNodePointer(null, "64", null) });
177                     }
178 
179                     public List getValues() {
180                         return Arrays.asList(new Object[] { "53", "64" });
181                     }
182 
183                 };
184             }
185         });
186         assertXPathValue(context, "key('a', 'b')", "53");
187         assertXPathValue(context, "key('a', 'b')[1]", "53");
188         assertXPathValue(context, "key('a', 'b')[2]", "64");
189         assertXPathValueIterator(context, "key('a', 'b')", list("53", "64"));
190         assertXPathValueIterator(context, "'x' | 'y'", list("x", "y"));
191         assertXPathValueIterator(context, "key('a', 'x' | 'y')", list("53", "64", "53", "64"));
192         assertXPathValueIterator(context, "key('a', /list[position() < 4])", list("53", "64", "53", "64", "53", "64"));
193         context.getVariables().declareVariable("ints", new int[] { 0, 0 });
194         assertXPathValueIterator(context, "key('a', $ints)", list("53", "64", "53", "64"));
195     }
196 
197     public void testFormatNumberFunction() {
198         
199         DecimalFormatSymbols symbols = new DecimalFormatSymbols();
200         symbols.setDigit('D');
201         
202         context.setDecimalFormatSymbols("test", symbols);
203         
204         assertXPathValue(
205             context,
206             "format-number(123456789, '#.000000000')",
207             "123456789.000000000");
208 
209         assertXPathValue(
210             context,
211             "format-number(123456789, '#.0')",
212             "123456789.0");
213 
214         assertXPathValue(
215             context, 
216             "format-number(0.123456789, '##%')", 
217             "12%");
218 
219         assertXPathValue(
220             context,
221             "format-number(123456789, '################')",
222             "123456789");
223 
224         assertXPathValue(
225             context,
226             "format-number(123456789, 'D.0', 'test')",
227             "123456789.0");
228 
229         assertXPathValue(
230             context,
231             "format-number(123456789, '$DDD,DDD,DDD.DD', 'test')",
232             "$123,456,789");
233     }
234 }