Use schemaless builders in RestconfMappingNodeUtil
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / utils / mapping / RestconfMappingNodeUtil.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.mapping;
9
10 import java.net.URI;
11 import java.time.Instant;
12 import java.time.OffsetDateTime;
13 import java.time.ZoneId;
14 import java.time.format.DateTimeFormatter;
15 import java.util.Collection;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Optional;
19 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
20 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.IetfYangLibrary;
21 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.MonitoringModule;
22 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.MonitoringModule.QueryParams;
23 import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160621.ModulesState;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160621.module.list.Module.ConformanceType;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.common.Revision;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
32 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
35 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
38 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
39 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
40 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
41 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
42 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
43 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.Deviation;
46 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
47 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
48 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
49 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
50 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
51 import org.opendaylight.yangtools.yang.model.api.Module;
52 import org.opendaylight.yangtools.yang.model.api.ModuleLike;
53 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
54 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
55 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
56 import org.opendaylight.yangtools.yang.model.api.Submodule;
57
58 /**
59  * Util class for mapping nodes.
60  *
61  */
62 public final class RestconfMappingNodeUtil {
63     private RestconfMappingNodeUtil() {
64         // Hidden on purpose
65     }
66
67     /**
68      * Map data from modules to {@link NormalizedNode}.
69      *
70      * @param modules modules for mapping
71      * @param context schema context
72      * @param moduleSetId module-set-id of actual set
73      * @return mapped data as {@link NormalizedNode}
74      */
75     public static ContainerNode mapModulesByIetfYangLibraryYang(final Collection<? extends Module> modules,
76             final SchemaContext context, final String moduleSetId) {
77         final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> mapBuilder = Builders.orderedMapBuilder()
78                 .withNodeIdentifier(new NodeIdentifier(IetfYangLibrary.MODULE_QNAME_LIST));
79         for (final Module module : context.getModules()) {
80             fillMapByModules(mapBuilder, IetfYangLibrary.MODULE_QNAME_LIST, false, module, context);
81         }
82         return Builders.containerBuilder()
83             .withNodeIdentifier(new NodeIdentifier(ModulesState.QNAME))
84             .withChild(ImmutableNodes.leafNode(IetfYangLibrary.MODULE_SET_ID_LEAF_QNAME, moduleSetId))
85             .withChild(mapBuilder.build()).build();
86     }
87
88     /**
89      * Map data by the specific module or submodule.
90      *
91      * @param mapBuilder
92      *             ordered list builder for children
93      * @param mapQName
94      *             QName corresponding to the list builder
95      * @param isSubmodule
96      *             true if module is specified as submodule, false otherwise
97      * @param module
98      *             specific module or submodule
99      * @param context
100      *             schema context
101      */
102     private static void fillMapByModules(final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> mapBuilder,
103             final QName mapQName, final boolean isSubmodule, final ModuleLike module, final SchemaContext context) {
104         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder =
105             newCommonLeafsMapEntryBuilder(mapQName, module);
106
107         mapEntryBuilder.withChild(ImmutableNodes.leafNode(IetfYangLibrary.SPECIFIC_MODULE_SCHEMA_LEAF_QNAME,
108             IetfYangLibrary.BASE_URI_OF_SCHEMA + module.getName() + "/"
109             // FIXME: orElse(null) does not seem appropriate here
110             + module.getQNameModule().getRevision().map(Revision::toString).orElse(null)));
111
112         if (!isSubmodule) {
113             mapEntryBuilder.withChild(ImmutableNodes.leafNode(IetfYangLibrary.SPECIFIC_MODULE_NAMESPACE_LEAF_QNAME,
114                 module.getNamespace().toString()));
115
116             // features - not mandatory
117             if (module.getFeatures() != null && !module.getFeatures().isEmpty()) {
118                 addFeatureLeafList(mapEntryBuilder, module.getFeatures());
119             }
120             // deviations - not mandatory
121             final ConformanceType conformance;
122             if (module.getDeviations() != null && !module.getDeviations().isEmpty()) {
123                 addDeviationList(module, mapEntryBuilder, context);
124                 conformance = ConformanceType.Implement;
125             } else {
126                 conformance = ConformanceType.Import;
127             }
128             mapEntryBuilder.withChild(
129                 ImmutableNodes.leafNode(IetfYangLibrary.SPECIFIC_MODULE_CONFORMANCE_LEAF_QNAME, conformance.getName()));
130
131             // submodules - not mandatory
132             if (module.getSubmodules() != null && !module.getSubmodules().isEmpty()) {
133                 addSubmodules(module, mapEntryBuilder, context);
134             }
135         }
136         mapBuilder.withChild(mapEntryBuilder.build());
137     }
138
139     /**
140      * Mapping submodules of specific module.
141      *
142      * @param module
143      *             module with submodules
144      * @param mapEntryBuilder
145      *             mapEntryBuilder of parent for mapping children
146      * @param ietfYangLibraryModule
147      *             ietf-yang-library module
148      * @param context
149      *             schema context
150      */
151     private static void addSubmodules(final ModuleLike module,
152             final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
153             final SchemaContext context) {
154         final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> mapBuilder = Builders.orderedMapBuilder()
155             .withNodeIdentifier(new NodeIdentifier(IetfYangLibrary.SPECIFIC_MODULE_SUBMODULE_LIST_QNAME));
156
157         for (final Submodule submodule : module.getSubmodules()) {
158             fillMapByModules(mapBuilder, IetfYangLibrary.SPECIFIC_MODULE_SUBMODULE_LIST_QNAME, true, submodule,
159                 context);
160         }
161         mapEntryBuilder.withChild(mapBuilder.build());
162     }
163
164     /**
165      * Mapping deviations of specific module.
166      *
167      * @param module
168      *             module with deviations
169      * @param mapEntryBuilder
170      *             mapEntryBuilder of parent for mapping children
171      * @param context
172      *             schema context
173      */
174     private static void addDeviationList(final ModuleLike module,
175             final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
176             final SchemaContext context) {
177         final CollectionNodeBuilder<MapEntryNode, MapNode> deviations = Builders.mapBuilder()
178             .withNodeIdentifier(new NodeIdentifier(IetfYangLibrary.SPECIFIC_MODULE_DEVIATION_LIST_QNAME));
179         for (final Deviation deviation : module.getDeviations()) {
180             final List<QName> ids = deviation.getTargetPath().getNodeIdentifiers();
181             final QName lastComponent = ids.get(ids.size() - 1);
182
183             deviations.withChild(newCommonLeafsMapEntryBuilder(IetfYangLibrary.SPECIFIC_MODULE_DEVIATION_LIST_QNAME,
184                 context.findModule(lastComponent.getModule()).get())
185                 .build());
186         }
187         mapEntryBuilder.withChild(deviations.build());
188     }
189
190     /**
191      * Mapping features of specific module.
192      *
193      * @param mapEntryBuilder mapEntryBuilder of parent for mapping children
194      * @param features features of specific module
195      */
196     private static void addFeatureLeafList(
197             final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
198             final Collection<? extends FeatureDefinition> features) {
199         final ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafSetBuilder = Builders.leafSetBuilder()
200                 .withNodeIdentifier(new NodeIdentifier(IetfYangLibrary.SPECIFIC_MODULE_FEATURE_LEAF_LIST_QNAME));
201         for (final FeatureDefinition feature : features) {
202             final String featureName = feature.getQName().getLocalName();
203             leafSetBuilder.withChild(Builders.leafSetEntryBuilder()
204                 .withNodeIdentifier(
205                     new NodeWithValue<>(IetfYangLibrary.SPECIFIC_MODULE_FEATURE_LEAF_LIST_QNAME, featureName))
206                 .withValue(featureName)
207                 .build());
208         }
209         mapEntryBuilder.withChild(leafSetBuilder.build());
210     }
211
212     private static DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> newCommonLeafsMapEntryBuilder(
213             final QName qname, final ModuleLike module) {
214         final var name = module.getName();
215         final var revision = module.getQNameModule().getRevision().map(Revision::toString).orElse("");
216         return Builders.mapEntryBuilder()
217             .withNodeIdentifier(NodeIdentifierWithPredicates.of(qname, Map.of(
218                 IetfYangLibrary.SPECIFIC_MODULE_NAME_LEAF_QNAME, name,
219                 IetfYangLibrary.SPECIFIC_MODULE_REVISION_LEAF_QNAME, revision)))
220             .withChild(ImmutableNodes.leafNode(IetfYangLibrary.SPECIFIC_MODULE_NAME_LEAF_QNAME, name))
221             .withChild(ImmutableNodes.leafNode(IetfYangLibrary.SPECIFIC_MODULE_REVISION_LEAF_QNAME, revision));
222     }
223
224     /**
225      * Map capabilites by ietf-restconf-monitoring.
226      *
227      * @param monitoringModule
228      *             ietf-restconf-monitoring module
229      * @return mapped capabilites
230      */
231     public static ContainerNode mapCapabilites(final Module monitoringModule) {
232         final DataSchemaNode restconfState =
233                 monitoringModule.getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME);
234         final DataSchemaNode capabilitesContSchema =
235                 getChildOfCont((ContainerSchemaNode) restconfState, MonitoringModule.CONT_CAPABILITES_QNAME);
236         final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> capabilitesContBuilder =
237                 Builders.containerBuilder((ContainerSchemaNode) capabilitesContSchema);
238         final DataSchemaNode leafListCapa = getChildOfCont((ContainerSchemaNode) capabilitesContSchema,
239                 MonitoringModule.LEAF_LIST_CAPABILITY_QNAME);
240         final ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafListCapaBuilder =
241                 Builders.orderedLeafSetBuilder((LeafListSchemaNode) leafListCapa);
242         fillLeafListCapa(leafListCapaBuilder, (LeafListSchemaNode) leafListCapa);
243
244         return Builders.containerBuilder()
245             .withNodeIdentifier(new NodeIdentifier(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
246             .withChild(capabilitesContBuilder.withChild(leafListCapaBuilder.build()).build())
247             .build();
248     }
249
250     /**
251      * Map data to leaf-list.
252      *
253      * @param builder
254      *             builder of parent for children
255      * @param leafListSchema
256      *             leaf list schema
257      */
258     private static void fillLeafListCapa(final ListNodeBuilder<Object, LeafSetEntryNode<Object>> builder,
259             final LeafListSchemaNode leafListSchema) {
260         builder.withChild(leafListEntryBuild(leafListSchema, QueryParams.DEPTH));
261         builder.withChild(leafListEntryBuild(leafListSchema, QueryParams.FIELDS));
262         builder.withChild(leafListEntryBuild(leafListSchema, QueryParams.FILTER));
263         builder.withChild(leafListEntryBuild(leafListSchema, QueryParams.REPLAY));
264         builder.withChild(leafListEntryBuild(leafListSchema, QueryParams.WITH_DEFAULTS));
265     }
266
267     /**
268      * Map value to leaf list entry node.
269      *
270      * @param leafListSchema
271      *             leaf list schema of leaf list entry
272      * @param value
273      *             value of leaf entry
274      * @return entry node
275      */
276     private static LeafSetEntryNode<Object> leafListEntryBuild(final LeafListSchemaNode leafListSchema,
277             final String value) {
278         return Builders.leafSetEntryBuilder(leafListSchema).withValue(value).build();
279     }
280
281     /**
282      * Find specific schema node by qname in parent {@link ContainerSchemaNode}.
283      *
284      * @param parent
285      *             schemaNode
286      * @param childQName
287      *             specific qname of child
288      * @return schema node of child by qname
289      */
290     private static DataSchemaNode getChildOfCont(final ContainerSchemaNode parent, final QName childQName) {
291         for (final DataSchemaNode child : parent.getChildNodes()) {
292             if (child.getQName().equals(childQName)) {
293                 return child;
294             }
295         }
296         throw new RestconfDocumentedException(
297                 childQName.getLocalName() + " doesn't exist in container " + MonitoringModule.CONT_RESTCONF_STATE_NAME);
298     }
299
300     /**
301      * Map data of yang notification to normalized node according to
302      * ietf-restconf-monitoring.
303      *
304      * @param notifiQName
305      *             qname of notification from listener
306      * @param notifications
307      *             list of notifications for find schema of notification by
308      *            notifiQName
309      * @param start
310      *             start-time query parameter of notification
311      * @param outputType
312      *             output type of notification
313      * @param uri
314      *             location of registered listener for sending data of
315      *            notification
316      * @param monitoringModule
317      *             ietf-restconf-monitoring module
318      * @param existParent
319      *             true if data of parent -
320      *            ietf-restconf-monitoring:restconf-state/streams - exist in DS
321      * @return mapped data of notification - map entry node if parent exists,
322      *         container streams with list and map entry node if not
323      */
324     public static NormalizedNode<?, ?> mapYangNotificationStreamByIetfRestconfMonitoring(final QName notifiQName,
325             final Collection<? extends NotificationDefinition> notifications, final Instant start,
326             final String outputType, final URI uri, final Module monitoringModule, final boolean existParent) {
327         for (final NotificationDefinition notificationDefinition : notifications) {
328             if (notificationDefinition.getQName().equals(notifiQName)) {
329                 final DataSchemaNode streamListSchema = ((ContainerSchemaNode) ((ContainerSchemaNode) monitoringModule
330                         .getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
331                                 .getDataChildByName(MonitoringModule.CONT_STREAMS_QNAME))
332                                         .getDataChildByName(MonitoringModule.LIST_STREAM_QNAME);
333                 final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamEntry =
334                         Builders.mapEntryBuilder((ListSchemaNode) streamListSchema);
335
336                 final ListSchemaNode listSchema = (ListSchemaNode) streamListSchema;
337                 prepareLeafAndFillEntryBuilder(streamEntry,
338                         listSchema.getDataChildByName(MonitoringModule.LEAF_NAME_STREAM_QNAME),
339                         notificationDefinition.getQName().getLocalName());
340
341                 final Optional<String> optDesc = notificationDefinition.getDescription();
342                 if (optDesc.isPresent()) {
343                     prepareLeafAndFillEntryBuilder(streamEntry,
344                             listSchema.getDataChildByName(MonitoringModule.LEAF_DESCR_STREAM_QNAME), optDesc.get());
345                 }
346                 prepareLeafAndFillEntryBuilder(streamEntry,
347                         listSchema.getDataChildByName(MonitoringModule.LEAF_REPLAY_SUPP_STREAM_QNAME), true);
348                 if (start != null) {
349                     prepareLeafAndFillEntryBuilder(streamEntry,
350                         listSchema.getDataChildByName(MonitoringModule.LEAF_START_TIME_STREAM_QNAME),
351                         DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.ofInstant(start,
352                             ZoneId.systemDefault())));
353                 }
354                 prepareListAndFillEntryBuilder(streamEntry,
355                         (ListSchemaNode) listSchema.getDataChildByName(MonitoringModule.LIST_ACCESS_STREAM_QNAME),
356                         outputType, uri);
357
358                 if (!existParent) {
359                     final DataSchemaNode contStreamsSchema = ((ContainerSchemaNode) monitoringModule
360                             .getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
361                                     .getDataChildByName(MonitoringModule.CONT_STREAMS_QNAME);
362                     return Builders.containerBuilder((ContainerSchemaNode) contStreamsSchema).withChild(Builders
363                             .mapBuilder((ListSchemaNode) streamListSchema).withChild(streamEntry.build()).build())
364                             .build();
365                 }
366                 return streamEntry.build();
367             }
368         }
369
370         throw new RestconfDocumentedException(notifiQName + " doesn't exist in any modul");
371     }
372
373     private static void prepareListAndFillEntryBuilder(
374             final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamEntry,
375             final ListSchemaNode listSchemaNode, final String outputType, final URI uriToWebsocketServer) {
376         final CollectionNodeBuilder<MapEntryNode, MapNode> accessListBuilder = Builders.mapBuilder(listSchemaNode);
377         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> entryAccessList =
378                 Builders.mapEntryBuilder(listSchemaNode);
379         prepareLeafAndFillEntryBuilder(entryAccessList,
380                 listSchemaNode.getDataChildByName(MonitoringModule.LEAF_ENCODING_ACCESS_QNAME), outputType);
381         prepareLeafAndFillEntryBuilder(entryAccessList,
382                 listSchemaNode.getDataChildByName(MonitoringModule.LEAF_LOCATION_ACCESS_QNAME),
383                 uriToWebsocketServer.toString());
384         streamEntry.withChild(accessListBuilder.withChild(entryAccessList.build()).build());
385     }
386
387     /**
388      * Prepare leaf and fill entry builder.
389      *
390      * @param streamEntry   Stream entry
391      * @param leafSchema    Leaf schema
392      * @param value         Value
393      */
394     private static void prepareLeafAndFillEntryBuilder(
395             final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamEntry,
396             final DataSchemaNode leafSchema, final Object value) {
397         streamEntry.withChild(Builders.leafBuilder((LeafSchemaNode) leafSchema).withValue(value).build());
398     }
399
400     /**
401      * Map data of data change notification to normalized node according to
402      * ietf-restconf-monitoring.
403      *
404      * @param path
405      *             path of data to listen on
406      * @param start
407      *             start-time query parameter of notification
408      * @param outputType
409      *             output type of notification
410      * @param uri
411      *             location of registered listener for sending data of
412      *            notification
413      * @param monitoringModule
414      *             ietf-restconf-monitoring module
415      * @param existParent
416      *             true if data of parent -
417      *            ietf-restconf-monitoring:restconf-state/streams - exist in DS
418      * @param schemaContext
419      *             schemaContext for parsing instance identifier to get schema
420      *            node of data
421      * @return mapped data of notification - map entry node if parent exists,
422      *         container streams with list and map entry node if not
423      */
424     public static NormalizedNode<?, ?> mapDataChangeNotificationStreamByIetfRestconfMonitoring(
425             final YangInstanceIdentifier path, final Instant start, final String outputType, final URI uri,
426             final Module monitoringModule, final boolean existParent, final EffectiveModelContext schemaContext) {
427         final SchemaNode schemaNode = ParserIdentifier
428                 .toInstanceIdentifier(ParserIdentifier.stringFromYangInstanceIdentifier(path, schemaContext),
429                         schemaContext, Optional.empty())
430                 .getSchemaNode();
431         final DataSchemaNode streamListSchema = ((ContainerSchemaNode) ((ContainerSchemaNode) monitoringModule
432                 .getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
433                         .getDataChildByName(MonitoringModule.CONT_STREAMS_QNAME))
434                                 .getDataChildByName(MonitoringModule.LIST_STREAM_QNAME);
435         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamEntry =
436                 Builders.mapEntryBuilder((ListSchemaNode) streamListSchema);
437
438         final ListSchemaNode listSchema = (ListSchemaNode) streamListSchema;
439         prepareLeafAndFillEntryBuilder(streamEntry,
440                 listSchema.getDataChildByName(MonitoringModule.LEAF_NAME_STREAM_QNAME),
441                 schemaNode.getQName().getLocalName());
442
443         final Optional<String> optDesc = schemaNode.getDescription();
444         if (optDesc.isPresent()) {
445             prepareLeafAndFillEntryBuilder(streamEntry,
446                     listSchema.getDataChildByName(MonitoringModule.LEAF_DESCR_STREAM_QNAME), optDesc.get());
447         }
448         prepareLeafAndFillEntryBuilder(streamEntry,
449                 listSchema.getDataChildByName(MonitoringModule.LEAF_REPLAY_SUPP_STREAM_QNAME), true);
450         prepareLeafAndFillEntryBuilder(streamEntry,
451                 listSchema.getDataChildByName(MonitoringModule.LEAF_START_TIME_STREAM_QNAME),
452                 DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.ofInstant(start, ZoneId.systemDefault())));
453         prepareListAndFillEntryBuilder(streamEntry,
454                 (ListSchemaNode) listSchema.getDataChildByName(MonitoringModule.LIST_ACCESS_STREAM_QNAME), outputType,
455                 uri);
456
457         if (!existParent) {
458             final DataSchemaNode contStreamsSchema = ((ContainerSchemaNode) monitoringModule
459                     .getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
460                             .getDataChildByName(MonitoringModule.CONT_STREAMS_QNAME);
461             return Builders
462                     .containerBuilder((ContainerSchemaNode) contStreamsSchema).withChild(Builders
463                             .mapBuilder((ListSchemaNode) streamListSchema).withChild(streamEntry.build()).build())
464                     .build();
465         }
466         return streamEntry.build();
467     }
468 }