2 ** Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.sal.binding.impl.connect.dom;
11 import java.lang.ref.WeakReference;
12 import java.lang.reflect.Method;
13 import java.util.Collections;
14 import java.util.concurrent.Future;
16 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
17 import org.opendaylight.yangtools.yang.binding.DataContainer;
18 import org.opendaylight.yangtools.yang.binding.DataObject;
19 import org.opendaylight.yangtools.yang.binding.RpcService;
20 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.common.RpcResult;
23 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
24 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
25 import org.opendaylight.yangtools.yang.data.api.Node;
26 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
27 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
29 import com.google.common.base.Function;
30 import com.google.common.base.Optional;
31 import com.google.common.collect.ImmutableList;
32 import com.google.common.util.concurrent.Futures;
33 import com.google.common.util.concurrent.ListenableFuture;
36 * RPC's can have both input, output, one or the other, or neither.
38 * This class handles the permutations and provides two means of invocation:
39 * 1. forwardToDomBroker
42 * Weak References to the input and output classes are used to allow these classes to
43 * be from another OSGi bundle/class loader which may come and go.
46 public class RpcInvocationStrategy {
48 private final BindingIndependentMappingService mappingService;
49 private final RpcProvisionRegistry biRpcRegistry;
50 protected final Method targetMethod;
51 protected final QName rpc;
53 @SuppressWarnings("rawtypes")
54 private final WeakReference<Class> inputClass;
56 @SuppressWarnings("rawtypes")
57 private final WeakReference<Class> outputClass;
59 @SuppressWarnings({ "rawtypes" })
60 public RpcInvocationStrategy(final QName rpc,
61 final Method targetMethod,
62 final BindingIndependentMappingService mappingService,
63 final RpcProvisionRegistry biRpcRegistry ) {
65 this.targetMethod = targetMethod;
68 Optional<Class<?>> outputClassOption = BindingReflections.resolveRpcOutputClass(targetMethod);
69 Optional<Class<? extends DataContainer>> inputClassOption = BindingReflections.resolveRpcInputClass(targetMethod);
71 if ( outputClassOption != null && outputClassOption.isPresent() ) {
72 this.outputClass = new WeakReference(outputClassOption.get() ) ;
74 this.outputClass = null ;
76 if ( inputClassOption != null && inputClassOption.isPresent() ) {
77 this.inputClass = new WeakReference(inputClassOption.get() ) ;
79 this.inputClass = null ;
82 this.mappingService = mappingService;
83 this.biRpcRegistry = biRpcRegistry;
86 @SuppressWarnings({ "unchecked" })
87 public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
89 if(biRpcRegistry == null) {
90 return Futures.<RpcResult<?>> immediateFuture(RpcResultBuilder.failed().build());
93 CompositeNode inputXml = null;
95 CompositeNode xml = mappingService.toDataDom(input);
96 inputXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
98 inputXml = ImmutableCompositeNode.create( rpc, Collections.<Node<?>>emptyList() );
101 Function<RpcResult<CompositeNode>, RpcResult<?>> transformationFunction =
102 new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
103 @SuppressWarnings("rawtypes")
105 public RpcResult<?> apply(RpcResult<CompositeNode> result) {
107 Object output = null;
109 if( getOutputClass() != null ) {
110 if (result.getResult() != null) {
111 output = mappingService.dataObjectFromDataDom(getOutputClass().get(),
116 return RpcResultBuilder.from( (RpcResult)result ).withResult( output ).build();
120 return Futures.transform(biRpcRegistry.invokeRpc(rpc, inputXml), transformationFunction);
123 @SuppressWarnings("unchecked")
124 private RpcResult<CompositeNode> uncheckedInvoke(final RpcService rpcService, final CompositeNode domInput) throws Exception {
126 Future<RpcResult<?>> futureResult = null;
128 if( inputClass != null ){
129 DataContainer bindingInput = mappingService.dataObjectFromDataDom(inputClass.get(), domInput);
130 futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService, bindingInput);
133 futureResult = (Future<RpcResult<?>>) targetMethod.invoke(rpcService);
136 if (futureResult == null) {
137 return RpcResultBuilder.<CompositeNode>failed().build();
140 @SuppressWarnings("rawtypes")
141 RpcResult bindingResult = futureResult.get();
143 final Object resultObj = bindingResult.getResult();
144 Object output = null;
145 if (resultObj instanceof DataObject) {
146 output = mappingService.toDataDom((DataObject)resultObj);
148 return RpcResultBuilder.from( bindingResult ).withResult( output ).build();
151 public RpcResult<CompositeNode> invokeOn(final RpcService rpcService, final CompositeNode domInput) throws Exception {
152 return uncheckedInvoke(rpcService, domInput);
155 @SuppressWarnings("rawtypes")
156 public WeakReference<Class> getOutputClass() {