1 package com.fasterxml.jackson.databind.node;
2 
3 import java.io.*;
4 import java.math.BigDecimal;
5 import java.math.BigInteger;
6 import java.util.ArrayList;
7 
8 import com.fasterxml.jackson.core.*;
9 import com.fasterxml.jackson.databind.*;
10 import com.fasterxml.jackson.databind.exc.MismatchedInputException;
11 import com.fasterxml.jackson.databind.node.ArrayNode;
12 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
13 import com.fasterxml.jackson.databind.node.TextNode;
14 import com.fasterxml.jackson.databind.node.TreeTraversingParser;
15 import static java.util.Arrays.asList;
16 
17 /**
18  * Additional tests for {@link ArrayNode} container class.
19  */
20 public class ArrayNodeTest
21     extends BaseMapTest
22 {
testDirectCreation()23     public void testDirectCreation() throws IOException
24     {
25         ArrayNode n = new ArrayNode(JsonNodeFactory.instance);
26         assertStandardEquals(n);
27         assertFalse(n.elements().hasNext());
28         assertFalse(n.fieldNames().hasNext());
29         assertTrue(n.isEmpty());
30         TextNode text = TextNode.valueOf("x");
31         n.add(text);
32         assertEquals(1, n.size());
33         assertFalse(n.isEmpty());
34         assertFalse(0 == n.hashCode());
35         assertTrue(n.elements().hasNext());
36         // no field names for arrays
37         assertFalse(n.fieldNames().hasNext());
38         assertNull(n.get("x")); // not used with arrays
39         assertTrue(n.path("x").isMissingNode());
40         assertSame(text, n.get(0));
41 
42         // single element, so:
43         assertFalse(n.has("field"));
44         assertFalse(n.hasNonNull("field"));
45         assertTrue(n.has(0));
46         assertTrue(n.hasNonNull(0));
47         assertFalse(n.has(1));
48         assertFalse(n.hasNonNull(1));
49 
50         // add null node too
51         n.add((JsonNode) null);
52         assertEquals(2, n.size());
53         assertTrue(n.get(1).isNull());
54         assertTrue(n.has(1));
55         assertFalse(n.hasNonNull(1));
56         // change to text
57         n.set(1, text);
58         assertSame(text, n.get(1));
59         n.set(0, null);
60         assertTrue(n.get(0).isNull());
61 
62         // and finally, clear it all
63         ArrayNode n2 = new ArrayNode(JsonNodeFactory.instance);
64         n2.add("foobar");
65         assertFalse(n.equals(n2));
66         n.addAll(n2);
67         assertEquals(3, n.size());
68 
69         assertFalse(n.get(0).isTextual());
70         assertNotNull(n.remove(0));
71         assertEquals(2, n.size());
72         assertTrue(n.get(0).isTextual());
73         assertNull(n.remove(-1));
74         assertNull(n.remove(100));
75         assertEquals(2, n.size());
76 
77         ArrayList<JsonNode> nodes = new ArrayList<JsonNode>();
78         nodes.add(text);
79         n.addAll(nodes);
80         assertEquals(3, n.size());
81         assertNull(n.get(10000));
82         assertNull(n.remove(-4));
83 
84         TextNode text2 = TextNode.valueOf("b");
85         n.insert(0, text2);
86         assertEquals(4, n.size());
87         assertSame(text2, n.get(0));
88 
89         assertNotNull(n.addArray());
90         assertEquals(5, n.size());
91         n.addPOJO("foo");
92         assertEquals(6, n.size());
93 
94         n.removeAll();
95         assertEquals(0, n.size());
96     }
97 
testDirectCreation2()98     public void testDirectCreation2() throws IOException
99     {
100         JsonNodeFactory f = objectMapper().getNodeFactory();
101         ArrayList<JsonNode> list = new ArrayList<>();
102         list.add(f.booleanNode(true));
103         list.add(f.textNode("foo"));
104         ArrayNode n = new ArrayNode(f, list);
105         assertEquals(2, n.size());
106         assertTrue(n.get(0).isBoolean());
107         assertTrue(n.get(1).isTextual());
108 
109         // also, should fail with invalid set attempt
110         try {
111             n.set(2, f.nullNode());
112             fail("Should not pass");
113         } catch (IndexOutOfBoundsException e) {
114             verifyException(e, "illegal index");
115         }
116         n.insert(1, (String) null);
117         assertEquals(3, n.size());
118         assertTrue(n.get(0).isBoolean());
119         assertTrue(n.get(1).isNull());
120         assertTrue(n.get(2).isTextual());
121 
122         n.removeAll();
123         n.insert(0, (JsonNode) null);
124         assertEquals(1, n.size());
125         assertTrue(n.get(0).isNull());
126     }
127 
testArrayViaMapper()128     public void testArrayViaMapper() throws Exception
129     {
130         final String JSON = "[[[-0.027512,51.503221],[-0.008497,51.503221],[-0.008497,51.509744],[-0.027512,51.509744]]]";
131 
132         JsonNode n = objectMapper().readTree(JSON);
133         assertNotNull(n);
134         assertTrue(n.isArray());
135         ArrayNode an = (ArrayNode) n;
136         assertEquals(1, an.size());
137         ArrayNode an2 = (ArrayNode) n.get(0);
138         assertTrue(an2.isArray());
139         assertEquals(4, an2.size());
140     }
141 
testAdds()142     public void testAdds()
143     {
144         ArrayNode n = new ArrayNode(JsonNodeFactory.instance);
145         assertNotNull(n.addArray());
146         assertNotNull(n.addObject());
147         n.addPOJO("foobar");
148         n.add(1);
149         n.add(1L);
150         n.add(0.5);
151         n.add(0.5f);
152         n.add(new BigDecimal("0.2"));
153         n.add(BigInteger.TEN);
154         assertEquals(9, n.size());
155         assertFalse(n.isEmpty());
156 
157         assertNotNull(n.insertArray(0));
158         assertNotNull(n.insertObject(0));
159         n.insertPOJO(2, "xxx");
160         assertEquals(12, n.size());
161 
162         n.insert(0, BigInteger.ONE);
163         n.insert(0, new BigDecimal("0.1"));
164         assertEquals(14, n.size());
165     }
166 
testNullAdds()167     public void testNullAdds()
168     {
169         JsonNodeFactory f = objectMapper().getNodeFactory();
170         ArrayNode array = f.arrayNode(14);
171 
172         array.add((BigDecimal) null);
173         array.add((BigInteger) null);
174         array.add((Boolean) null);
175         array.add((byte[]) null);
176         array.add((Double) null);
177         array.add((Float) null);
178         array.add((Integer) null);
179         array.add((JsonNode) null);
180         array.add((Long) null);
181         array.add((String) null);
182 
183         assertEquals(10, array.size());
184 
185         for (JsonNode node : array) {
186             assertTrue(node.isNull());
187         }
188     }
189 
testAddAllWithNullInCollection()190     public void testAddAllWithNullInCollection()
191     {
192         // preparation
193         final ArrayNode array = JsonNodeFactory.instance.arrayNode();
194 
195         // test
196         array.addAll(asList(null, JsonNodeFactory.instance.objectNode()));
197 
198         // assertions
199         assertEquals(2, array.size());
200 
201         for (JsonNode node : array) {
202             assertNotNull(node);
203         }
204         assertEquals(NullNode.getInstance(), array.get(0));
205     }
206 
testNullInserts()207     public void testNullInserts()
208     {
209         JsonNodeFactory f = objectMapper().getNodeFactory();
210         ArrayNode array = f.arrayNode(3);
211 
212         array.insert(0, (BigDecimal) null);
213         array.insert(0, (BigInteger) null);
214         array.insert(0, (Boolean) null);
215         // Offsets out of the range are fine; negative become 0;
216         // super big just add at the end
217         array.insert(-56, (byte[]) null);
218         array.insert(0, (Double) null);
219         array.insert(200, (Float) null);
220         array.insert(0, (Integer) null);
221         array.insert(1, (JsonNode) null);
222         array.insert(array.size(), (Long) null);
223         array.insert(1, (String) null);
224 
225         assertEquals(10, array.size());
226 
227         for (JsonNode node : array) {
228             assertTrue(node.isNull());
229         }
230     }
231 
testNullChecking()232     public void testNullChecking()
233     {
234         ArrayNode a1 = JsonNodeFactory.instance.arrayNode();
235         ArrayNode a2 = JsonNodeFactory.instance.arrayNode();
236         // used to throw NPE before fix:
237         a1.addAll(a2);
238         assertEquals(0, a1.size());
239         assertEquals(0, a2.size());
240 
241         a2.addAll(a1);
242         assertEquals(0, a1.size());
243         assertEquals(0, a2.size());
244     }
245 
testNullChecking2()246     public void testNullChecking2()
247     {
248         ObjectMapper mapper = new ObjectMapper();
249         ArrayNode src = mapper.createArrayNode();
250         ArrayNode dest = mapper.createArrayNode();
251         src.add("element");
252         dest.addAll(src);
253     }
254 
testParser()255     public void testParser() throws Exception
256     {
257         ArrayNode n = new ArrayNode(JsonNodeFactory.instance);
258         n.add(123);
259         TreeTraversingParser p = new TreeTraversingParser(n, null);
260         p.setCodec(null);
261         assertNull(p.getCodec());
262         assertNotNull(p.getParsingContext());
263         assertTrue(p.getParsingContext().inRoot());
264         assertNotNull(p.getTokenLocation());
265         assertNotNull(p.getCurrentLocation());
266         assertNull(p.getEmbeddedObject());
267         assertNull(p.currentNode());
268 
269         //assertNull(p.getNumberType());
270 
271         assertToken(JsonToken.START_ARRAY, p.nextToken());
272         assertNotNull(p.getParsingContext());
273         assertTrue(p.getParsingContext().inArray());
274         p.skipChildren();
275         assertToken(JsonToken.END_ARRAY, p.currentToken());
276         p.close();
277 
278         p = new TreeTraversingParser(n, null);
279         p.nextToken();
280         assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
281         assertEquals(JsonParser.NumberType.INT, p.getNumberType());
282         p.close();
283     }
284 
testArrayNodeEquality()285     public void testArrayNodeEquality()
286     {
287         ArrayNode n1 = new ArrayNode(null);
288         ArrayNode n2 = new ArrayNode(null);
289 
290         assertTrue(n1.equals(n2));
291         assertTrue(n2.equals(n1));
292 
293         n1.add(TextNode.valueOf("Test"));
294 
295         assertFalse(n1.equals(n2));
296         assertFalse(n2.equals(n1));
297 
298         n2.add(TextNode.valueOf("Test"));
299 
300         assertTrue(n1.equals(n2));
301         assertTrue(n2.equals(n1));
302     }
303 
testSimpleArray()304     public void testSimpleArray() throws Exception
305     {
306         ArrayNode result = objectMapper().createArrayNode();
307 
308         assertTrue(result.isArray());
309         assertType(result, ArrayNode.class);
310 
311         assertFalse(result.isObject());
312         assertFalse(result.isNumber());
313         assertFalse(result.isNull());
314         assertFalse(result.isTextual());
315 
316         // and let's add stuff...
317         result.add(false);
318         result.insertNull(0);
319 
320         // should be equal to itself no matter what
321         assertEquals(result, result);
322         assertFalse(result.equals(null)); // but not to null
323 
324         // plus see that we can access stuff
325         assertEquals(NullNode.instance, result.path(0));
326         assertEquals(NullNode.instance, result.get(0));
327         assertEquals(BooleanNode.FALSE, result.path(1));
328         assertEquals(BooleanNode.FALSE, result.get(1));
329         assertEquals(2, result.size());
330 
331         assertNull(result.get(-1));
332         assertNull(result.get(2));
333         JsonNode missing = result.path(2);
334         assertTrue(missing.isMissingNode());
335         assertTrue(result.path(-100).isMissingNode());
336 
337         // then construct and compare
338         ArrayNode array2 = objectMapper().createArrayNode();
339         array2.addNull();
340         array2.add(false);
341         assertEquals(result, array2);
342 
343         // plus remove entries
344         JsonNode rm1 = array2.remove(0);
345         assertEquals(NullNode.instance, rm1);
346         assertEquals(1, array2.size());
347         assertEquals(BooleanNode.FALSE, array2.get(0));
348         assertFalse(result.equals(array2));
349 
350         JsonNode rm2 = array2.remove(0);
351         assertEquals(BooleanNode.FALSE, rm2);
352         assertEquals(0, array2.size());
353     }
354 
testSimpleMismatch()355     public void testSimpleMismatch() throws Exception
356     {
357         ObjectMapper mapper = objectMapper();
358         try {
359             mapper.readValue(" 123 ", ArrayNode.class);
360             fail("Should not pass");
361         } catch (MismatchedInputException e) {
362             verifyException(e, "from Integer value (token `JsonToken.VALUE_NUMBER_INT`)");
363         }
364     }
365 }
366