Bug 7433 - Remove use of YangSchemaSourceImpl from restconf tests
[netconf.git] / restconf / sal-rest-connector / src / test / java / org / opendaylight / restconf / parser / builder / YangInstanceIdentifierDeserializerTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.restconf.parser.builder;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertTrue;
13 import static org.junit.Assert.fail;
14
15 import com.google.common.collect.Iterables;
16 import com.google.common.collect.Sets;
17 import java.util.Iterator;
18 import java.util.LinkedHashMap;
19 import java.util.Map;
20 import org.junit.Before;
21 import org.junit.Rule;
22 import org.junit.Test;
23 import org.junit.rules.ExpectedException;
24 import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
25 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
26 import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
27 import org.opendaylight.yangtools.yang.common.QName;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
30 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
31 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
32
33 /**
34  * Unit tests for {@link YangInstanceIdentifierDeserializer}
35  */
36 public class YangInstanceIdentifierDeserializerTest {
37
38     @Rule
39     public ExpectedException thrown = ExpectedException.none();
40
41     // schema context
42     private SchemaContext schemaContext;
43
44     @Before
45     public void init() throws Exception {
46         this.schemaContext =
47                 YangParserTestUtils.parseYangSources(TestRestconfUtils.loadFiles("/restconf/parser/deserializer"));
48     }
49
50     /**
51      * Test of deserialization <code>String</code> URI with container to
52      * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
53      */
54     @Test
55     public void deserializeContainerTest() {
56         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
57                 .create(this.schemaContext, "deserializer-test:contA");
58
59         assertEquals("Result does not contains expected number of path arguments", 1, Iterables.size(result));
60         assertEquals("Not expected path argument",
61                 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")),
62                 result.iterator().next());
63     }
64
65     /**
66      * Test of deserialization <code>String</code> URI with container containing leaf to
67      * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
68      */
69     @Test
70     public void deserializeContainerWithLeafTest() {
71         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
72                 .create(this.schemaContext, "deserializer-test:contA/leaf-A");
73
74         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
75
76         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
77         assertEquals("Not expected path argument",
78                 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")),
79                 iterator.next());
80         assertEquals("Not expected path argument",
81                 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "leaf-A")),
82                 iterator.next());
83     }
84
85     /**
86      * Test of deserialization <code>String</code> URI with container containing list with leaf list to
87      * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
88      */
89     @Test
90     public void deserializeContainerWithListWithLeafListTest() {
91         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
92                 .create(this.schemaContext, "deserializer-test:contA/list-A=100/leaf-list-AA=instance");
93
94         assertEquals("Result does not contains expected number of path arguments", 5, Iterables.size(result));
95
96         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
97
98         // container
99         assertEquals("Not expected path argument",
100                 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")),
101                 iterator.next());
102
103         // list
104         final QName list = QName.create("deserializer:test", "2016-06-06", "list-A");
105         assertEquals("Not expected path argument",
106                 YangInstanceIdentifier.NodeIdentifier.create(list),
107                 iterator.next());
108         assertEquals("Not expected path argument",
109                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(
110                         list, QName.create(list, "list-key"), 100).toString(),
111                 iterator.next().toString());
112
113         // leaf list
114         final QName leafList = QName.create("deserializer:test", "2016-06-06", "leaf-list-AA");
115         assertEquals("Not expected path argument",
116                 YangInstanceIdentifier.NodeIdentifier.create(leafList),
117                 iterator.next());
118         assertEquals("Not expected path argument",
119                 new YangInstanceIdentifier.NodeWithValue(leafList, "instance"),
120                 iterator.next());
121     }
122
123     /**
124      * Test of deserialization <code>String</code> URI containing list with no keys to
125      * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
126      */
127     @Test
128     public void deserializeListWithNoKeysTest() {
129         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
130                 .create(this.schemaContext, "deserializer-test:list-no-key");
131
132         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
133
134         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
135         final QName list = QName.create("deserializer:test", "2016-06-06", "list-no-key");
136
137         assertEquals("Not expected path argument",
138                 YangInstanceIdentifier.NodeIdentifier.create(list),
139                 iterator.next());
140         assertEquals("Not expected path argument",
141                 YangInstanceIdentifier.NodeIdentifier.create(list),
142                 iterator.next());
143     }
144
145     /**
146      * Test of deserialization <code>String</code> URI containing list with one key to
147      * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
148      */
149     @Test
150     public void deserializeListWithOneKeyTest() {
151         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
152                 .create(this.schemaContext, "deserializer-test:list-one-key=value");
153
154         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
155
156         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
157         final QName list = QName.create("deserializer:test", "2016-06-06", "list-one-key");
158
159         assertEquals("Not expected path argument",
160                 YangInstanceIdentifier.NodeIdentifier.create(list),
161                 iterator.next());
162         assertEquals("Not expected path argument",
163                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, QName.create(list, "name"), "value"),
164                 iterator.next());
165     }
166
167     /**
168      * Test of deserialization <code>String</code> URI containing list with multiple keys to
169      * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
170      */
171     @Test
172     public void deserializeListWithMultipleKeysTest() {
173         final QName list = QName.create("deserializer:test", "2016-06-06", "list-multiple-keys");
174         final Map<QName, Object> values = new LinkedHashMap<>();
175         values.put(QName.create(list, "name"), "value");
176         values.put(QName.create(list, "number"), 100);
177         values.put(QName.create(list, "enabled"), false);
178
179         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
180                 .create(this.schemaContext, "deserializer-test:list-multiple-keys=value,100,false");
181
182         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
183
184         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
185
186         assertEquals("Not expected path argument",
187                 YangInstanceIdentifier.NodeIdentifier.create(list),
188                 iterator.next());
189         assertEquals("Not expected path argument",
190                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, values).toString(),
191                 iterator.next().toString());
192     }
193
194     /**
195      * Test of deserialization <code>String</code> URI containing leaf list to
196      * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
197      */
198     @Test
199     public void deserializeLeafListTest() {
200         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
201                 .create(this.schemaContext, "deserializer-test:leaf-list-0=true");
202
203         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
204
205         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
206         final QName leafList = QName.create("deserializer:test", "2016-06-06", "leaf-list-0");
207
208         assertEquals("Not expected path argument",
209                 new YangInstanceIdentifier.NodeIdentifier(leafList),
210                 iterator.next());
211         assertEquals("Not expected path argument",
212                 new YangInstanceIdentifier.NodeWithValue(leafList, true).toString(),
213                 iterator.next().toString());
214     }
215
216     /**
217      * Test when empty <code>String</code> is supplied as an input. Test is expected to return empty result.
218      */
219     @Test
220     public void deserializeEmptyDataTest() {
221         final Iterable<PathArgument> result = YangInstanceIdentifierDeserializer.create(this.schemaContext, "");
222         assertTrue("Empty result expected", Iterables.isEmpty(result));
223     }
224
225     /**
226      * Negative test when supplied <code>SchemaContext</code> is null. Test is expected to fail with
227      * <code>NullPointerException</code>.
228      */
229     @Test
230     public void deserializeNullSchemaContextNegativeTest() {
231         this.thrown.expect(NullPointerException.class);
232         YangInstanceIdentifierDeserializer.create(null, "deserializer-test:contA");
233     }
234
235     /**
236      * Negative test when supplied <code>String</code> data to deserialize is null. Test is expected to fail with
237      * <code>NullPointerException</code>.
238      */
239     @Test
240     public void nullDataNegativeNegativeTest() {
241         this.thrown.expect(NullPointerException.class);
242         YangInstanceIdentifierDeserializer.create(this.schemaContext, null);
243     }
244
245     /**
246      * Negative test when identifier is not followed by slash or equals. Test is expected to fail with
247      * <code>IllegalArgumentException</code>.
248      */
249     @Test
250     public void deserializeBadCharMissingSlashOrEqualNegativeTest() {
251         this.thrown.expect(IllegalArgumentException.class);
252         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:cont*leaf-A");
253     }
254
255     /**
256      * Negative test of validating identifier when there is a slash after container without next identifier. Test
257      * is expected to fail with <code>IllegalArgumentException</code>.
258      */
259     @Test
260     public void validArgIdentifierContainerEndsWithSlashNegativeTest() {
261         this.thrown.expect(IllegalArgumentException.class);
262         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:contA/");
263     }
264
265     /**
266      * Negative test of validating identifier when there is a slash after list key values without next identifier. Test
267      * is expected to fail with <code>IllegalArgumentException</code>.
268      */
269     @Test
270     public void validArgIdentifierListEndsWithSlashLNegativeTest() {
271         this.thrown.expect(IllegalArgumentException.class);
272         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:list-one-key=value/");
273     }
274
275     /**
276      * Negative test of creating <code>QName</code> when identifier is empty (example: '/'). Test is expected to fail
277      * with <code>IllegalArgumentException</code>.
278      */
279     @Test
280     public void prepareQnameEmptyIdentifierNegativeTest() {
281         this.thrown.expect(IllegalArgumentException.class);
282         YangInstanceIdentifierDeserializer.create(this.schemaContext, "/");
283     }
284
285     /**
286      * Negative test of creating <code>QName</code> when two identifiers are separated by two slashes. Test is
287      * expected to fail with <code>IllegalArgumentException</code>.
288      */
289     @Test
290     public void prepareQnameTwoSlashesNegativeTest() {
291         this.thrown.expect(IllegalArgumentException.class);
292         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:contA//leaf-A");
293     }
294
295     /**
296      * Negative test of creating <code>QName</code> when in identifier there is another sign than colon or equals.
297      * Test is expected to fail with <code>IllegalArgumentException</code>.
298      */
299     @Test
300     public void prepareQnameBuildPathNegativeTest() {
301         this.thrown.expect(IllegalArgumentException.class);
302         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test*contA");
303     }
304
305     /**
306      * Negative test of creating <code>QName</code> when it is not possible to find module for specified prefix. Test is
307      * expected to fail with <code>IllegalArgumentException</code>.
308      */
309     @Test
310     public void prepareQnameNotExistingPrefixNegativeTest() {
311         this.thrown.expect(IllegalArgumentException.class);
312         YangInstanceIdentifierDeserializer.create(this.schemaContext, "not-existing:contA");
313     }
314
315     /**
316      * Negative test of creating <code>QName</code> when after prefix and colon there is not parsable identifier as
317      * local name. Test is expected to fail with <code>IllegalArgumentException</code>.
318      */
319     @Test
320     public void prepareQnameNotValidPrefixAndLocalNameNegativeTest() {
321         this.thrown.expect(IllegalArgumentException.class);
322         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:*not-parsable-identifier");
323     }
324
325     /**
326      * Negative test of creating <code>QName</code> when data ends after prefix and colon. Test is expected to fail
327      * with <code>StringIndexOutOfBoundsException</code>.
328      */
329     @Test
330     public void prepareQnameErrorParsingNegativeTest() {
331         this.thrown.expect(StringIndexOutOfBoundsException.class);
332         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:");
333     }
334
335     /**
336      * Negative test of creating <code>QName</code> when after identifier and colon there is node name of unknown
337      * node in current container. Test is expected to fail with <code>RestconfDocumentedException</code> and error
338      * type, error tag and error status code are compared to expected values.
339      */
340     @Test
341     public void prepareQnameNotValidContainerNameNegativeTest() {
342         try {
343             YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:contA/leafB");
344             fail("Test should fail due to unknown child node in container");
345         } catch (final RestconfDocumentedException e) {
346             assertEquals("Not expected error type",
347                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
348             assertEquals("Not expected error tag",
349                     RestconfError.ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
350             assertEquals("Not expected error status code",
351                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
352         }
353     }
354
355     /**
356      * Negative test of creating <code>QName</code> when after identifier and equals there is node name of unknown
357      * node in current list. Test is expected to fail with <code>RestconfDocumentedException</code> and error
358      * type, error tag and error status code are compared to expected values.
359      */
360     @Test
361     public void prepareQnameNotValidListNameNegativeTest() {
362         try {
363             YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:list-no-key/disabled=false");
364             fail("Test should fail due to unknown child node in list");
365         } catch (final RestconfDocumentedException e) {
366             assertEquals("Not expected error type",
367                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
368             assertEquals("Not expected error tag",
369                     RestconfError.ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
370             assertEquals("Not expected error status code",
371                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
372         }
373     }
374
375     /**
376      * Negative test of getting next identifier when current node is keyed entry. Test is expected to
377      * fail with <code>IllegalArgumentException</code>.
378      */
379     @Test
380     public void prepareIdentifierNotKeyedEntryNegativeTest() {
381         this.thrown.expect(IllegalArgumentException.class);
382         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:list-one-key");
383     }
384
385     /**
386      * Negative test when there is a comma also after the last key. Test is expected to fail with
387      * <code>IllegalArgumentException</code>.
388      */
389     @Test
390     public void deserializeKeysEndsWithComaNegativeTest() {
391         this.thrown.expect(IllegalArgumentException.class);
392         YangInstanceIdentifierDeserializer.create( this.schemaContext,
393                 "deserializer-test:list-multiple-keys=value,100,false,");
394     }
395
396     /**
397      * Positive when not all keys of list are encoded. The missing keys should be considered to has empty
398      * <code>String</code> values. Also value of next leaf must not be considered to be missing key value.
399      */
400     @Test
401     public void notAllListKeysEncodedPositiveTest() {
402         final QName list = QName.create("deserializer:test", "2016-06-06", "list-multiple-keys");
403         final Map<QName, Object> values = new LinkedHashMap<>();
404         values.put(QName.create(list, "name"), ":foo");
405         values.put(QName.create(list, "number"), "");
406         values.put(QName.create(list, "enabled"), "");
407
408         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer.create(
409                 this.schemaContext, "deserializer-test:list-multiple-keys=%3Afoo,,/string-value");
410
411         assertEquals("Result does not contains expected number of path arguments", 3, Iterables.size(result));
412
413         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
414
415         // list
416         assertEquals("Not expected path argument",
417                 YangInstanceIdentifier.NodeIdentifier.create(list),
418                 iterator.next());
419         assertEquals("Not expected path argument",
420                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, values).toString(),
421                 iterator.next().toString());
422
423         // leaf
424         assertEquals("Not expected path argument",
425                 new YangInstanceIdentifier.NodeIdentifier(
426                         QName.create("deserializer:test", "2016-06-06", "string-value")),
427                 iterator.next());
428     }
429
430     /**
431      * Negative test when not all keys of list are encoded and it is not possible to consider missing keys to be empty.
432      * Test is expected to fail with <code>RestconfDocumentedException</code> and error type, error tag and error
433      * status code are compared to expected values.
434      */
435     @Test
436     public void notAllListKeysEncodedNegativeTest() {
437         try {
438             YangInstanceIdentifierDeserializer.create(
439                     this.schemaContext, "deserializer-test:list-multiple-keys=%3Afoo/string-value");
440             fail("Test should fail due to missing list key values");
441         } catch (final RestconfDocumentedException e) {
442             assertEquals("Not expected error type",
443                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
444             assertEquals("Not expected error tag",
445                     RestconfError.ErrorTag.MISSING_ATTRIBUTE, e.getErrors().get(0).getErrorTag());
446             assertEquals("Not expected error status code",
447                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
448         }
449     }
450
451     /**
452      * Test URI with list where key value starts with, ends with or contains percent encoded characters.The encoded
453      * value should be complete also with not percent-encoded parts.
454      */
455     @Test
456     public void percentEncodedKeyEndsWithNoPercentEncodedChars() {
457         final String URI = "deserializer-test:list-multiple-keys=%3Afoo,1,true";
458         final YangInstanceIdentifier result = YangInstanceIdentifier.create(
459                 YangInstanceIdentifierDeserializer.create(this.schemaContext, URI));
460
461         final Iterator<Map.Entry<QName, Object>> resultListKeys = ((YangInstanceIdentifier.NodeIdentifierWithPredicates)
462                 result.getLastPathArgument()).getKeyValues().entrySet().iterator();
463
464         assertEquals(":foo", resultListKeys.next().getValue());
465         assertEquals(new Short("1"), resultListKeys.next().getValue());
466         assertEquals(true, resultListKeys.next().getValue());
467     }
468
469     /**
470      * Positive test when all keys of list can be considered to be empty <code>String</code>.
471      */
472     @Test
473     public void deserializeAllKeysEmptyTest() {
474         final QName list = QName.create("deserializer:test", "2016-06-06", "list-multiple-keys");
475         final Map<QName, Object> values = new LinkedHashMap<>();
476         values.put(QName.create(list, "name"), "");
477         values.put(QName.create(list, "number"), "");
478         values.put(QName.create(list, "enabled"), "");
479
480         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
481                 .create(this.schemaContext, "deserializer-test:list-multiple-keys=,,");
482
483         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
484
485         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
486
487         assertEquals("Not expected path argument",
488                 YangInstanceIdentifier.NodeIdentifier.create(list),
489                 iterator.next());
490         assertEquals("Not expected path argument",
491                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, values).toString(),
492                 iterator.next().toString());
493     }
494
495     /**
496      * Negative test of deserialization when for leaf list there is no specified instance value.
497      * <code>RestconfDocumentedException</code> is expected and error type, error tag and error status code are
498      * compared to expected values.
499      */
500     @Test
501     public void leafListMissingKeyNegativeTest() {
502         try {
503             YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:leaf-list-0=");
504             fail("Test should fail due to missing instance value");
505         } catch (final RestconfDocumentedException e) {
506             assertEquals("Not expected error type",
507                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
508             assertEquals("Not expected error tag",
509                     RestconfError.ErrorTag.MISSING_ATTRIBUTE, e.getErrors().get(0).getErrorTag());
510             assertEquals("Not expected error status code",
511                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
512         }
513     }
514
515     /**
516      * Positive test of deserialization when parts of input URI <code>String</code> are defined in another module.
517      */
518     @Test
519     public void deserializePartInOtherModuleTest() {
520         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer.create(
521                 this.schemaContext, "deserializer-test-included:augmented-list=100/augmented-leaf");
522
523         assertEquals("Result does not contains expected number of path arguments", 4, Iterables.size(result));
524
525         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
526         final QName list = QName.create("deserializer:test:included", "2016-06-06", "augmented-list");
527         final QName child = QName.create("deserializer:test", "2016-06-06", "augmented-leaf");
528
529         // list
530         assertEquals("Not expected path argument",
531                 YangInstanceIdentifier.NodeIdentifier.create(list),
532                 iterator.next());
533
534         assertEquals("Not expected path argument",
535                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, QName.create(list, "list-key"), 100)
536                         .toString(),
537                 iterator.next()
538                         .toString());
539
540         // augmented leaf
541         assertEquals("Not expected path argument",
542                 new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(child)),
543                 iterator.next());
544
545         assertEquals("Not expected path argument",
546                 YangInstanceIdentifier.NodeIdentifier.create(child),
547                 iterator.next());
548     }
549 }