Integrate ParserFieldsParameter with FieldsParameter
[netconf.git] / restconf / restconf-nb-rfc8040 / src / test / java / org / opendaylight / restconf / nb / rfc8040 / utils / parser / ParserFieldsParameterTest.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 package org.opendaylight.restconf.nb.rfc8040.utils.parser;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertThrows;
13 import static org.junit.Assert.assertTrue;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.when;
16
17 import java.text.ParseException;
18 import java.util.List;
19 import java.util.Optional;
20 import java.util.Set;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.mockito.Mock;
25 import org.mockito.junit.MockitoJUnitRunner;
26 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
27 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
28 import org.opendaylight.restconf.nb.rfc8040.FieldsParam;
29 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
30 import org.opendaylight.yangtools.yang.common.ErrorTag;
31 import org.opendaylight.yangtools.yang.common.ErrorType;
32 import org.opendaylight.yangtools.yang.common.QName;
33 import org.opendaylight.yangtools.yang.common.QNameModule;
34 import org.opendaylight.yangtools.yang.common.Revision;
35 import org.opendaylight.yangtools.yang.common.XMLNamespace;
36 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
38 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
39 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
40 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
42 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
43 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
46 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
47
48 /**
49  * Unit test for {@link ParserFieldsParameter}.
50  */
51 @RunWith(MockitoJUnitRunner.class)
52 public class ParserFieldsParameterTest {
53
54     @Mock
55     private InstanceIdentifierContext<ContainerSchemaNode> identifierJukebox;
56
57     @Mock
58     private InstanceIdentifierContext<ContainerSchemaNode> identifierTestServices;
59
60     private static final QNameModule Q_NAME_MODULE_JUKEBOX = QNameModule.create(
61         XMLNamespace.of("http://example.com/ns/example-jukebox"), Revision.of("2015-04-04"));
62     private static final QNameModule Q_NAME_MODULE_TEST_SERVICES = QNameModule.create(
63         XMLNamespace.of("tests:test-services"), Revision.of("2019-03-25"));
64     private static final QNameModule Q_NAME_MODULE_AUGMENTED_JUKEBOX = QNameModule.create(
65         XMLNamespace.of("http://example.com/ns/augmented-jukebox"), Revision.of("2016-05-05"));
66
67     // container jukebox
68     @Mock
69     private ContainerSchemaNode containerJukebox;
70     private static final QName JUKEBOX_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "jukebox");
71
72     // container player
73     @Mock
74     private ContainerSchemaNode containerPlayer;
75     private static final QName PLAYER_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "player");
76
77     // container library
78     @Mock
79     private ContainerSchemaNode containerLibrary;
80     private static final QName LIBRARY_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "library");
81
82     // container augmented library
83     @Mock
84     private ContainerSchemaNode augmentedContainerLibrary;
85     private static final QName AUGMENTED_LIBRARY_Q_NAME = QName.create(Q_NAME_MODULE_AUGMENTED_JUKEBOX,
86             "augmented-library");
87
88     // augmentation that contains speed leaf
89     @Mock
90     private AugmentationSchemaNode speedAugmentation;
91
92     // leaf speed
93     @Mock
94     private LeafSchemaNode leafSpeed;
95     private static final QName SPEED_Q_NAME = QName.create(Q_NAME_MODULE_AUGMENTED_JUKEBOX, "speed");
96
97     // list album
98     @Mock
99     private ListSchemaNode listAlbum;
100     private static final QName ALBUM_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "album");
101
102     // leaf name
103     @Mock
104     private LeafSchemaNode leafName;
105     private static final QName NAME_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "name");
106
107     // container test data
108     @Mock
109     private ContainerSchemaNode containerTestData;
110     private static final QName TEST_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "test-data");
111
112     // list services
113     @Mock
114     private ListSchemaNode listServices;
115     private static final QName SERVICES_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "services");
116
117     // leaf type-of-service
118     @Mock
119     private LeafSchemaNode leafTypeOfService;
120     private static final QName TYPE_OF_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "type-of-service");
121
122     // list instance
123     @Mock
124     private ListSchemaNode listInstance;
125     private static final QName INSTANCE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance");
126
127     // leaf instance-name
128     @Mock
129     private LeafSchemaNode leafInstanceName;
130     private static final QName INSTANCE_NAME_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance-name");
131
132     // leaf provider
133     @Mock
134     private LeafSchemaNode leafProvider;
135     private static final QName PROVIDER_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "provider");
136
137     // container next-data
138     @Mock
139     private ContainerSchemaNode containerNextData;
140     private static final QName NEXT_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-data");
141
142     // leaf next-service
143     @Mock
144     private LeafSchemaNode leafNextService;
145     private static final QName NEXT_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-service");
146
147     // leaf-list protocols
148     @Mock
149     private LeafListSchemaNode leafListProtocols;
150     private static final QName PROTOCOLS_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "protocols");
151
152     @Before
153     public void setUp() throws Exception {
154         final EffectiveModelContext schemaContextJukebox =
155                 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/jukebox"));
156         initJukeboxSchemaNodes(schemaContextJukebox);
157
158         final EffectiveModelContext schemaContextTestServices =
159                 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/test-services"));
160         initTestServicesSchemaNodes(schemaContextTestServices);
161     }
162
163     private void initJukeboxSchemaNodes(final EffectiveModelContext schemaContext) {
164         when(identifierJukebox.getSchemaContext()).thenReturn(schemaContext);
165         when(containerJukebox.getQName()).thenReturn(JUKEBOX_Q_NAME);
166         when(identifierJukebox.getSchemaNode()).thenReturn(containerJukebox);
167
168         when(containerLibrary.getQName()).thenReturn(LIBRARY_Q_NAME);
169         when(containerJukebox.dataChildByName(LIBRARY_Q_NAME)).thenReturn(containerLibrary);
170
171         when(augmentedContainerLibrary.getQName()).thenReturn(AUGMENTED_LIBRARY_Q_NAME);
172         when(containerJukebox.dataChildByName(AUGMENTED_LIBRARY_Q_NAME))
173                 .thenReturn(augmentedContainerLibrary);
174
175         when(containerPlayer.getQName()).thenReturn(PLAYER_Q_NAME);
176         when(containerJukebox.dataChildByName(PLAYER_Q_NAME)).thenReturn(containerPlayer);
177
178         when(listAlbum.getQName()).thenReturn(ALBUM_Q_NAME);
179         when(containerLibrary.dataChildByName(ALBUM_Q_NAME)).thenReturn(listAlbum);
180
181         when(leafName.getQName()).thenReturn(NAME_Q_NAME);
182         when(listAlbum.dataChildByName(NAME_Q_NAME)).thenReturn(leafName);
183
184         when(leafSpeed.getQName()).thenReturn(SPEED_Q_NAME);
185         when(leafSpeed.isAugmenting()).thenReturn(true);
186         when(containerPlayer.dataChildByName(SPEED_Q_NAME)).thenReturn(leafSpeed);
187         when(containerPlayer.getDataChildByName(SPEED_Q_NAME)).thenReturn(leafSpeed);
188         doReturn(List.of(leafSpeed)).when(speedAugmentation).getChildNodes();
189         doReturn(List.of(speedAugmentation)).when(containerPlayer).getAvailableAugmentations();
190         when(speedAugmentation.findDataChildByName(SPEED_Q_NAME)).thenReturn(Optional.of(leafSpeed));
191     }
192
193     private void initTestServicesSchemaNodes(final EffectiveModelContext schemaContext) {
194         when(identifierTestServices.getSchemaContext()).thenReturn(schemaContext);
195         when(containerTestData.getQName()).thenReturn(TEST_DATA_Q_NAME);
196         when(identifierTestServices.getSchemaNode()).thenReturn(containerTestData);
197
198         when(listServices.getQName()).thenReturn(SERVICES_Q_NAME);
199         when(containerTestData.dataChildByName(SERVICES_Q_NAME)).thenReturn(listServices);
200
201         when(leafListProtocols.getQName()).thenReturn(PROTOCOLS_Q_NAME);
202         when(containerTestData.dataChildByName(PROTOCOLS_Q_NAME)).thenReturn(leafListProtocols);
203
204         when(leafTypeOfService.getQName()).thenReturn(TYPE_OF_SERVICE_Q_NAME);
205         when(listServices.dataChildByName(TYPE_OF_SERVICE_Q_NAME)).thenReturn(leafTypeOfService);
206
207         when(listInstance.getQName()).thenReturn(INSTANCE_Q_NAME);
208         when(listServices.dataChildByName(INSTANCE_Q_NAME)).thenReturn(listInstance);
209
210         when(leafInstanceName.getQName()).thenReturn(INSTANCE_NAME_Q_NAME);
211         when(listInstance.dataChildByName(INSTANCE_NAME_Q_NAME)).thenReturn(leafInstanceName);
212
213         when(leafProvider.getQName()).thenReturn(PROVIDER_Q_NAME);
214         when(listInstance.dataChildByName(PROVIDER_Q_NAME)).thenReturn(leafProvider);
215
216         when(containerNextData.getQName()).thenReturn(NEXT_DATA_Q_NAME);
217         when(listServices.dataChildByName(NEXT_DATA_Q_NAME)).thenReturn(containerNextData);
218
219         when(leafNextService.getQName()).thenReturn(NEXT_SERVICE_Q_NAME);
220         when(containerNextData.dataChildByName(NEXT_SERVICE_Q_NAME)).thenReturn(leafNextService);
221     }
222
223     /**
224      * Test parse fields parameter containing only one child selected.
225      */
226     @Test
227     public void parseFieldsParameterSimplePathTest() {
228         final List<Set<QName>> parsedFields = assertFieldsParameter(identifierJukebox, "library");
229
230         assertNotNull(parsedFields);
231         assertEquals(1, parsedFields.size());
232         assertEquals(1, parsedFields.get(0).size());
233         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
234     }
235
236     /**
237      * Test parse fields parameter containing two child nodes selected.
238      */
239     @Test
240     public void parseFieldsParameterDoublePathTest() {
241         final List<Set<QName>> parsedFields = assertFieldsParameter(identifierJukebox, "library;player");
242
243         assertNotNull(parsedFields);
244         assertEquals(1, parsedFields.size());
245         assertEquals(2, parsedFields.get(0).size());
246         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
247         assertTrue(parsedFields.get(0).contains(PLAYER_Q_NAME));
248     }
249
250     /**
251      * Test parse fields parameter containing sub-children selected delimited by slash.
252      */
253     @Test
254     public void parseFieldsParameterSubPathTest() {
255         final List<Set<QName>> parsedFields = assertFieldsParameter(identifierJukebox, "library/album/name");
256
257         assertNotNull(parsedFields);
258         assertEquals(3, parsedFields.size());
259
260         assertEquals(1, parsedFields.get(0).size());
261         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
262
263         assertEquals(1, parsedFields.get(1).size());
264         assertTrue(parsedFields.get(1).contains(ALBUM_Q_NAME));
265
266         assertEquals(1, parsedFields.get(2).size());
267         assertTrue(parsedFields.get(2).contains(NAME_Q_NAME));
268     }
269
270     /**
271      * Test parse fields parameter containing sub-children selected delimited by parenthesis.
272      */
273     @Test
274     public void parseFieldsParameterChildrenPathTest() {
275         final List<Set<QName>> parsedFields = assertFieldsParameter(identifierJukebox, "library(album(name))");
276
277         assertNotNull(parsedFields);
278         assertEquals(3, parsedFields.size());
279
280         assertEquals(1, parsedFields.get(0).size());
281         assertTrue(parsedFields.get(0).contains(LIBRARY_Q_NAME));
282
283         assertEquals(1, parsedFields.get(1).size());
284         assertTrue(parsedFields.get(1).contains(ALBUM_Q_NAME));
285
286         assertEquals(1, parsedFields.get(2).size());
287         assertTrue(parsedFields.get(2).contains(NAME_Q_NAME));
288     }
289
290     /**
291      * Test parse fields parameter when augmentation with different namespace is used.
292      */
293     @Test
294     public void parseFieldsParameterNamespaceTest() {
295         final List<Set<QName>> parsedFields = assertFieldsParameter(identifierJukebox,
296             "augmented-jukebox:augmented-library");
297
298         assertNotNull(parsedFields);
299         assertEquals(1, parsedFields.size());
300
301         assertEquals(1, parsedFields.get(0).size());
302         assertTrue(parsedFields.get(0).contains(AUGMENTED_LIBRARY_Q_NAME));
303     }
304
305     /**
306      * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
307      * direct children of parent node - multiple children which are constructed using '/'.
308      */
309     @Test
310     public void parseFieldsParameterWithMultipleChildrenTest1() {
311         final List<Set<QName>> parsedFields = assertFieldsParameter(identifierTestServices,
312             "services(type-of-service;instance/instance-name;instance/provider)");
313
314         assertNotNull(parsedFields);
315         assertEquals(parsedFields.size(), 3);
316
317         assertEquals(parsedFields.get(0).size(), 1);
318         assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
319
320         assertEquals(parsedFields.get(1).size(), 2);
321         assertTrue(parsedFields.get(1).containsAll(List.of(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME)));
322
323         assertEquals(parsedFields.get(2).size(), 2);
324         assertTrue(parsedFields.get(2).containsAll(List.of(INSTANCE_NAME_Q_NAME, PROVIDER_Q_NAME)));
325     }
326
327     /**
328      * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
329      * direct children of parent node - one of children nodes is typed using brackets, other is constructed using '/'.
330      */
331     @Test
332     public void parseFieldsParameterWithMultipleChildrenTest2() {
333         final List<Set<QName>> parsedFields = assertFieldsParameter(identifierTestServices,
334             "services(type-of-service;instance(instance-name;provider))");
335
336         assertNotNull(parsedFields);
337         assertEquals(parsedFields.size(), 3);
338
339         assertEquals(parsedFields.get(0).size(), 1);
340         assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
341
342         assertEquals(parsedFields.get(1).size(), 2);
343         assertTrue(parsedFields.get(1).containsAll(List.of(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME)));
344
345         assertEquals(parsedFields.get(2).size(), 2);
346         assertTrue(parsedFields.get(2).containsAll(List.of(INSTANCE_NAME_Q_NAME, PROVIDER_Q_NAME)));
347     }
348
349     /**
350      * Testing of fields parameter parsing when multiple nodes are wrapped in brackets and these nodes are not
351      * direct children of parent node - multiple children with different parent nodes.
352      */
353     @Test
354     public void parseFieldsParameterWithMultipleChildrenTest3() {
355         final List<Set<QName>> parsedFields = assertFieldsParameter(identifierTestServices,
356             "services(instance/instance-name;type-of-service;next-data/next-service)");
357
358         assertNotNull(parsedFields);
359         assertEquals(parsedFields.size(), 3);
360
361         assertEquals(parsedFields.get(0).size(), 1);
362         assertTrue(parsedFields.get(0).contains(SERVICES_Q_NAME));
363
364         assertEquals(parsedFields.get(1).size(), 3);
365         assertTrue(parsedFields.get(1).containsAll(
366                 List.of(TYPE_OF_SERVICE_Q_NAME, INSTANCE_Q_NAME, NEXT_DATA_Q_NAME)));
367
368         assertEquals(parsedFields.get(2).size(), 2);
369         assertTrue(parsedFields.get(2).containsAll(
370                 List.of(INSTANCE_NAME_Q_NAME, NEXT_SERVICE_Q_NAME)));
371     }
372
373     /**
374      * Test parse fields parameter when not existing child node selected.
375      */
376     @Test
377     public void parseFieldsParameterMissingChildNodeNegativeTest() throws ParseException {
378         final FieldsParam input = FieldsParam.parse("library(not-existing)");
379
380         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
381             () -> ParserFieldsParameter.parseFieldsParameter(identifierJukebox, input));
382         // Bad request
383         assertEquals("Error type is not correct", ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
384         assertEquals("Error tag is not correct", ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
385     }
386
387     @Test
388     public void parseTopLevelContainerToPathTest() {
389         final List<YangInstanceIdentifier> parsedFields = assertFieldsPaths(identifierJukebox, "library");
390
391         assertNotNull(parsedFields);
392         assertEquals(1, parsedFields.size());
393         final List<PathArgument> pathArguments = parsedFields.get(0).getPathArguments();
394         assertEquals(1, pathArguments.size());
395         assertEquals(LIBRARY_Q_NAME, pathArguments.get(0).getNodeType());
396     }
397
398     @Test
399     public void parseTwoTopLevelContainersToPathsTest() {
400         final String input = "library;player";
401         final List<YangInstanceIdentifier> parsedFields = assertFieldsPaths(identifierJukebox, input);
402
403         assertNotNull(parsedFields);
404         assertEquals(2, parsedFields.size());
405
406         final Optional<YangInstanceIdentifier> libraryPath = findPath(parsedFields, LIBRARY_Q_NAME);
407         assertTrue(libraryPath.isPresent());
408         assertEquals(1, libraryPath.get().getPathArguments().size());
409
410         final Optional<YangInstanceIdentifier> playerPath = findPath(parsedFields, PLAYER_Q_NAME);
411         assertTrue(playerPath.isPresent());
412         assertEquals(1, libraryPath.get().getPathArguments().size());
413     }
414
415     @Test
416     public void parseNestedLeafToPathTest() {
417         final List<YangInstanceIdentifier> parsedFields = assertFieldsPaths(identifierJukebox, "library/album/name");
418
419         assertEquals(1, parsedFields.size());
420         final List<PathArgument> pathArguments = parsedFields.get(0).getPathArguments();
421         assertEquals(3, pathArguments.size());
422
423         assertEquals(LIBRARY_Q_NAME, pathArguments.get(0).getNodeType());
424         assertEquals(ALBUM_Q_NAME, pathArguments.get(1).getNodeType());
425         assertEquals(NAME_Q_NAME, pathArguments.get(2).getNodeType());
426     }
427
428     @Test
429     public void parseAugmentedLeafToPathTest() {
430         final List<YangInstanceIdentifier> parsedFields = assertFieldsPaths(identifierJukebox,
431             "player/augmented-jukebox:speed");
432
433         assertEquals(1, parsedFields.size());
434         final List<PathArgument> pathArguments = parsedFields.get(0).getPathArguments();
435
436         assertEquals(3, pathArguments.size());
437         assertEquals(PLAYER_Q_NAME, pathArguments.get(0).getNodeType());
438         assertTrue(pathArguments.get(1) instanceof AugmentationIdentifier);
439         assertEquals(SPEED_Q_NAME, pathArguments.get(2).getNodeType());
440     }
441
442     @Test
443     public void parseMultipleFieldsOnDifferentLevelsToPathsTest() {
444         final List<YangInstanceIdentifier> parsedFields = assertFieldsPaths(identifierTestServices,
445             "services(type-of-service;instance/instance-name;instance/provider)");
446
447         assertEquals(3, parsedFields.size());
448
449         final Optional<YangInstanceIdentifier> tosPath = findPath(parsedFields, TYPE_OF_SERVICE_Q_NAME);
450         assertTrue(tosPath.isPresent());
451         assertEquals(2, tosPath.get().getPathArguments().size());
452
453         final Optional<YangInstanceIdentifier> instanceNamePath = findPath(parsedFields, INSTANCE_NAME_Q_NAME);
454         assertTrue(instanceNamePath.isPresent());
455         assertEquals(3, instanceNamePath.get().getPathArguments().size());
456
457         final Optional<YangInstanceIdentifier> providerPath = findPath(parsedFields, PROVIDER_Q_NAME);
458         assertTrue(providerPath.isPresent());
459         assertEquals(3, providerPath.get().getPathArguments().size());
460     }
461
462     @Test
463     public void parseListFieldUnderListToPathTest() {
464         final List<YangInstanceIdentifier> parsedFields = assertFieldsPaths(identifierTestServices,
465             "services/instance");
466
467         assertEquals(1, parsedFields.size());
468         final List<PathArgument> pathArguments = parsedFields.get(0).getPathArguments();
469         assertEquals(2, pathArguments.size());
470
471         assertEquals(SERVICES_Q_NAME, pathArguments.get(0).getNodeType());
472         assertTrue(pathArguments.get(0) instanceof NodeIdentifier);
473         assertEquals(INSTANCE_Q_NAME, pathArguments.get(1).getNodeType());
474         assertTrue(pathArguments.get(1) instanceof NodeIdentifier);
475     }
476
477     @Test
478     public void parseLeafListFieldToPathTest() {
479         final List<YangInstanceIdentifier> parsedFields = assertFieldsPaths(identifierTestServices, "protocols");
480
481         assertEquals(1, parsedFields.size());
482         final List<PathArgument> pathArguments = parsedFields.get(0).getPathArguments();
483         assertEquals(1, pathArguments.size());
484         assertTrue(pathArguments.get(0) instanceof NodeIdentifier);
485         assertEquals(PROTOCOLS_Q_NAME, pathArguments.get(0).getNodeType());
486     }
487
488     private static Optional<YangInstanceIdentifier> findPath(final List<YangInstanceIdentifier> paths,
489                                                              final QName lastPathArg) {
490         return paths.stream()
491                 .filter(path -> lastPathArg.equals(path.getLastPathArgument().getNodeType()))
492                 .findAny();
493     }
494
495     private static List<Set<QName>> assertFieldsParameter(final InstanceIdentifierContext<?> identifier,
496             final String input) {
497         return ParserFieldsParameter.parseFieldsParameter(identifier, assertFields(input));
498     }
499
500     private static List<YangInstanceIdentifier> assertFieldsPaths(final InstanceIdentifierContext<?> identifier,
501             final String input) {
502         return ParserFieldsParameter.parseFieldsPaths(identifier, assertFields(input));
503     }
504
505     private static FieldsParam assertFields(final String input) {
506         try {
507             return FieldsParam.parse(input);
508         } catch (ParseException e) {
509             throw new AssertionError(e);
510         }
511     }
512 }