Turn streams.Configuration into a record
[netconf.git] / restconf / restconf-nb / src / main / java / org / opendaylight / restconf / nb / rfc8040 / rests / services / impl / RestconfStreamsSubscriptionServiceImpl.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.rests.services.impl;
9
10 import java.net.URI;
11 import javax.ws.rs.Path;
12 import javax.ws.rs.core.UriInfo;
13 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
14 import org.opendaylight.mdsal.dom.api.DOMNotificationService;
15 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
16 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
17 import org.opendaylight.restconf.nb.rfc8040.NotificationQueryParams;
18 import org.opendaylight.restconf.nb.rfc8040.databind.DatabindProvider;
19 import org.opendaylight.restconf.nb.rfc8040.databind.jaxrs.QueryParams;
20 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
21 import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
22 import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants;
23 import org.opendaylight.restconf.nb.rfc8040.streams.StreamsConfiguration;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
26 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
27 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Implementation of {@link RestconfStreamsSubscriptionService}.
33  */
34 @Path("/")
35 public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSubscriptionService {
36     private static final Logger LOG = LoggerFactory.getLogger(RestconfStreamsSubscriptionServiceImpl.class);
37     private static final QName LOCATION_QNAME =
38         QName.create("subscribe:to:notification", "2016-10-28", "location").intern();
39     private static final NodeIdentifier LOCATION_NODEID = NodeIdentifier.create(LOCATION_QNAME);
40     private static final QName NOTIFI_QNAME = QName.create(LOCATION_QNAME, "notifi").intern();
41
42     private final SubscribeToStreamUtil streamUtils;
43     private final HandlersHolder handlersHolder;
44
45     /**
46      * Initialize holder of handlers with holders as parameters.
47      *
48      * @param dataBroker {@link DOMDataBroker}
49      * @param notificationService {@link DOMNotificationService}
50      * @param databindProvider a {@link DatabindProvider}
51      * @param configuration configuration for RESTCONF {@link StreamsConfiguration}}
52      */
53     public RestconfStreamsSubscriptionServiceImpl(final DOMDataBroker dataBroker,
54             final DOMNotificationService notificationService, final DatabindProvider databindProvider,
55             final StreamsConfiguration configuration) {
56         handlersHolder = new HandlersHolder(dataBroker, notificationService, databindProvider);
57         streamUtils = configuration.useSSE() ? SubscribeToStreamUtil.serverSentEvents()
58                 : SubscribeToStreamUtil.webSockets();
59     }
60
61     @Override
62     public NormalizedNodePayload subscribeToStream(final String identifier, final UriInfo uriInfo) {
63         final NotificationQueryParams params = QueryParams.newNotificationQueryParams(uriInfo);
64
65         final URI response;
66         if (identifier.contains(RestconfStreamsConstants.DATA_SUBSCRIPTION)) {
67             response = streamUtils.subscribeToDataStream(identifier, uriInfo, params, handlersHolder);
68         } else if (identifier.contains(RestconfStreamsConstants.NOTIFICATION_STREAM)) {
69             response = streamUtils.subscribeToYangStream(identifier, uriInfo, params, handlersHolder);
70         } else {
71             final String msg = "Bad type of notification of sal-remote";
72             LOG.warn(msg);
73             throw new RestconfDocumentedException(msg);
74         }
75
76         // prepare node with value of location
77         return NormalizedNodePayload.ofLocation(
78             prepareIIDSubsStreamOutput(handlersHolder.getDatabindProvider().currentContext().modelContext()),
79             LOCATION_NODEID, response);
80     }
81
82     /**
83      * Prepare InstanceIdentifierContext for Location leaf.
84      *
85      * @param schemaHandler Schema context handler.
86      * @return InstanceIdentifier of Location leaf.
87      */
88     private static InstanceIdentifierContext prepareIIDSubsStreamOutput(final EffectiveModelContext modelContext) {
89         return InstanceIdentifierContext.ofStack(
90             SchemaInferenceStack.ofDataTreePath(modelContext, NOTIFI_QNAME, LOCATION_QNAME));
91     }
92
93     /**
94      * Holder of all handlers for notifications.
95      */
96     // FIXME: why do we even need this class?!
97     public static final class HandlersHolder {
98         private final DOMDataBroker dataBroker;
99         private final DOMNotificationService notificationService;
100         private final DatabindProvider databindProvider;
101
102         private HandlersHolder(final DOMDataBroker dataBroker, final DOMNotificationService notificationService,
103                 final DatabindProvider databindProvider) {
104             this.dataBroker = dataBroker;
105             this.notificationService = notificationService;
106             this.databindProvider = databindProvider;
107         }
108
109         /**
110          * Get {@link DOMDataBroker}.
111          *
112          * @return the dataBroker
113          */
114         public DOMDataBroker getDataBroker() {
115             return dataBroker;
116         }
117
118         /**
119          * Get {@link DOMNotificationService}.
120          *
121          * @return the notificationService
122          */
123         public DOMNotificationService getNotificationServiceHandler() {
124             return notificationService;
125         }
126
127         /**
128          * Get {@link DatabindProvider}.
129          *
130          * @return the schemaHandler
131          */
132         public DatabindProvider getDatabindProvider() {
133             return databindProvider;
134         }
135     }
136 }