X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-dom-adapter%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fdom%2Fadapter%2FRpcServiceAdapter.java;h=1938faf875ae2c86c8e30b6b3f0eaf3278139d43;hb=c71394328f488ea5f3bccf5ac8d42c8802cb637e;hp=3835bc9a500e88928f96b5e9d995365e388a0a61;hpb=c6680361d2856cf956e26c8b0a46ae54492eea3c;p=mdsal.git diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/RpcServiceAdapter.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/RpcServiceAdapter.java index 3835bc9a50..1938faf875 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/RpcServiceAdapter.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/RpcServiceAdapter.java @@ -5,32 +5,33 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ - package org.opendaylight.mdsal.binding.dom.adapter; -import com.google.common.base.Function; +import static java.util.Objects.requireNonNull; +import static org.opendaylight.mdsal.binding.dom.adapter.StaticConfiguration.ENABLE_CODEC_SHORTCUT; + import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; -import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Map.Entry; -import org.opendaylight.mdsal.dom.api.DOMRpcException; +import java.util.Optional; +import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry; +import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections; import org.opendaylight.mdsal.dom.api.DOMRpcResult; import org.opendaylight.mdsal.dom.api.DOMRpcService; import org.opendaylight.mdsal.dom.spi.RpcRoutingStrategy; -import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.RpcService; -import org.opendaylight.yangtools.yang.binding.util.BindingReflections; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; -import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.opendaylight.yangtools.yang.common.YangConstants; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; @@ -41,7 +42,6 @@ import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaPath; class RpcServiceAdapter implements InvocationHandler { - private final ImmutableMap rpcNames; private final Class type; private final BindingToNormalizedNodeCodec codec; @@ -50,9 +50,9 @@ class RpcServiceAdapter implements InvocationHandler { RpcServiceAdapter(final Class type, final BindingToNormalizedNodeCodec codec, final DOMRpcService domService) { - this.type = Preconditions.checkNotNull(type); - this.codec = Preconditions.checkNotNull(codec); - this.delegate = Preconditions.checkNotNull(domService); + this.type = requireNonNull(type); + this.codec = requireNonNull(codec); + this.delegate = requireNonNull(domService); final ImmutableMap.Builder rpcBuilder = ImmutableMap.builder(); for (final Entry rpc : codec.getRpcMethodToSchema(type).entrySet()) { rpcBuilder.put(rpc.getKey(), createStrategy(rpc.getKey(), rpc.getValue())); @@ -61,15 +61,6 @@ class RpcServiceAdapter implements InvocationHandler { proxy = (RpcService) Proxy.newProxyInstance(type.getClassLoader(), new Class[] {type}, this); } - private ListenableFuture> invoke0(final SchemaPath schemaPath, final NormalizedNode input) { - final CheckedFuture result = delegate.invokeRpc(schemaPath, input); - if (result instanceof LazyDOMRpcResultFuture) { - return ((LazyDOMRpcResultFuture) result).getBindingFuture(); - } - - return transformFuture(schemaPath, result, codec.getCodecFactory()); - } - private RpcInvocationStrategy createStrategy(final Method method, final RpcDefinition schema) { final RpcRoutingStrategy strategy = RpcRoutingStrategy.from(schema); if (strategy.isContextBasedRouted()) { @@ -83,11 +74,12 @@ class RpcServiceAdapter implements InvocationHandler { } @Override + @SuppressWarnings("checkstyle:hiddenField") public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { final RpcInvocationStrategy rpc = rpcNames.get(method); if (rpc != null) { - if (method.getParameterTypes().length == 0) { + if (method.getParameterCount() == 0) { return rpc.invokeEmpty(); } if (args.length != 1) { @@ -96,55 +88,28 @@ class RpcServiceAdapter implements InvocationHandler { return rpc.invoke((DataObject) args[0]); } - if (isObjectMethod(method)) { - return callObjectMethod(proxy, method, args); - } - throw new UnsupportedOperationException("Method " + method.toString() + "is unsupported."); - } - - private static boolean isObjectMethod(final Method method) { switch (method.getName()) { case "toString": - return (method.getReturnType().equals(String.class) && method.getParameterTypes().length == 0); + if (method.getReturnType().equals(String.class) && method.getParameterCount() == 0) { + return type.getName() + "$Adapter{delegate=" + delegate.toString() + "}"; + } + break; case "hashCode": - return (method.getReturnType().equals(int.class) && method.getParameterTypes().length == 0); + if (method.getReturnType().equals(int.class) && method.getParameterCount() == 0) { + return System.identityHashCode(proxy); + } + break; case "equals": - return (method.getReturnType().equals(boolean.class) && method.getParameterTypes().length == 1 && method - .getParameterTypes()[0] == Object.class); + if (method.getReturnType().equals(boolean.class) && method.getParameterCount() == 1 + && method.getParameterTypes()[0] == Object.class) { + return proxy == args[0]; + } + break; default: - return false; + break; } - } - private Object callObjectMethod(final Object self, final Method method, final Object[] args) { - switch (method.getName()) { - case "toString": - return type.getName() + "$Adapter{delegate=" + delegate.toString() + "}"; - case "hashCode": - return System.identityHashCode(self); - case "equals": - return (self == args[0]); - default: - return null; - } - } - - private static ListenableFuture> transformFuture(final SchemaPath rpc, - final ListenableFuture domFuture, final BindingNormalizedNodeCodecRegistry codec) { - return Futures.transform(domFuture, new Function>() { - @Override - public RpcResult apply(final DOMRpcResult input) { - final NormalizedNode domData = input.getResult(); - final DataObject bindingResult; - if (domData != null) { - final SchemaPath rpcOutput = rpc.createChild(QName.create(rpc.getLastComponent(), "output")); - bindingResult = codec.fromNormalizedNodeRpcData(rpcOutput, (ContainerNode) domData); - } else { - bindingResult = null; - } - return RpcResult.class.cast(RpcResultBuilder.success(bindingResult).build()); - } - }); + throw new UnsupportedOperationException("Method " + method.toString() + "is unsupported."); } private abstract class RpcInvocationStrategy { @@ -159,7 +124,7 @@ class RpcServiceAdapter implements InvocationHandler { return invoke0(rpcName, serialize(input)); } - abstract NormalizedNode serialize(DataObject input); + abstract ContainerNode serialize(DataObject input); final ListenableFuture> invokeEmpty() { return invoke0(rpcName, null); @@ -169,6 +134,31 @@ class RpcServiceAdapter implements InvocationHandler { return rpcName; } + ListenableFuture> invoke0(final SchemaPath schemaPath, final ContainerNode input) { + final ListenableFuture result = delegate.invokeRpc(schemaPath, input); + if (ENABLE_CODEC_SHORTCUT && result instanceof BindingRpcFutureAware) { + return ((BindingRpcFutureAware) result).getBindingFuture(); + } + + return transformFuture(schemaPath, result, codec.getCodecFactory()); + } + + private ListenableFuture> transformFuture(final SchemaPath rpc, + final ListenableFuture domFuture, final BindingNormalizedNodeCodecRegistry resultCodec) { + return Futures.transform(domFuture, input -> { + final NormalizedNode domData = input.getResult(); + final DataObject bindingResult; + if (domData != null) { + final SchemaPath rpcOutput = rpc.createChild(YangConstants.operationOutputQName( + rpc.getLastComponent().getModule())); + bindingResult = resultCodec.fromNormalizedNodeRpcData(rpcOutput, (ContainerNode) domData); + } else { + bindingResult = null; + } + + return RpcResultUtil.rpcResultFromDOM(input.getErrors(), bindingResult); + }, MoreExecutors.directExecutor()); + } } private final class NonRoutedStrategy extends RpcInvocationStrategy { @@ -178,7 +168,7 @@ class RpcServiceAdapter implements InvocationHandler { } @Override - NormalizedNode serialize(final DataObject input) { + ContainerNode serialize(final DataObject input) { return LazySerializedContainerNode.create(getRpcName(), input, codec.getCodecRegistry()); } @@ -191,13 +181,16 @@ class RpcServiceAdapter implements InvocationHandler { protected RoutedStrategy(final SchemaPath path, final Method rpcMethod, final QName leafName) { super(path); - final Class inputType = BindingReflections.resolveRpcInputClass(rpcMethod).get(); + final Optional> maybeInputType = + BindingReflections.resolveRpcInputClass(rpcMethod); + Preconditions.checkState(maybeInputType.isPresent(), "RPC method %s has no input", rpcMethod.getName()); + final Class inputType = maybeInputType.get(); refExtractor = ContextReferenceExtractor.from(inputType); this.contextName = new NodeIdentifier(leafName); } @Override - NormalizedNode serialize(final DataObject input) { + ContainerNode serialize(final DataObject input) { final InstanceIdentifier bindingII = refExtractor.extract(input); if (bindingII != null) { final YangInstanceIdentifier yangII = codec.toYangInstanceIdentifierCached(bindingII);