Cleaned up sal-dom-* packages and removed legacy interfaces
[mdsal.git] / binding / mdsal-binding-api / src / main / java / org / opendaylight / controller / sal / binding / api / RpcProviderRegistry.java
1 /*
2  * Copyright (c) 2014 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.controller.sal.binding.api;
9
10 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
11 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
12 import org.opendaylight.yangtools.yang.binding.RpcService;
13
14 /**
15  * Provides a registry for Remote Procedure Call (RPC) service implementations. The RPCs are defined
16  * in YANG models.
17  * <p>
18  * There are 2 types of RPCs:
19  * <ul>
20  * <li>Global</li>
21  * <li>Routed</li>
22  * </ul>
23  *
24  * <h2>Global RPC</h2>
25  * <p>
26  * An RPC is global if there is intended to be only 1 registered implementation. A global RPC is not
27  * explicitly declared as such, essentially any RPC that is not defined to be routed is considered
28  * global.
29  * <p>
30  * Global RPCs are registered using the {@link #addRpcImplementation(Class, RpcService)} method.
31  *
32  * <h2>Routed RPC</h2>
33  * <p>
34  * MD-SAL supports routing of RPC between multiple implementations where the appropriate
35  * implementation is selected at run time based on the content of the RPC message as described in
36  * YANG model.
37  * <p>
38  * RPC routing is based on:
39  * <ul>
40  * <li><b>Route identifier</b> - An
41  * {@link org.opendaylight.yangtools.yang.binding.InstanceIdentifier InstanceIdentifier} value which
42  * is part of the RPC input. This value is used to select the correct implementation at run time.</li>
43  * <li><b>Context Type</b> - A YANG-defined construct which constrains the subset of valid route
44  * identifiers for a particular RPC.</li>
45  * </ul>
46  *
47  * <h3>Context type</h3>
48  * <p>
49  * A context type is modeled in YANG using a combination of a YANG <code>identity</code> and
50  * Opendaylight specific extensions from <code>yang-ext</code> module. These extensions are:
51  * <ul>
52  * <li><b>context-instance</b> - This is used in the data tree part of a YANG model to define a
53  * context type that associates nodes with a specified context <code>identity</code>. Instance
54  * identifiers that reference these nodes are valid route identifiers for RPCs that reference this
55  * context type.</li>
56  * <li><b>context-reference</b> - This is used in RPC input to mark a leaf of type
57  * <code>instance-identifier</code> as a reference to the particular context type defined by the
58  * specified context <code>identity</code>. The value of this leaf is used by the RPC broker at run
59  * time to route the RPC request to the correct implementation. Note that
60  * <code>context-reference</code> may only be used on leaf elements of type
61  * <code>instance-identifier</code> or a type derived from <code>instance-identifier</code>.</li>
62  * </ul>
63  *
64  *
65  * <h3>Routed RPC example</h3>
66  * <p>
67  * <h4>1. Defining a Context Type</h4>
68  * <p>
69  * The following snippet declares a simple YANG <code>identity</code> named
70  * <code>example-context</code>:
71  *
72  * <pre>
73  * module example {
74  *     ...
75  *     identity example-context {
76  *          description "Identity used to define an example-context type";
77  *     }
78  *     ...
79  * }
80  * </pre>
81  * <p>
82  * We then use the declared identity to define a context type by using it in combination with the
83  * <code>context-instance</code> YANG extension. We'll associate the context type with a list
84  * element in the data tree. This defines the set of nodes whose instance identifiers are valid for
85  * the <code>example-context</code> context type.
86  * <p>
87  * The following YANG snippet imports the <code>yang-ext</code> module and defines the list element
88  * named <code>item</code> inside a container named <code>foo</code>:
89  *
90  * <pre>
91  * module foo {
92  *     ...
93  *     import yang-ext {prefix ext;}
94  *     ...
95  *     container foo {
96  *          list item {
97  *              key "id";
98  *              leaf id {type string;}
99  *              ext:context-instance "example-context";
100  *          }
101  *     }
102  *     ...
103  * }
104  * </pre>
105  * <p>
106  * The statement <code>ext:context-instance "example-context";</code> inside the list element
107  * declares that any instance identifier referencing <code>item</code> in the data tree is valid for
108  * <code>example-context</code>. For example, the following instance identifier:
109  * 
110  * <pre>
111  * InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey(&quot;Foo&quot;))
112  * </pre>
113  * 
114  * is valid for <code>example-context</code>. However the following:
115  * 
116  * <pre>
117  * InstanceIdentifier.create(Example.class)
118  * </pre>
119  * 
120  * is not valid.
121  * <p>
122  * So using an <code>identity</code> in combination with <code>context-instance</code> we have
123  * effectively defined a context type that can be referenced in a YANG RPC input.
124  *
125  * <h5>2. Defining an RPC to use the Context Type</h5>
126  * <p>
127  * To define an RPC to be routed based on the context type we need to add an input leaf element that
128  * references the context type which will hold an instance identifier value to be used to route the
129  * RPC.
130  * <p>
131  * The following snippet defines an RPC named <code>show-item</code> with 2 leaf elements as input:
132  * <code>item</code> of type <code>instance-identifier</code> and <code>description</code>:
133  *
134  * <pre>
135  * module foo {
136  *      ...
137  *      import yang-ext {prefix ext;}
138  *      ...
139  *      rpc show-item {
140  *          input {
141  *              leaf item {
142  *                  type instance-identifier;
143  *                  ext:context-reference example-context;
144  *              }
145  *              leaf description {
146  *                  type "string";
147  *              }
148  *          }
149  *      }
150  * }
151  * </pre>
152  * <p>
153  * We mark the <code>item</code> leaf with a <code>context-reference</code> statement that
154  * references the <code>example-context</code> context type. RPC calls will then be routed based on
155  * the instance identifier value contained in <code>item</code>. Only instance identifiers that
156  * point to a <code>foo/item</code> node are valid as input.
157  * <p>
158  * The generated RPC Service interface for the module is:
159  *
160  * <pre>
161  * interface FooService implements RpcService {
162  *      Future&lt;RpcResult&lt;Void&gt;&gt; showItem(ShowItemInput input);
163  * }
164  * </pre>
165  * <p>
166  * For constructing the RPC input, there are generated classes ShowItemInput and
167  * ShowItemInputBuilder.
168  *
169  * <h5>3. Registering a routed RPC implementation</h5>
170  * <p>
171  * To register a routed implementation for the <code>show-item</code> RPC, we must use the
172  * {@link #addRoutedRpcImplementation(Class, RpcService)} method. This will return a
173  * {@link RoutedRpcRegistration} instance which can then be used to register / unregister routed
174  * paths associated with the registered implementation.
175  * <p>
176  * The following snippet registers <code>myImpl</code> as the RPC implementation for an
177  * <code>item</code> with key <code>"foo"</code>:
178  * 
179  * <pre>
180  * // Create the instance identifier path for item &quot;foo&quot;
181  * InstanceIdentifier path = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey(&quot;foo&quot;));
182  * 
183  * // Register myImpl as the implementation for the FooService RPC interface
184  * RoutedRpcRegistration reg = rpcRegistry.addRoutedRpcImplementation(FooService.class, myImpl);
185  * 
186  * // Now register for the context type and specific path ID. The context type is specified by the
187  * // YANG-generated class for the example-context identity.
188  * reg.registerPath(ExampleContext.class, path);
189  * </pre>
190  * <p>
191  * It is also possible to register the same implementation for multiple paths:
192  *
193  * <pre>
194  * InstanceIdentifier one = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey(&quot;One&quot;));
195  * InstanceIdentifier two = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey(&quot;Two&quot;));
196  * 
197  * RoutedRpcRegistration reg = rpcRegistry.addRoutedRpcImplementation(FooService.class, myImpl);
198  * reg.registerPath(ExampleContext.class, one);
199  * reg.registerPath(ExampleContext.class, two);
200  * </pre>
201  *
202  * <p>
203  * When another client invokes the <code>showItem(ShowItemInput)</code> method on the proxy instance
204  * retrieved via {@link RpcConsumerRegistry#getRpcService(Class)}, the proxy will inspect the
205  * arguments in ShowItemInput, extract the InstanceIdentifier value of the <code>item</code> leaf
206  * and select the implementation whose registered path matches the InstanceIdentifier value of the
207  * <code>item</code> leaf.
208  *
209  * <h2>Notes for RPC Implementations</h2>
210  *
211  * <h3>RpcResult</h3>
212  * <p>
213  * The generated interfaces require implementors to return {@link java.util.concurrent.Future
214  * Future}&lt;{@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}
215  * &lt;{RpcName}Output&gt;&gt; instances.
216  *
217  * Implementations should do processing of RPC calls asynchronously and update the returned
218  * {@link java.util.concurrent.Future Future} instance when processing is complete. However using
219  * {@link com.google.common.util.concurrent.Futures#immediateFuture(Object) Futures.immediateFuture}
220  * is valid only if the result is immediately available and asynchronous processing is unnecessary
221  * and would only introduce additional complexity.
222  *
223  * <p>
224  * The {@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult} is a generic wrapper for
225  * the RPC output payload, if any, and also allows for attaching error or warning information
226  * (possibly along with the payload) should the RPC processing partially or completely fail. This is
227  * intended to provide additional human readable information for users of the API and to transfer
228  * warning / error information across the system so it may be visible via other external APIs such
229  * as Restconf.
230  * <p>
231  * It is recommended to use the {@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}
232  * for conveying appropriate error information on failure rather than purposely throwing unchecked
233  * exceptions if at all possible. While unchecked exceptions will fail the returned
234  * {@link java.util.concurrent.Future Future}, using the intended RpcResult to convey the error
235  * information is more user-friendly.
236  */
237 public interface RpcProviderRegistry extends RpcConsumerRegistry {
238     /**
239      * Registers a global implementation of the provided RPC service interface.
240      * All methods of the interface are required to be implemented.
241      *
242      * @param serviceInterface the YANG-generated interface of the RPC Service for which to register.
243      * @param implementation "the implementation of the RPC service interface.
244      * @return an RpcRegistration instance that should be used to unregister the RPC implementation
245      *         when no longer needed by calling {@link RpcRegistration#close()}.
246      *
247      * @throws IllegalStateException
248      *             if the supplied RPC interface is a routed RPC type.
249      */
250     <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> serviceInterface, T implementation)
251             throws IllegalStateException;
252
253     /**
254      * Registers an implementation of the given routed RPC service interface.
255      * <p>
256      * See the {@link RpcProviderRegistry class} documentation for information and example on how to
257      * use routed RPCs.
258      *
259      * @param serviceInterface the YANG-generated interface of the RPC Service for which to
260      *        register.
261      * @param implementation the implementation instance to register.
262      * @return a RoutedRpcRegistration instance which can be used to register paths for the RPC
263      *         implementation via invoking
264      *         {@link RoutedRpcRegistration#registerPath(Class, org.opendaylight.yangtools.yang.binding.InstanceIdentifier)}
265      *         . {@link RoutedRpcRegistration#close()} should be called to unregister the
266      *         implementation and all previously registered paths when no longer needed.
267      *
268      * @throws IllegalStateException if the supplied RPC interface is not a routed RPC type.
269      */
270     <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> serviceInterface,
271                                                                                T implementation)
272             throws IllegalStateException;
273 }