1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jxpath.ri.compiler;
19
20 import java.text.DecimalFormatSymbols;
21 import java.util.Arrays;
22 import java.util.List;
23
24 import org.apache.commons.jxpath.AbstractJXPathTest;
25 import org.apache.commons.jxpath.ExtendedKeyManager;
26 import org.apache.commons.jxpath.JXPathContext;
27 import org.apache.commons.jxpath.NodeSet;
28 import org.apache.commons.jxpath.Pointer;
29 import org.apache.commons.jxpath.TestMixedModelBean;
30 import org.apache.commons.jxpath.Variables;
31 import org.apache.commons.jxpath.ri.model.NodePointer;
32 import org.junit.jupiter.api.BeforeEach;
33 import org.junit.jupiter.api.Test;
34
35
36
37
38 public class CoreFunctionTest extends AbstractJXPathTest {
39
40 private JXPathContext context;
41
42 @Override
43 @BeforeEach
44 public void setUp() {
45 if (context == null) {
46 context = JXPathContext.newContext(new TestMixedModelBean());
47 final Variables vars = context.getVariables();
48 vars.declareVariable("nan", Double.NaN);
49 vars.declareVariable("bool_true", Boolean.TRUE);
50 vars.declareVariable("bool_false", Boolean.FALSE);
51 }
52 }
53
54 @Test
55 public void testCoreFunctions() {
56 assertXPathValue(context, "string(2)", "2");
57 assertXPathValue(context, "string($nan)", "NaN");
58 assertXPathValue(context, "string(-$nan)", "NaN");
59 assertXPathValue(context, "string(-2 div 0)", "-Infinity");
60 assertXPathValue(context, "string(2 div 0)", "Infinity");
61 assertXPathValue(context, "concat('a', 'b', 'c')", "abc");
62 assertXPathValue(context, "starts-with('abc', 'ab')", Boolean.TRUE);
63 assertXPathValue(context, "starts-with('xabc', 'ab')", Boolean.FALSE);
64 assertXPathValue(context, "ends-with('abc', 'bc')", Boolean.TRUE);
65 assertXPathValue(context, "ends-with('xabc', 'ab')", Boolean.FALSE);
66 assertXPathValue(context, "contains('xabc', 'ab')", Boolean.TRUE);
67 assertXPathValue(context, "contains('xabc', 'ba')", Boolean.FALSE);
68 assertXPathValue(context, "substring-before('1999/04/01', '/')", "1999");
69 assertXPathValue(context, "substring-after('1999/04/01', '/')", "04/01");
70 assertXPathValue(context, "substring('12345', 2, 3)", "234");
71 assertXPathValue(context, "substring('12345', 2)", "2345");
72 assertXPathValue(context, "substring('12345', 1.5, 2.6)", "234");
73 assertXPathValue(context, "substring('12345', 0, 3)", "12");
74 assertXPathValue(context, "substring('12345', 0 div 0, 3)", "");
75 assertXPathValue(context, "substring('12345', 1, 0 div 0)", "");
76 assertXPathValue(context, "substring('12345', -42, 1 div 0)", "12345");
77 assertXPathValue(context, "substring('12345', -1 div 0, 1 div 0)", "");
78 assertXPathValue(context, "substring('12345', 6, 6)", "");
79 assertXPathValue(context, "substring('12345', 7, 8)", "");
80 assertXPathValue(context, "substring('12345', 7)", "");
81 assertXPathValue(context, "string-length('12345')", Double.valueOf(5));
82 assertXPathValue(context, "normalize-space(' abc def ')", "abc def");
83 assertXPathValue(context, "normalize-space('abc def')", "abc def");
84 assertXPathValue(context, "normalize-space(' ')", "");
85 assertXPathValue(context, "translate('--aaa--', 'abc-', 'ABC')", "AAA");
86 assertXPathValue(context, "boolean(1)", Boolean.TRUE);
87 assertXPathValue(context, "boolean(0)", Boolean.FALSE);
88 assertXPathValue(context, "boolean('x')", Boolean.TRUE);
89 assertXPathValue(context, "boolean('')", Boolean.FALSE);
90 assertXPathValue(context, "boolean(/list)", Boolean.TRUE);
91 assertXPathValue(context, "boolean(/list[position() < 1])", Boolean.FALSE);
92 assertXPathValue(context, "true()", Boolean.TRUE);
93 assertXPathValue(context, "false()", Boolean.FALSE);
94 assertXPathValue(context, "not(false())", Boolean.TRUE);
95 assertXPathValue(context, "not(true())", Boolean.FALSE);
96 assertXPathValue(context, "null()", null);
97 assertXPathValue(context, "number('1')", Double.valueOf(1));
98 assertXPathValue(context, "number($bool_true)", Double.valueOf(1));
99 assertXPathValue(context, "number($bool_false)", Double.valueOf(0));
100 assertXPathValue(context, "floor(1.5)", Double.valueOf(1));
101 assertXPathValue(context, "floor(-1.5)", Double.valueOf(-2));
102 assertXPathValue(context, "ceiling(1.5)", Double.valueOf(2));
103 assertXPathValue(context, "ceiling(-1.5)", Double.valueOf(-1));
104 assertXPathValue(context, "round(1.5)", Double.valueOf(2));
105 assertXPathValue(context, "round(-1.5)", Double.valueOf(-1));
106 assertXPathValue(context, "floor('NaN')", Double.valueOf(Double.NaN));
107 assertXPathValue(context, "floor(-2 div 0)", Double.valueOf(Double.NEGATIVE_INFINITY));
108 assertXPathValue(context, "floor(2 div 0)", Double.valueOf(Double.POSITIVE_INFINITY));
109 assertXPathValue(context, "ceiling('NaN')", Double.valueOf(Double.NaN));
110 assertXPathValue(context, "ceiling(-2 div 0)", Double.valueOf(Double.NEGATIVE_INFINITY));
111 assertXPathValue(context, "ceiling(2 div 0)", Double.valueOf(Double.POSITIVE_INFINITY));
112 assertXPathValue(context, "round('NaN')", Double.valueOf(Double.NaN));
113 assertXPathValue(context, "round(-2 div 0)", Double.valueOf(Double.NEGATIVE_INFINITY));
114 assertXPathValue(context, "round(2 div 0)", Double.valueOf(Double.POSITIVE_INFINITY));
115 }
116
117 @Test
118 public void testExtendedKeyFunction() {
119 context.setKeyManager(new ExtendedKeyManager() {
120
121 @Override
122 public NodeSet getNodeSetByKey(final JXPathContext context, final String keyName, final Object keyValue) {
123 return new NodeSet() {
124
125 @Override
126 public List getNodes() {
127 return Arrays.asList("53", "64");
128 }
129
130 @Override
131 public List getPointers() {
132 return Arrays.asList(NodePointer.newNodePointer(null, "53", null), NodePointer.newNodePointer(null, "64", null));
133 }
134
135 @Override
136 public List getValues() {
137 return Arrays.asList("53", "64");
138 }
139 };
140 }
141
142 @Override
143 public Pointer getPointerByKey(final JXPathContext context, final String key, final String value) {
144 return NodePointer.newNodePointer(null, "incorrect", null);
145 }
146 });
147 assertXPathValue(context, "key('a', 'b')", "53");
148 assertXPathValue(context, "key('a', 'b')[1]", "53");
149 assertXPathValue(context, "key('a', 'b')[2]", "64");
150 assertXPathValueIterator(context, "key('a', 'b')", list("53", "64"));
151 assertXPathValueIterator(context, "'x' | 'y'", list("x", "y"));
152 assertXPathValueIterator(context, "key('a', 'x' | 'y')", list("53", "64", "53", "64"));
153 assertXPathValueIterator(context, "key('a', /list[position() < 4])", list("53", "64", "53", "64", "53", "64"));
154 context.getVariables().declareVariable("ints", new int[] { 0, 0 });
155 assertXPathValueIterator(context, "key('a', $ints)", list("53", "64", "53", "64"));
156 }
157
158 @Test
159 public void testFormatNumberFunction() {
160 final DecimalFormatSymbols symbols = new DecimalFormatSymbols();
161 symbols.setDigit('D');
162 context.setDecimalFormatSymbols("test", symbols);
163 assertXPathValue(context, "format-number(123456789, '#.000000000')", "123456789.000000000");
164 assertXPathValue(context, "format-number(123456789, '#.0')", "123456789.0");
165 assertXPathValue(context, "format-number(0.123456789, '##%')", "12%");
166 assertXPathValue(context, "format-number(123456789, '################')", "123456789");
167 assertXPathValue(context, "format-number(123456789, 'D.0', 'test')", "123456789.0");
168 assertXPathValue(context, "format-number(123456789, '$DDD,DDD,DDD.DD', 'test')", "$123,456,789");
169 }
170
171 @Test
172 public void testIDFunction() {
173 context.setIdentityManager((context, id) -> {
174 NodePointer ptr = (NodePointer) context.getPointer("/document");
175 ptr = ptr.getValuePointer();
176 return ptr.getPointerByID(context, id);
177 });
178 assertXPathValueAndPointer(context, "id(101)//street", "Tangerine Drive", "id('101')/address[1]/street[1]");
179 assertXPathPointerLenient(context, "id(105)/address/street", "id(105)/address/street");
180 }
181
182 @Test
183 public void testKeyFunction() {
184 context.setKeyManager((context, key, value) -> NodePointer.newNodePointer(null, "42", null));
185 assertXPathValue(context, "key('a', 'b')", "42");
186 }
187 }