Reduce exception guard
[netconf.git] / restconf / restconf-nb / 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 static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.$YangModuleInfoImpl.qnameOf;
11
12 import com.google.common.annotations.VisibleForTesting;
13 import java.net.URI;
14 import java.time.Instant;
15 import java.time.OffsetDateTime;
16 import java.time.ZoneId;
17 import java.time.format.DateTimeFormatter;
18 import java.util.Collection;
19 import java.util.Optional;
20 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
21 import org.opendaylight.restconf.nb.rfc8040.utils.parser.IdentifierCodec;
22 import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.restconf.state.streams.Stream;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.restconf.state.streams.stream.Access;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
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.builder.DataContainerNodeBuilder;
32 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
33 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
34 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
35 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
36 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
37
38 /**
39  * Util class for mapping nodes.
40  */
41 public final class RestconfMappingNodeUtil {
42     @VisibleForTesting
43     static final QName DESCRIPTION_QNAME = qnameOf("description");
44     @VisibleForTesting
45     static final QName ENCODING_QNAME = qnameOf("encoding");
46     @VisibleForTesting
47     static final QName LOCATION_QNAME = qnameOf("location");
48     @VisibleForTesting
49     static final QName NAME_QNAME = qnameOf("name");
50     @VisibleForTesting
51     static final QName REPLAY_SUPPORT_QNAME = qnameOf("replay-support");
52     @VisibleForTesting
53     static final QName REPLAY_LOG_CREATION_TIME = qnameOf("replay-log-creation-time");
54
55     private RestconfMappingNodeUtil() {
56         // Hidden on purpose
57     }
58
59     /**
60      * Map data of yang notification to normalized node according to ietf-restconf-monitoring.
61      *
62      * @param notifiQName qname of notification from listener
63      * @param notifications list of notifications for find schema of notification by notifiQName
64      * @param start start-time query parameter of notification
65      * @param outputType output type of notification
66      * @param uri location of registered listener for sending data of notification
67      * @return mapped data of notification - map entry node if parent exists,
68      *         container streams with list and map entry node if not
69      */
70     public static MapEntryNode mapYangNotificationStreamByIetfRestconfMonitoring(final QName notifiQName,
71             final Collection<? extends NotificationDefinition> notifications, final Instant start,
72             final String outputType, final URI uri) {
73         for (final NotificationDefinition notificationDefinition : notifications) {
74             if (notificationDefinition.getQName().equals(notifiQName)) {
75                 final String streamName = notifiQName.getLocalName();
76                 final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamEntry =
77                     Builders.mapEntryBuilder()
78                         .withNodeIdentifier(NodeIdentifierWithPredicates.of(Stream.QNAME, NAME_QNAME, streamName))
79                         .withChild(ImmutableNodes.leafNode(NAME_QNAME, streamName));
80
81                 notificationDefinition.getDescription().ifPresent(
82                     desc -> streamEntry.withChild(ImmutableNodes.leafNode(DESCRIPTION_QNAME, desc)));
83                 streamEntry.withChild(ImmutableNodes.leafNode(REPLAY_SUPPORT_QNAME, Boolean.TRUE));
84                 if (start != null) {
85                     streamEntry.withChild(ImmutableNodes.leafNode(REPLAY_LOG_CREATION_TIME,
86                         DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.ofInstant(start,
87                             ZoneId.systemDefault()))));
88                 }
89
90                 return streamEntry
91                     .withChild(createAccessList(outputType, uri))
92                     .build();
93             }
94         }
95
96         throw new RestconfDocumentedException(notifiQName + " doesn't exist in any modul");
97     }
98
99     private static MapNode createAccessList(final String outputType, final URI uriToWebsocketServer) {
100         return Builders.mapBuilder()
101             .withNodeIdentifier(new NodeIdentifier(Access.QNAME))
102             .withChild(Builders.mapEntryBuilder()
103                 .withNodeIdentifier(NodeIdentifierWithPredicates.of(Access.QNAME, ENCODING_QNAME, outputType))
104                 .withChild(ImmutableNodes.leafNode(ENCODING_QNAME, outputType))
105                 .withChild(ImmutableNodes.leafNode(LOCATION_QNAME, uriToWebsocketServer.toString()))
106                 .build())
107             .build();
108     }
109
110     /**
111      * Map data of data change notification to normalized node according to ietf-restconf-monitoring.
112      *
113      * @param path path of data to listen on
114      * @param start start-time query parameter of notification
115      * @param outputType output type of notification
116      * @param uri location of registered listener for sending data of notification
117      * @param schemaContext schemaContext for parsing instance identifier to get schema node of data
118      * @return mapped data of notification - map entry node if parent exists,
119      *         container streams with list and map entry node if not
120      */
121     public static MapEntryNode mapDataChangeNotificationStreamByIetfRestconfMonitoring(
122             final YangInstanceIdentifier path, final Instant start, final String outputType, final URI uri,
123             final EffectiveModelContext schemaContext, final String streamName) {
124         final SchemaNode schemaNode = ParserIdentifier.toInstanceIdentifier(
125             IdentifierCodec.serialize(path, schemaContext), schemaContext, Optional.empty()).getSchemaNode();
126         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> streamEntry =
127             Builders.mapEntryBuilder()
128                 .withNodeIdentifier(NodeIdentifierWithPredicates.of(Stream.QNAME, NAME_QNAME, streamName))
129                 .withChild(ImmutableNodes.leafNode(NAME_QNAME, streamName));
130
131         schemaNode.getDescription().ifPresent(desc ->
132             streamEntry.withChild(ImmutableNodes.leafNode(DESCRIPTION_QNAME, desc)));
133
134         return streamEntry
135             .withChild(ImmutableNodes.leafNode(REPLAY_SUPPORT_QNAME, Boolean.TRUE))
136             .withChild(ImmutableNodes.leafNode(REPLAY_LOG_CREATION_TIME,
137                 DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.ofInstant(start, ZoneId.systemDefault()))))
138             .withChild(createAccessList(outputType, uri))
139             .build();
140     }
141 }