Bug 7686 - Make notifications defined by yangs automatic loaded
[netconf.git] / restconf / sal-rest-connector / src / main / java / org / opendaylight / restconf / 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.utils.mapping;
9
10 import java.net.URI;
11 import java.text.SimpleDateFormat;
12 import java.util.Collection;
13 import java.util.Date;
14 import java.util.Set;
15 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
16 import org.opendaylight.restconf.Rfc8040.IetfYangLibrary;
17 import org.opendaylight.restconf.Rfc8040.MonitoringModule;
18 import org.opendaylight.restconf.Rfc8040.MonitoringModule.QueryParams;
19 import org.opendaylight.restconf.utils.parser.ParserIdentifier;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160621.module.list.Module.ConformanceType;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
26 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
28 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
33 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
34 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
35 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
36 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
37 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.Deviation;
40 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
41 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
42 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
43 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.Module;
46 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
47 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
48 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
49
50 /**
51  * Util class for mapping nodes
52  *
53  */
54 public final class RestconfMappingNodeUtil {
55
56     private RestconfMappingNodeUtil() {
57         throw new UnsupportedOperationException("Util class");
58     }
59
60     /**
61      * Map data from modules to {@link NormalizedNode}
62      *
63      * @param modules
64      *            - modules for mapping
65      * @param ietfYangLibraryModule
66      *            - ietf-yang-library module
67      * @param context
68      *            - schema context
69      * @param moduleSetId
70      *            - module-set-id of actual set
71      * @return mapped data as {@link NormalizedNode}
72      */
73     public static NormalizedNode<NodeIdentifier, Collection<DataContainerChild<? extends PathArgument, ?>>>
74             mapModulesByIetfYangLibraryYang(final Set<Module> modules, final Module ietfYangLibraryModule,
75                     final SchemaContext context, final String moduleSetId) {
76         final DataSchemaNode modulesStateSch =
77                 ietfYangLibraryModule.getDataChildByName(IetfYangLibrary.MODUELS_STATE_CONT_QNAME);
78         final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> modulesStateBuilder =
79                 Builders.containerBuilder((ContainerSchemaNode) modulesStateSch);
80
81         final DataSchemaNode moduleSetIdSch =
82                 ((ContainerSchemaNode) modulesStateSch).getDataChildByName(IetfYangLibrary.MODULE_SET_ID_LEAF_QNAME);
83         modulesStateBuilder
84                 .withChild(Builders.leafBuilder((LeafSchemaNode) moduleSetIdSch).withValue(moduleSetId).build());
85
86         final DataSchemaNode moduleSch = findNodeInGroupings(IetfYangLibrary.MODULE_QNAME_LIST, ietfYangLibraryModule);
87         final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> mapBuilder =
88                 Builders.orderedMapBuilder((ListSchemaNode) moduleSch);
89         for (final Module module : context.getModules()) {
90             fillMapByModules(mapBuilder, moduleSch, false, module, ietfYangLibraryModule, context);
91         }
92         return modulesStateBuilder.withChild(mapBuilder.build()).build();
93     }
94
95     /**
96      * Map data by the specific module or submodule
97      *
98      * @param mapBuilder
99      *            - ordered list builder for children
100      * @param moduleSch
101      *            - schema of list for entryMapBuilder
102      * @param isSubmodule
103      *            - true if module is specified as submodule, false otherwise
104      * @param module
105      *            - specific module or submodule
106      * @param ietfYangLibraryModule
107      *            - ietf-yang-library module
108      * @param context
109      *            - schema context
110      */
111     private static void fillMapByModules(final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> mapBuilder,
112             final DataSchemaNode moduleSch, final boolean isSubmodule, final Module module,
113             final Module ietfYangLibraryModule, final SchemaContext context) {
114         final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder =
115                 Builders.mapEntryBuilder((ListSchemaNode) moduleSch);
116         addCommonLeafs(module, mapEntryBuilder, ietfYangLibraryModule);
117         addChildOfModuleBySpecificModuleInternal(
118                 IetfYangLibrary.SPECIFIC_MODULE_SCHEMA_LEAF_QNAME, mapEntryBuilder, IetfYangLibrary.BASE_URI_OF_SCHEMA
119                         + module.getName() + "/" + new SimpleDateFormat("yyyy-MM-dd").format(module.getRevision()),
120                 ietfYangLibraryModule);
121         if (!isSubmodule) {
122             addChildOfModuleBySpecificModuleOfListChild(IetfYangLibrary.SPECIFIC_MODULE_NAMESPACE_LEAF_QNAME,
123                     mapEntryBuilder, module.getNamespace().toString(), ietfYangLibraryModule);
124
125             // features - not mandatory
126             if ((module.getFeatures() != null) && !module.getFeatures().isEmpty()) {
127                 addFeatureLeafList(IetfYangLibrary.SPECIFIC_MODULE_FEATURE_LEAF_LIST_QNAME, mapEntryBuilder,
128                         module.getFeatures(), ietfYangLibraryModule);
129             }
130             // deviations - not mandatory
131             if ((module.getDeviations() != null) && !module.getDeviations().isEmpty()) {
132                 addDeviationList(module, mapEntryBuilder, ietfYangLibraryModule, context);
133                 addChildOfModuleBySpecificModuleOfListChild(IetfYangLibrary.SPECIFIC_MODULE_CONFORMANCE_LEAF_QNAME,
134                         mapEntryBuilder, ConformanceType.Implement.getName(), ietfYangLibraryModule);
135             } else {
136                 addChildOfModuleBySpecificModuleOfListChild(IetfYangLibrary.SPECIFIC_MODULE_CONFORMANCE_LEAF_QNAME,
137                         mapEntryBuilder, ConformanceType.Import.getName(), ietfYangLibraryModule);
138             }
139             // submodules - not mandatory
140             if ((module.getSubmodules() != null) && !module.getSubmodules().isEmpty()) {
141                 addSubmodules(module, mapEntryBuilder, ietfYangLibraryModule, context);
142             }
143         }
144         mapBuilder.withChild(mapEntryBuilder.build());
145     }
146
147     /**
148      * Mapping submodules of specific module
149      *
150      * @param module
151      *            - module with submodules
152      * @param mapEntryBuilder
153      *            - mapEntryBuilder of parent for mapping children
154      * @param ietfYangLibraryModule
155      *            - ietf-yang-library module
156      * @param context
157      *            - schema context
158      */
159     private static void addSubmodules(final Module module,
160             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
161             final Module ietfYangLibraryModule, final SchemaContext context) {
162         final DataSchemaNode listSubm = findSchemaInListOfModulesSchema(
163                 IetfYangLibrary.SPECIFIC_MODULE_SUBMODULE_LIST_QNAME, ietfYangLibraryModule);
164         final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> mapBuilder =
165                 Builders.orderedMapBuilder((ListSchemaNode) listSubm);
166         for (final Module submodule : module.getSubmodules()) {
167             fillMapByModules(mapBuilder, listSubm, true, submodule, ietfYangLibraryModule, context);
168         }
169         mapEntryBuilder.withChild(mapBuilder.build());
170     }
171
172     /**
173      * Mapping deviations of specific module
174      *
175      * @param module
176      *            - module with deviations
177      * @param mapEntryBuilder
178      *            - mapEntryBuilder of parent for mapping children
179      * @param ietfYangLibraryModule
180      *            - ietf-yang-library module
181      * @param context
182      *            - schema context
183      */
184     private static void addDeviationList(final Module module,
185             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
186             final Module ietfYangLibraryModule, final SchemaContext context) {
187         final DataSchemaNode deviationsSchema = findSchemaInListOfModulesSchema(
188                 IetfYangLibrary.SPECIFIC_MODULE_DEVIATION_LIST_QNAME, ietfYangLibraryModule);
189         final CollectionNodeBuilder<MapEntryNode, MapNode> deviations =
190                 Builders.mapBuilder((ListSchemaNode) deviationsSchema);
191         for (final Deviation deviation : module.getDeviations()) {
192             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> deviationEntryNode =
193                     Builders.mapEntryBuilder((ListSchemaNode) deviationsSchema);
194             final QName lastComponent = deviation.getTargetPath().getLastComponent();
195             addChildOfModuleBySpecificModule(IetfYangLibrary.SPECIFIC_MODULE_NAME_LEAF_QNAME, deviationEntryNode,
196                     context.findModuleByNamespaceAndRevision(lastComponent.getNamespace(), lastComponent.getRevision())
197                             .getName(),
198                     ietfYangLibraryModule);
199             addChildOfModuleBySpecificModule(IetfYangLibrary.SPECIFIC_MODULE_REVISION_LEAF_QNAME, deviationEntryNode,
200                     lastComponent.getRevision(), ietfYangLibraryModule);
201             deviations.withChild(deviationEntryNode.build());
202         }
203         mapEntryBuilder.withChild(deviations.build());
204     }
205
206     /**
207      * Mapping features of specific module
208      *
209      * @param qnameOfFeaturesLeafList
210      *            - qname of feature leaf-list in ietf-yang-library module
211      * @param mapEntryBuilder
212      *            - mapEntryBuilder of parent for mapping children
213      * @param features
214      *            - features of specific module
215      * @param ietfYangLibraryModule
216      *            - ieat-yang-library module
217      */
218     private static void addFeatureLeafList(final QName qnameOfFeaturesLeafList,
219             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
220             final Set<FeatureDefinition> features, final Module ietfYangLibraryModule) {
221         final DataSchemaNode schemaNode =
222                 findSchemaInListOfModulesSchema(qnameOfFeaturesLeafList, ietfYangLibraryModule);
223         final ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafSetBuilder =
224                 Builders.leafSetBuilder((LeafListSchemaNode) schemaNode);
225         for (final FeatureDefinition feature : features) {
226             leafSetBuilder.withChild(Builders.leafSetEntryBuilder((LeafListSchemaNode) schemaNode)
227                     .withValue(feature.getQName().getLocalName()).build());
228         }
229         mapEntryBuilder.withChild(leafSetBuilder.build());
230     }
231
232     /**
233      * Mapping common leafs (grouping common-leafs in ietf-yang-library) of
234      * specific module
235      *
236      * @param module
237      *            - specific module for getting name and revision
238      * @param mapEntryBuilder
239      *            - mapEntryBuilder of parent for mapping children
240      * @param ietfYangLibraryModule
241      *            - ietf-yang-library module
242      */
243     private static void addCommonLeafs(final Module module,
244             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
245             final Module ietfYangLibraryModule) {
246         addChildOfModuleBySpecificModuleInternal(IetfYangLibrary.SPECIFIC_MODULE_NAME_LEAF_QNAME, mapEntryBuilder,
247                 module.getName(), ietfYangLibraryModule);
248         addChildOfModuleBySpecificModuleInternal(IetfYangLibrary.SPECIFIC_MODULE_REVISION_LEAF_QNAME, mapEntryBuilder,
249                 new SimpleDateFormat("yyyy-MM-dd").format(module.getRevision()), ietfYangLibraryModule);
250     }
251
252     /**
253      * Mapping data child of grouping module-list by ietf-yang-library
254      *
255      * @param specificQName
256      *            - qname of leaf in module-list grouping
257      * @param mapEntryBuilder
258      *            - mapEntryBuilder of parent for mapping children
259      * @param value
260      *            - value of leaf
261      * @param ietfYangLibraryModule
262      *            - ietf-yang-library module
263      */
264     private static void addChildOfModuleBySpecificModuleOfListChild(final QName specificQName,
265             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
266             final Object value, final Module ietfYangLibraryModule) {
267         final DataSchemaNode leafSch = findSchemaInListOfModulesSchema(specificQName, ietfYangLibraryModule);
268         mapEntryBuilder.withChild(Builders.leafBuilder((LeafSchemaNode) leafSch).withValue(value).build());
269     }
270
271     /**
272      * Find specific schema in gourping module-lsit
273      *
274      * @param specificQName
275      *            - qname of schema
276      * @param ietfYangLibraryModule
277      *            - ietf-yang-library module
278      * @return schemaNode of specific child
279      */
280     private static DataSchemaNode findSchemaInListOfModulesSchema(final QName specificQName,
281             final Module ietfYangLibraryModule) {
282         for (final GroupingDefinition groupingDefinition : ietfYangLibraryModule.getGroupings()) {
283             if (groupingDefinition.getQName().equals(IetfYangLibrary.GROUPING_MODULE_LIST_QNAME)) {
284                 final DataSchemaNode dataChildByName =
285                         groupingDefinition.getDataChildByName(IetfYangLibrary.MODULE_QNAME_LIST);
286                 return ((ListSchemaNode) dataChildByName).getDataChildByName(specificQName);
287             }
288         }
289         throw new RestconfDocumentedException(specificQName.getLocalName() + " doesn't exist.");
290     }
291
292     /**
293      * Mapping data child of internal groupings in module-list grouping
294      *
295      * @param specifiLeafQName
296      *            - qnmae of leaf for mapping
297      * @param mapEntryBuilder
298      *            - mapEntryBuilder of parent for mapping children
299      * @param value
300      *            - value of leaf
301      * @param ietfYangLibraryModule
302      *            - ietf-yang-library module
303      */
304     private static void addChildOfModuleBySpecificModuleInternal(final QName specifiLeafQName,
305             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
306             final Object value, final Module ietfYangLibraryModule) {
307         final DataSchemaNode nameLeaf = findNodeInInternGroupings(specifiLeafQName, ietfYangLibraryModule);
308         mapEntryBuilder.withChild(Builders.leafBuilder((LeafSchemaNode) nameLeaf).withValue(value).build());
309     }
310
311     /**
312      * Find schema node of leaf by qname in internal groupings of module-list
313      * grouping
314      *
315      * @param qnameOfSchema
316      *            - qname of leaf
317      * @param ietfYangLibraryModule
318      *            - ietf-yang-library module
319      * @return schema node of specific leaf
320      */
321     private static DataSchemaNode findNodeInInternGroupings(final QName qnameOfSchema,
322             final Module ietfYangLibraryModule) {
323         for (final GroupingDefinition groupingDefinition : ietfYangLibraryModule.getGroupings()) {
324             if (groupingDefinition.getQName().equals(IetfYangLibrary.GROUPING_MODULE_LIST_QNAME)) {
325                 for (final GroupingDefinition internalGrouping : groupingDefinition.getGroupings()) {
326                     if (internalGrouping.getDataChildByName(qnameOfSchema) != null) {
327                         return internalGrouping.getDataChildByName(qnameOfSchema);
328                     }
329                 }
330             }
331         }
332         throw new RestconfDocumentedException(qnameOfSchema.getLocalName() + " doesn't exist.");
333     }
334
335     /**
336      * Mapping childrens of list-module
337      *
338      * @param specifiLeafQName
339      *            - qname of leaf
340      * @param mapEntryBuilder
341      *            - maptEntryBuilder of parent for mapping children
342      * @param value
343      *            - valeu of leaf
344      * @param ietfYangLibraryModule
345      *            - ietf-yang-library module
346      */
347     private static void addChildOfModuleBySpecificModule(final QName specifiLeafQName,
348             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
349             final Object value, final Module ietfYangLibraryModule) {
350         final DataSchemaNode nameLeaf = findNodeInGroupings(specifiLeafQName, ietfYangLibraryModule);
351         mapEntryBuilder.withChild(Builders.leafBuilder((LeafSchemaNode) nameLeaf).withValue(value).build());
352     }
353
354     /**
355      * Find schema of specific leaf in list-module grouping
356      *
357      * @param qnameOfSchema
358      *            - qname of leaf
359      * @param ietfYangLibraryModule
360      *            - ietf-yang-library module
361      * @return schemaNode of specific leaf
362      */
363     private static DataSchemaNode findNodeInGroupings(final QName qnameOfSchema, final Module ietfYangLibraryModule) {
364         for (final GroupingDefinition groupingDefinition : ietfYangLibraryModule.getGroupings()) {
365             if (groupingDefinition.getDataChildByName(qnameOfSchema) != null) {
366                 return groupingDefinition.getDataChildByName(qnameOfSchema);
367             }
368         }
369         throw new RestconfDocumentedException(qnameOfSchema.getLocalName() + " doesn't exist.");
370     }
371
372     /**
373      * Map capabilites by ietf-restconf-monitoring
374      *
375      * @param monitoringModule
376      *            - ietf-restconf-monitoring module
377      * @return mapped capabilites
378      */
379     public static NormalizedNode<NodeIdentifier, Collection<DataContainerChild<? extends PathArgument, ?>>>
380             mapCapabilites(final Module monitoringModule) {
381         final DataSchemaNode restconfState =
382                 monitoringModule.getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME);
383         final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> restStateContBuilder =
384                 Builders.containerBuilder((ContainerSchemaNode) restconfState);
385         final DataSchemaNode capabilitesContSchema =
386                 getChildOfCont((ContainerSchemaNode) restconfState, MonitoringModule.CONT_CAPABILITES_QNAME);
387         final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> capabilitesContBuilder =
388                 Builders.containerBuilder((ContainerSchemaNode) capabilitesContSchema);
389         final DataSchemaNode leafListCapa = getChildOfCont((ContainerSchemaNode) capabilitesContSchema,
390                 MonitoringModule.LEAF_LIST_CAPABILITY_QNAME);
391         final ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafListCapaBuilder =
392                 Builders.orderedLeafSetBuilder((LeafListSchemaNode) leafListCapa);
393         fillLeafListCapa(leafListCapaBuilder, (LeafListSchemaNode) leafListCapa);
394
395         return restStateContBuilder.withChild(capabilitesContBuilder.withChild(leafListCapaBuilder.build()).build())
396                 .build();
397     }
398
399     /**
400      * Map data to leaf-list
401      *
402      * @param builder
403      *            - builder of parent for children
404      * @param leafListSchema
405      */
406     @SuppressWarnings({ "unchecked", "rawtypes" })
407     private static void fillLeafListCapa(final ListNodeBuilder builder, final LeafListSchemaNode leafListSchema) {
408         builder.withChild(leafListEntryBuild(leafListSchema, QueryParams.DEPTH));
409         builder.withChild(leafListEntryBuild(leafListSchema, QueryParams.FIELDS));
410         builder.withChild(leafListEntryBuild(leafListSchema, QueryParams.FILTER));
411         builder.withChild(leafListEntryBuild(leafListSchema, QueryParams.REPLAY));
412         builder.withChild(leafListEntryBuild(leafListSchema, QueryParams.WITH_DEFAULTS));
413     }
414
415     /**
416      * Map value to leaf list entry node
417      *
418      * @param leafListSchema
419      *            - leaf list schema of leaf list entry
420      * @param value
421      *            - value of leaf entry
422      * @return entry node
423      */
424     @SuppressWarnings("rawtypes")
425     private static LeafSetEntryNode leafListEntryBuild(final LeafListSchemaNode leafListSchema, final String value) {
426         return Builders.leafSetEntryBuilder(leafListSchema).withValue(value).build();
427     }
428
429     /**
430      * Find specific schema node by qname in parent {@link ContainerSchemaNode}
431      *
432      * @param parent
433      *            - schemaNode
434      * @param childQName
435      *            - specific qname of child
436      * @return schema node of child by qname
437      */
438     private static DataSchemaNode getChildOfCont(final ContainerSchemaNode parent, final QName childQName) {
439         for (final DataSchemaNode child : parent.getChildNodes()) {
440             if (child.getQName().equals(childQName)) {
441                 return child;
442             }
443         }
444         throw new RestconfDocumentedException(
445                 childQName.getLocalName() + " doesn't exist in container " + MonitoringModule.CONT_RESTCONF_STATE_NAME);
446     }
447
448     /**
449      * Map data of yang notification to normalized node according to
450      * ietf-restconf-monitoring
451      *
452      * @param notifiQName
453      *            - qname of notification from listener
454      * @param notifications
455      *            - list of notifications for find schema of notification by
456      *            notifiQName
457      * @param start
458      *            - start-time query parameter of notification
459      * @param outputType
460      *            - output type of notification
461      * @param uri
462      *            - location of registered listener for sending data of
463      *            notification
464      * @param monitoringModule
465      *            - ietf-restconf-monitoring module
466      * @param existParent
467      *            - true if data of parent -
468      *            ietf-restconf-monitoring:restconf-state/streams - exist in DS
469      * @return mapped data of notification - map entry node if parent exists,
470      *         container streams with list and map entry node if not
471      */
472     @SuppressWarnings("rawtypes")
473     public static NormalizedNode mapYangNotificationStreamByIetfRestconfMonitoring(final QName notifiQName,
474             final Set<NotificationDefinition> notifications, final Date start, final String outputType, final URI uri,
475             final Module monitoringModule, final boolean existParent) {
476         for (final NotificationDefinition notificationDefinition : notifications) {
477             if (notificationDefinition.getQName().equals(notifiQName)) {
478                 final DataSchemaNode streamListSchema = ((ContainerSchemaNode) ((ContainerSchemaNode) monitoringModule
479                         .getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
480                                 .getDataChildByName(MonitoringModule.CONT_STREAMS_QNAME))
481                                         .getDataChildByName(MonitoringModule.LIST_STREAM_QNAME);
482                 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamEntry =
483                         Builders.mapEntryBuilder((ListSchemaNode) streamListSchema);
484
485                 final ListSchemaNode listSchema = ((ListSchemaNode) streamListSchema);
486                 prepareLeafAndFillEntryBuilder(streamEntry,
487                         listSchema.getDataChildByName(MonitoringModule.LEAF_NAME_STREAM_QNAME),
488                         notificationDefinition.getQName().getLocalName());
489                 if ((notificationDefinition.getDescription() != null)
490                         && !notificationDefinition.getDescription().equals("")) {
491                     prepareLeafAndFillEntryBuilder(streamEntry,
492                             listSchema.getDataChildByName(MonitoringModule.LEAF_DESCR_STREAM_QNAME),
493                             notificationDefinition.getDescription());
494                 }
495                 prepareLeafAndFillEntryBuilder(streamEntry,
496                         listSchema.getDataChildByName(MonitoringModule.LEAF_REPLAY_SUPP_STREAM_QNAME), true);
497                 if (start != null) {
498                     prepareLeafAndFillEntryBuilder(streamEntry,
499                         listSchema.getDataChildByName(MonitoringModule.LEAF_START_TIME_STREAM_QNAME),
500                         new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'XXX").format(start));
501                 }
502                 prepareListAndFillEntryBuilder(streamEntry,
503                         (ListSchemaNode) listSchema.getDataChildByName(MonitoringModule.LIST_ACCESS_STREAM_QNAME),
504                         outputType, uri);
505
506                 if (!existParent) {
507                     final DataSchemaNode contStreamsSchema = ((ContainerSchemaNode) monitoringModule
508                             .getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
509                                     .getDataChildByName(MonitoringModule.CONT_STREAMS_QNAME);
510                     return Builders.containerBuilder((ContainerSchemaNode) contStreamsSchema).withChild(Builders
511                             .mapBuilder((ListSchemaNode) streamListSchema).withChild(streamEntry.build()).build())
512                             .build();
513                 }
514                 return streamEntry.build();
515             }
516         }
517
518         throw new RestconfDocumentedException(notifiQName + " doesn't exist in any modul");
519     }
520
521     private static void prepareListAndFillEntryBuilder(
522             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamEntry,
523             final ListSchemaNode listSchemaNode, final String outputType, final URI uriToWebsocketServer) {
524         final CollectionNodeBuilder<MapEntryNode, MapNode> accessListBuilder = Builders.mapBuilder(listSchemaNode);
525         final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> entryAccessList =
526                 Builders.mapEntryBuilder(listSchemaNode);
527         prepareLeafAndFillEntryBuilder(entryAccessList,
528                 listSchemaNode.getDataChildByName(MonitoringModule.LEAF_ENCODING_ACCESS_QNAME), outputType);
529         prepareLeafAndFillEntryBuilder(entryAccessList,
530                 listSchemaNode.getDataChildByName(MonitoringModule.LEAF_LOCATION_ACCESS_QNAME),
531                 uriToWebsocketServer.toString());
532         streamEntry.withChild(accessListBuilder.withChild(entryAccessList.build()).build());
533     }
534
535     /**
536      * @param streamEntry
537      * @param dataChildByName
538      * @param localName
539      */
540     private static void prepareLeafAndFillEntryBuilder(
541             final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamEntry,
542             final DataSchemaNode leafSchema, final Object value) {
543         streamEntry.withChild(Builders.leafBuilder((LeafSchemaNode) leafSchema).withValue(value).build());
544     }
545
546     /**
547      * Map data of data change notification to normalized node according to
548      * ietf-restconf-monitoring
549      *
550      * @param path
551      *            - path of data to listen on
552      * @param start
553      *            - start-time query parameter of notification
554      * @param outputType
555      *            - output type of notification
556      * @param uri
557      *            - location of registered listener for sending data of
558      *            notification
559      * @param monitoringModule
560      *            - ietf-restconf-monitoring module
561      * @param existParent
562      *            - true if data of parent -
563      *            ietf-restconf-monitoring:restconf-state/streams - exist in DS
564      * @param schemaContext
565      *            - schemaContext for parsing instance identifier to get schema
566      *            node of data
567      * @return mapped data of notification - map entry node if parent exists,
568      *         container streams with list and map entry node if not
569      */
570     @SuppressWarnings("rawtypes")
571     public static NormalizedNode mapDataChangeNotificationStreamByIetfRestconfMonitoring(
572             final YangInstanceIdentifier path, final Date start, final String outputType, final URI uri,
573             final Module monitoringModule, final boolean existParent, final SchemaContext schemaContext) {
574         final SchemaNode schemaNode = ParserIdentifier
575                 .toInstanceIdentifier(ParserIdentifier.stringFromYangInstanceIdentifier(path, schemaContext),
576                         schemaContext, null)
577                 .getSchemaNode();
578         final DataSchemaNode streamListSchema = ((ContainerSchemaNode) ((ContainerSchemaNode) monitoringModule
579                 .getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
580                         .getDataChildByName(MonitoringModule.CONT_STREAMS_QNAME))
581                                 .getDataChildByName(MonitoringModule.LIST_STREAM_QNAME);
582         final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamEntry =
583                 Builders.mapEntryBuilder((ListSchemaNode) streamListSchema);
584
585         final ListSchemaNode listSchema = ((ListSchemaNode) streamListSchema);
586         prepareLeafAndFillEntryBuilder(streamEntry,
587                 listSchema.getDataChildByName(MonitoringModule.LEAF_NAME_STREAM_QNAME),
588                 schemaNode.getQName().getLocalName());
589         if ((schemaNode.getDescription() != null) && !schemaNode.getDescription().equals("")) {
590             prepareLeafAndFillEntryBuilder(streamEntry,
591                     listSchema.getDataChildByName(MonitoringModule.LEAF_DESCR_STREAM_QNAME),
592                     schemaNode.getDescription());
593         }
594         prepareLeafAndFillEntryBuilder(streamEntry,
595                 listSchema.getDataChildByName(MonitoringModule.LEAF_REPLAY_SUPP_STREAM_QNAME), true);
596         prepareLeafAndFillEntryBuilder(streamEntry,
597                 listSchema.getDataChildByName(MonitoringModule.LEAF_START_TIME_STREAM_QNAME),
598                 new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'XXX").format(start));
599         prepareListAndFillEntryBuilder(streamEntry,
600                 (ListSchemaNode) listSchema.getDataChildByName(MonitoringModule.LIST_ACCESS_STREAM_QNAME), outputType,
601                 uri);
602
603         if (!existParent) {
604             final DataSchemaNode contStreamsSchema = ((ContainerSchemaNode) monitoringModule
605                     .getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
606                             .getDataChildByName(MonitoringModule.CONT_STREAMS_QNAME);
607             return Builders
608                     .containerBuilder((ContainerSchemaNode) contStreamsSchema).withChild(Builders
609                             .mapBuilder((ListSchemaNode) streamListSchema).withChild(streamEntry.build()).build())
610                     .build();
611         }
612         return streamEntry.build();
613     }
614 }