2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.restconf.utils.mapping;
10 import com.google.common.base.Preconditions;
11 import java.text.SimpleDateFormat;
12 import java.util.Collection;
14 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
15 import org.opendaylight.restconf.Draft18.IetfYangLibrary;
16 import org.opendaylight.restconf.utils.schema.context.RestconfSchemaUtil;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160621.module.list.Module.ConformanceType;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
22 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
24 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
29 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
30 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
31 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
32 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
33 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.Deviation;
36 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
37 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
38 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
40 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.Module;
42 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
45 * Util class for mapping nodes
48 public final class RestconfMappingNodeUtil {
50 private RestconfMappingNodeUtil() {
51 throw new UnsupportedOperationException("Util class");
55 * Map data from modules to {@link NormalizedNode}
58 * - modules for mapping
59 * @param ietfYangLibraryModule
60 * - ietf-yang-library module
64 * - module-set-id of actual set
65 * @return mapped data as {@link NormalizedNode}
67 public static NormalizedNode<NodeIdentifier, Collection<DataContainerChild<? extends PathArgument, ?>>>
68 mapModulesByIetfYangLibraryYang(final Set<Module> modules, final Module ietfYangLibraryModule,
69 final SchemaContext context, final String moduleSetId) {
70 final DataSchemaNode modulesStateSch =
71 ietfYangLibraryModule.getDataChildByName(IetfYangLibrary.MODUELS_STATE_CONT_QNAME);
72 final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> modulesStateBuilder =
73 Builders.containerBuilder((ContainerSchemaNode) modulesStateSch);
75 final DataSchemaNode moduleSetIdSch =
76 ((ContainerSchemaNode) modulesStateSch).getDataChildByName(IetfYangLibrary.MODULE_SET_ID_LEAF_QNAME);
78 .withChild(Builders.leafBuilder((LeafSchemaNode) moduleSetIdSch).withValue(moduleSetId).build());
80 final DataSchemaNode moduleSch = findNodeInGroupings(IetfYangLibrary.MODULE_QNAME_LIST, ietfYangLibraryModule);
81 final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> mapBuilder =
82 Builders.orderedMapBuilder((ListSchemaNode) moduleSch);
83 for (final Module module : context.getModules()) {
84 fillMapByModules(mapBuilder, moduleSch, false, module, ietfYangLibraryModule, context);
86 return modulesStateBuilder.withChild(mapBuilder.build()).build();
90 * Map data by the specific module or submodule
93 * - ordered list builder for children
95 * - schema of list for entryMapBuilder
97 * - true if module is specified as submodule, false otherwise
99 * - specific module or submodule
100 * @param ietfYangLibraryModule
101 * - ietf-yang-library module
105 private static void fillMapByModules(final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> mapBuilder,
106 final DataSchemaNode moduleSch, final boolean isSubmodule, final Module module,
107 final Module ietfYangLibraryModule, final SchemaContext context) {
108 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder =
109 Builders.mapEntryBuilder((ListSchemaNode) moduleSch);
110 addCommonLeafs(module, mapEntryBuilder, ietfYangLibraryModule);
111 addChildOfModuleBySpecificModuleInternal(
112 IetfYangLibrary.SPECIFIC_MODULE_SCHEMA_LEAF_QNAME, mapEntryBuilder, IetfYangLibrary.BASE_URI_OF_SCHEMA
113 + module.getName() + "/" + new SimpleDateFormat("yyyy-MM-dd").format(module.getRevision()),
114 ietfYangLibraryModule);
116 addChildOfModuleBySpecificModuleOfListChild(IetfYangLibrary.SPECIFIC_MODULE_NAMESPACE_LEAF_QNAME,
117 mapEntryBuilder, module.getNamespace().toString(), ietfYangLibraryModule);
119 // features - not mandatory
120 if ((module.getFeatures() != null) && !module.getFeatures().isEmpty()) {
121 addFeatureLeafList(IetfYangLibrary.SPECIFIC_MODULE_FEATURE_LEAF_LIST_QNAME, mapEntryBuilder,
122 module.getFeatures(), ietfYangLibraryModule);
124 // deviations - not mandatory
125 if ((module.getDeviations() != null) && !module.getDeviations().isEmpty()) {
126 addDeviationList(module, mapEntryBuilder, ietfYangLibraryModule, context);
127 addChildOfModuleBySpecificModuleOfListChild(IetfYangLibrary.SPECIFIC_MODULE_CONFORMANCE_LEAF_QNAME,
128 mapEntryBuilder, ConformanceType.Implement.getName(), ietfYangLibraryModule);
130 addChildOfModuleBySpecificModuleOfListChild(IetfYangLibrary.SPECIFIC_MODULE_CONFORMANCE_LEAF_QNAME,
131 mapEntryBuilder, ConformanceType.Import.getName(), ietfYangLibraryModule);
133 // submodules - not mandatory
134 if ((module.getSubmodules() != null) && !module.getSubmodules().isEmpty()) {
135 addSubmodules(module, mapEntryBuilder, ietfYangLibraryModule, context);
138 mapBuilder.withChild(mapEntryBuilder.build());
142 * Mapping submodules of specific module
145 * - module with submodules
146 * @param mapEntryBuilder
147 * - mapEntryBuilder of parent for mapping children
148 * @param ietfYangLibraryModule
149 * - ietf-yang-library module
153 private static void addSubmodules(final Module module,
154 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
155 final Module ietfYangLibraryModule, final SchemaContext context) {
156 final DataSchemaNode listSubm = findSchemaInListOfModulesSchema(
157 IetfYangLibrary.SPECIFIC_MODULE_SUBMODULE_LIST_QNAME, ietfYangLibraryModule);
158 final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> mapBuilder =
159 Builders.orderedMapBuilder((ListSchemaNode) listSubm);
160 for (final Module submodule : module.getSubmodules()) {
161 fillMapByModules(mapBuilder, listSubm, true, submodule, ietfYangLibraryModule, context);
163 mapEntryBuilder.withChild(mapBuilder.build());
167 * Mapping deviations of specific module
170 * - module with deviations
171 * @param mapEntryBuilder
172 * - mapEntryBuilder of parent for mapping children
173 * @param ietfYangLibraryModule
174 * - ietf-yang-library module
178 private static void addDeviationList(final Module module,
179 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
180 final Module ietfYangLibraryModule, final SchemaContext context) {
181 final DataSchemaNode deviationsSchema = findSchemaInListOfModulesSchema(
182 IetfYangLibrary.SPECIFIC_MODULE_DEVIATION_LIST_QNAME, ietfYangLibraryModule);
183 final CollectionNodeBuilder<MapEntryNode, MapNode> deviations =
184 Builders.mapBuilder((ListSchemaNode) deviationsSchema);
185 for (final Deviation deviation : module.getDeviations()) {
186 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> deviationEntryNode =
187 Builders.mapEntryBuilder((ListSchemaNode) deviationsSchema);
188 final QName lastComponent = deviation.getTargetPath().getLastComponent();
189 addChildOfModuleBySpecificModule(IetfYangLibrary.SPECIFIC_MODULE_NAME_LEAF_QNAME, deviationEntryNode,
190 context.findModuleByNamespaceAndRevision(lastComponent.getNamespace(), lastComponent.getRevision())
192 ietfYangLibraryModule);
193 addChildOfModuleBySpecificModule(IetfYangLibrary.SPECIFIC_MODULE_REVISION_LEAF_QNAME, deviationEntryNode,
194 lastComponent.getRevision(), ietfYangLibraryModule);
195 deviations.withChild(deviationEntryNode.build());
197 mapEntryBuilder.withChild(deviations.build());
201 * Mapping features of specific module
203 * @param qnameOfFeaturesLeafList
204 * - qname of feature leaf-list in ietf-yang-library module
205 * @param mapEntryBuilder
206 * - mapEntryBuilder of parent for mapping children
208 * - features of specific module
209 * @param ietfYangLibraryModule
210 * - ieat-yang-library module
212 private static void addFeatureLeafList(final QName qnameOfFeaturesLeafList,
213 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
214 final Set<FeatureDefinition> features, final Module ietfYangLibraryModule) {
215 final DataSchemaNode schemaNode =
216 findSchemaInListOfModulesSchema(qnameOfFeaturesLeafList, ietfYangLibraryModule);
217 final ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafSetBuilder =
218 Builders.leafSetBuilder((LeafListSchemaNode) schemaNode);
219 for (final FeatureDefinition feature : features) {
220 leafSetBuilder.withChild(Builders.leafSetEntryBuilder((LeafListSchemaNode) schemaNode)
221 .withValue(feature.getQName().getLocalName()).build());
223 mapEntryBuilder.withChild(leafSetBuilder.build());
227 * Mapping common leafs (grouping common-leafs in ietf-yang-library) of
231 * - specific module for getting name and revision
232 * @param mapEntryBuilder
233 * - mapEntryBuilder of parent for mapping children
234 * @param ietfYangLibraryModule
235 * - ietf-yang-library module
237 private static void addCommonLeafs(final Module module,
238 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
239 final Module ietfYangLibraryModule) {
240 addChildOfModuleBySpecificModuleInternal(IetfYangLibrary.SPECIFIC_MODULE_NAME_LEAF_QNAME, mapEntryBuilder,
241 module.getName(), ietfYangLibraryModule);
242 addChildOfModuleBySpecificModuleInternal(IetfYangLibrary.SPECIFIC_MODULE_REVISION_LEAF_QNAME, mapEntryBuilder,
243 new SimpleDateFormat("yyyy-MM-dd").format(module.getRevision()), ietfYangLibraryModule);
247 * Mapping data child of grouping module-list by ietf-yang-library
249 * @param specificQName
250 * - qname of leaf in module-list grouping
251 * @param mapEntryBuilder
252 * - mapEntryBuilder of parent for mapping children
255 * @param ietfYangLibraryModule
256 * - ietf-yang-library module
258 private static void addChildOfModuleBySpecificModuleOfListChild(final QName specificQName,
259 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
260 final Object value, final Module ietfYangLibraryModule) {
261 final DataSchemaNode leafSch = findSchemaInListOfModulesSchema(specificQName, ietfYangLibraryModule);
262 mapEntryBuilder.withChild(Builders.leafBuilder((LeafSchemaNode) leafSch).withValue(value).build());
266 * Find specific schema in gourping module-lsit
268 * @param specificQName
270 * @param ietfYangLibraryModule
271 * - ietf-yang-library module
272 * @return schemaNode of specific child
274 private static DataSchemaNode findSchemaInListOfModulesSchema(final QName specificQName,
275 final Module ietfYangLibraryModule) {
276 for (final GroupingDefinition groupingDefinition : ietfYangLibraryModule.getGroupings()) {
277 if (groupingDefinition.getQName().equals(IetfYangLibrary.GROUPING_MODULE_LIST_QNAME)) {
278 final DataSchemaNode dataChildByName =
279 groupingDefinition.getDataChildByName(IetfYangLibrary.MODULE_QNAME_LIST);
280 return ((ListSchemaNode) dataChildByName).getDataChildByName(specificQName);
283 throw new RestconfDocumentedException(specificQName.getLocalName() + " doesn't exist.");
287 * Mapping data child of internal groupings in module-list grouping
289 * @param specifiLeafQName
290 * - qnmae of leaf for mapping
291 * @param mapEntryBuilder
292 * - mapEntryBuilder of parent for mapping children
295 * @param ietfYangLibraryModule
296 * - ietf-yang-library module
298 private static void addChildOfModuleBySpecificModuleInternal(final QName specifiLeafQName,
299 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
300 final Object value, final Module ietfYangLibraryModule) {
301 final DataSchemaNode nameLeaf = findNodeInInternGroupings(specifiLeafQName, ietfYangLibraryModule);
302 mapEntryBuilder.withChild(Builders.leafBuilder((LeafSchemaNode) nameLeaf).withValue(value).build());
306 * Find schema node of leaf by qname in internal groupings of module-list
309 * @param qnameOfSchema
311 * @param ietfYangLibraryModule
312 * - ietf-yang-library module
313 * @return schema node of specific leaf
315 private static DataSchemaNode findNodeInInternGroupings(final QName qnameOfSchema,
316 final Module ietfYangLibraryModule) {
317 for (final GroupingDefinition groupingDefinition : ietfYangLibraryModule.getGroupings()) {
318 if (groupingDefinition.getQName().equals(IetfYangLibrary.GROUPING_MODULE_LIST_QNAME)) {
319 for (final GroupingDefinition internalGrouping : groupingDefinition.getGroupings()) {
320 if (internalGrouping.getDataChildByName(qnameOfSchema) != null) {
321 return internalGrouping.getDataChildByName(qnameOfSchema);
326 throw new RestconfDocumentedException(qnameOfSchema.getLocalName() + " doesn't exist.");
330 * Mapping childrens of list-module
332 * @param specifiLeafQName
334 * @param mapEntryBuilder
335 * - maptEntryBuilder of parent for mapping children
338 * @param ietfYangLibraryModule
339 * - ietf-yang-library module
341 private static void addChildOfModuleBySpecificModule(final QName specifiLeafQName,
342 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder,
343 final Object value, final Module ietfYangLibraryModule) {
344 final DataSchemaNode nameLeaf = findNodeInGroupings(specifiLeafQName, ietfYangLibraryModule);
345 mapEntryBuilder.withChild(Builders.leafBuilder((LeafSchemaNode) nameLeaf).withValue(value).build());
349 * Find schema of specific leaf in list-module grouping
351 * @param qnameOfSchema
353 * @param ietfYangLibraryModule
354 * - ietf-yang-library module
355 * @return schemaNode of specific leaf
357 private static DataSchemaNode findNodeInGroupings(final QName qnameOfSchema, final Module ietfYangLibraryModule) {
358 for (final GroupingDefinition groupingDefinition : ietfYangLibraryModule.getGroupings()) {
359 if (groupingDefinition.getDataChildByName(qnameOfSchema) != null) {
360 return groupingDefinition.getDataChildByName(qnameOfSchema);
363 throw new RestconfDocumentedException(qnameOfSchema.getLocalName() + " doesn't exist.");
367 * Mapping {@link MapEntryNode} stream entries of stream to
368 * {@link ListSchemaNode}
372 * @param streamListSchemaNode
373 * - mapped {@link DataSchemaNode}
374 * @return {@link MapEntryNode}
376 public static MapEntryNode toStreamEntryNode(final String streamName, final DataSchemaNode streamListSchemaNode) {
377 Preconditions.checkState(streamListSchemaNode instanceof ListSchemaNode);
378 final ListSchemaNode listStreamSchemaNode = (ListSchemaNode) streamListSchemaNode;
379 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamNodeValues = Builders
380 .mapEntryBuilder(listStreamSchemaNode);
383 fillListWithLeaf(listStreamSchemaNode, streamNodeValues, RestconfMappingNodeConstants.NAME, streamName);
385 // STREAM DESCRIPTION
386 fillListWithLeaf(listStreamSchemaNode, streamNodeValues, RestconfMappingNodeConstants.DESCRIPTION,
387 RestconfMappingStreamConstants.DESCRIPTION);
389 // STREAM REPLAY_SUPPORT
390 fillListWithLeaf(listStreamSchemaNode, streamNodeValues, RestconfMappingNodeConstants.REPLAY_SUPPORT,
391 RestconfMappingStreamConstants.REPLAY_SUPPORT);
394 fillListWithLeaf(listStreamSchemaNode, streamNodeValues, RestconfMappingNodeConstants.REPLAY_LOG,
395 RestconfMappingStreamConstants.REPLAY_LOG);
398 fillListWithLeaf(listStreamSchemaNode, streamNodeValues, RestconfMappingNodeConstants.EVENTS,
399 RestconfMappingStreamConstants.EVENTS);
401 return streamNodeValues.build();
405 * Method for filling {@link ListSchemaNode} with {@link LeafSchemaNode}
407 * @param listStreamSchemaNode
408 * - {@link ListSchemaNode}
409 * @param streamNodeValues
410 * - filled {@link DataContainerNodeAttrBuilder}
411 * @param nameSchemaNode
412 * - name of mapped leaf
414 * - value for mapped node
416 private static void fillListWithLeaf(
417 final ListSchemaNode listStreamSchemaNode,
418 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamNodeValues,
419 final String nameSchemaNode, final Object value) {
420 final DataSchemaNode schemaNode = RestconfSchemaUtil
421 .findSchemaNodeInCollection(listStreamSchemaNode.getChildNodes(), nameSchemaNode);
422 Preconditions.checkState(schemaNode instanceof LeafSchemaNode);
423 streamNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) schemaNode).withValue(value).build());