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