Bump upstreams to SNAPSHOTs
[netconf.git] / restconf / restconf-nb-rfc8040 / 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.jaxrs.QueryParams;
19 import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
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.Configuration;
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.SchemaContext;
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 schemaHandler
51      *             handler of {@link SchemaContext}
52      * @param configuration
53      *             configuration for restconf {@link Configuration}}
54      */
55     public RestconfStreamsSubscriptionServiceImpl(final DOMDataBroker dataBroker,
56             final DOMNotificationService notificationService, final SchemaContextHandler schemaHandler,
57             final Configuration configuration) {
58         handlersHolder = new HandlersHolder(dataBroker, notificationService, schemaHandler);
59         streamUtils = configuration.isUseSSE() ? SubscribeToStreamUtil.serverSentEvents()
60                 : SubscribeToStreamUtil.webSockets();
61     }
62
63     @Override
64     public NormalizedNodePayload subscribeToStream(final String identifier, final UriInfo uriInfo) {
65         final NotificationQueryParams params = QueryParams.newNotificationQueryParams(uriInfo);
66
67         final URI response;
68         if (identifier.contains(RestconfStreamsConstants.DATA_SUBSCRIPTION)) {
69             response = streamUtils.subscribeToDataStream(identifier, uriInfo, params, handlersHolder);
70         } else if (identifier.contains(RestconfStreamsConstants.NOTIFICATION_STREAM)) {
71             response = streamUtils.subscribeToYangStream(identifier, uriInfo, params, handlersHolder);
72         } else {
73             final String msg = "Bad type of notification of sal-remote";
74             LOG.warn(msg);
75             throw new RestconfDocumentedException(msg);
76         }
77
78         // prepare node with value of location
79         return NormalizedNodePayload.ofLocation(prepareIIDSubsStreamOutput(handlersHolder.getSchemaHandler()),
80             LOCATION_NODEID, response);
81     }
82
83     /**
84      * Prepare InstanceIdentifierContext for Location leaf.
85      *
86      * @param schemaHandler Schema context handler.
87      * @return InstanceIdentifier of Location leaf.
88      */
89     private static InstanceIdentifierContext prepareIIDSubsStreamOutput(final SchemaContextHandler schemaHandler) {
90         return InstanceIdentifierContext.ofStack(
91             SchemaInferenceStack.ofDataTreePath(schemaHandler.get(), NOTIFI_QNAME, LOCATION_QNAME));
92     }
93
94     /**
95      * Holder of all handlers for notifications.
96      */
97     // FIXME: why do we even need this class?!
98     public static final class HandlersHolder {
99         private final DOMDataBroker dataBroker;
100         private final DOMNotificationService notificationService;
101         private final SchemaContextHandler schemaHandler;
102
103         private HandlersHolder(final DOMDataBroker dataBroker, final DOMNotificationService notificationService,
104                 final SchemaContextHandler schemaHandler) {
105             this.dataBroker = dataBroker;
106             this.notificationService = notificationService;
107             this.schemaHandler = schemaHandler;
108         }
109
110         /**
111          * Get {@link DOMDataBroker}.
112          *
113          * @return the dataBroker
114          */
115         public DOMDataBroker getDataBroker() {
116             return dataBroker;
117         }
118
119         /**
120          * Get {@link DOMNotificationService}.
121          *
122          * @return the notificationService
123          */
124         public DOMNotificationService getNotificationServiceHandler() {
125             return notificationService;
126         }
127
128         /**
129          * Get {@link SchemaContextHandler}.
130          *
131          * @return the schemaHandler
132          */
133         public SchemaContextHandler getSchemaHandler() {
134             return schemaHandler;
135         }
136     }
137 }