75ff3437d6f5bc1f3dca2a155f2f88fb6721ad35
[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.errors.RestconfDocumentedException;
16 import org.opendaylight.restconf.nb.rfc8040.NotificationQueryParams;
17 import org.opendaylight.restconf.nb.rfc8040.databind.DatabindProvider;
18 import org.opendaylight.restconf.nb.rfc8040.databind.jaxrs.QueryParams;
19 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
20 import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService;
21 import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants;
22 import org.opendaylight.restconf.nb.rfc8040.streams.StreamsConfiguration;
23 import org.opendaylight.yang.gen.v1.subscribe.to.notification.rev161028.Notifi;
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.util.SchemaInferenceStack.Inference;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * Implementation of {@link RestconfStreamsSubscriptionService}.
32  */
33 @Path("/")
34 public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSubscriptionService {
35     private static final Logger LOG = LoggerFactory.getLogger(RestconfStreamsSubscriptionServiceImpl.class);
36     private static final QName LOCATION_QNAME = QName.create(Notifi.QNAME, "location").intern();
37     private static final NodeIdentifier LOCATION_NODEID = NodeIdentifier.create(LOCATION_QNAME);
38
39     private final SubscribeToStreamUtil streamUtils;
40     private final HandlersHolder handlersHolder;
41
42     /**
43      * Initialize holder of handlers with holders as parameters.
44      *
45      * @param dataBroker {@link DOMDataBroker}
46      * @param notificationService {@link DOMNotificationService}
47      * @param databindProvider a {@link DatabindProvider}
48      * @param configuration configuration for RESTCONF {@link StreamsConfiguration}}
49      */
50     public RestconfStreamsSubscriptionServiceImpl(final DOMDataBroker dataBroker,
51             final DOMNotificationService notificationService, final DatabindProvider databindProvider,
52             final StreamsConfiguration configuration) {
53         handlersHolder = new HandlersHolder(dataBroker, notificationService, databindProvider);
54         streamUtils = configuration.useSSE() ? SubscribeToStreamUtil.serverSentEvents()
55                 : SubscribeToStreamUtil.webSockets();
56     }
57
58     @Override
59     public NormalizedNodePayload subscribeToStream(final String identifier, final UriInfo uriInfo) {
60         final NotificationQueryParams params = QueryParams.newNotificationQueryParams(uriInfo);
61
62         final URI response;
63         if (identifier.contains(RestconfStreamsConstants.DATA_SUBSCRIPTION)) {
64             response = streamUtils.subscribeToDataStream(identifier, uriInfo, params, handlersHolder);
65         } else if (identifier.contains(RestconfStreamsConstants.NOTIFICATION_STREAM)) {
66             response = streamUtils.subscribeToYangStream(identifier, uriInfo, params, handlersHolder);
67         } else {
68             final String msg = "Bad type of notification of sal-remote";
69             LOG.warn(msg);
70             throw new RestconfDocumentedException(msg);
71         }
72
73         // prepare node with value of location
74         return NormalizedNodePayload.ofLocation(
75             Inference.ofDataTreePath(handlersHolder.getDatabindProvider().currentContext().modelContext(),
76                 Notifi.QNAME, LOCATION_QNAME),
77             LOCATION_NODEID, response);
78     }
79
80     /**
81      * Holder of all handlers for notifications.
82      */
83     // FIXME: why do we even need this class?!
84     public static final class HandlersHolder {
85         private final DOMDataBroker dataBroker;
86         private final DOMNotificationService notificationService;
87         private final DatabindProvider databindProvider;
88
89         private HandlersHolder(final DOMDataBroker dataBroker, final DOMNotificationService notificationService,
90                 final DatabindProvider databindProvider) {
91             this.dataBroker = dataBroker;
92             this.notificationService = notificationService;
93             this.databindProvider = databindProvider;
94         }
95
96         /**
97          * Get {@link DOMDataBroker}.
98          *
99          * @return the dataBroker
100          */
101         public DOMDataBroker getDataBroker() {
102             return dataBroker;
103         }
104
105         /**
106          * Get {@link DOMNotificationService}.
107          *
108          * @return the notificationService
109          */
110         public DOMNotificationService getNotificationServiceHandler() {
111             return notificationService;
112         }
113
114         /**
115          * Get {@link DatabindProvider}.
116          *
117          * @return the schemaHandler
118          */
119         public DatabindProvider getDatabindProvider() {
120             return databindProvider;
121         }
122     }
123 }