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=12c604dcb3497a24446bcd94dc0cf72e4fc29240;hb=7c1493fd2f93985c4b9a45e214cf7a6df9e53cf9;hp=f7ec742788d882d3b078adc6917f4786ce506028;hpb=e9ce6cd98ca8b8da187229b6afedaa16ae123609;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 f7ec742788..12c604dcb3 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 @@ -7,18 +7,24 @@ */ package org.opendaylight.mdsal.binding.dom.adapter; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; +import static org.opendaylight.mdsal.binding.dom.adapter.StaticConfiguration.ENABLE_CODEC_SHORTCUT; + +import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; 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.Collection; import java.util.Map.Entry; -import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry; +import java.util.Optional; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer; +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; @@ -26,12 +32,8 @@ 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.RpcError; -import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity; 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; @@ -40,22 +42,25 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.model.api.RpcDefinition; -import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; class RpcServiceAdapter implements InvocationHandler { private final ImmutableMap rpcNames; private final Class type; - private final BindingToNormalizedNodeCodec codec; + private final AdapterContext adapterContext; private final DOMRpcService delegate; private final RpcService proxy; - RpcServiceAdapter(final Class type, final BindingToNormalizedNodeCodec codec, + RpcServiceAdapter(final Class type, final AdapterContext adapterContext, final DOMRpcService domService) { - this.type = Preconditions.checkNotNull(type); - this.codec = Preconditions.checkNotNull(codec); - this.delegate = Preconditions.checkNotNull(domService); - final ImmutableMap.Builder rpcBuilder = ImmutableMap.builder(); - for (final Entry rpc : codec.getRpcMethodToSchema(type).entrySet()) { + this.type = requireNonNull(type); + this.adapterContext = requireNonNull(adapterContext); + delegate = requireNonNull(domService); + + final ImmutableBiMap methods = adapterContext.currentSerializer() + .getRpcMethodToSchema(type); + final Builder rpcBuilder = ImmutableMap.builderWithExpectedSize(methods.size()); + for (final Entry rpc : methods.entrySet()) { rpcBuilder.put(rpc.getKey(), createStrategy(rpc.getKey(), rpc.getValue())); } rpcNames = rpcBuilder.build(); @@ -63,11 +68,10 @@ class RpcServiceAdapter implements InvocationHandler { } private RpcInvocationStrategy createStrategy(final Method method, final RpcDefinition schema) { + final QName rpcType = schema.getQName(); final RpcRoutingStrategy strategy = RpcRoutingStrategy.from(schema); - if (strategy.isContextBasedRouted()) { - return new RoutedStrategy(schema.getPath(), method, strategy.getLeaf()); - } - return new NonRoutedStrategy(schema.getPath()); + return strategy.isContextBasedRouted() ? new RoutedStrategy(rpcType, method, strategy.getLeaf()) + : new NonRoutedStrategy(rpcType); } RpcService getProxy() { @@ -76,32 +80,28 @@ class RpcServiceAdapter implements InvocationHandler { @Override @SuppressWarnings("checkstyle:hiddenField") - public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { - + public Object invoke(final Object proxy, final Method method, final Object[] args) { final RpcInvocationStrategy rpc = rpcNames.get(method); if (rpc != null) { - if (method.getParameterTypes().length == 0) { - return rpc.invokeEmpty(); - } if (args.length != 1) { throw new IllegalArgumentException("Input must be provided."); } - return rpc.invoke((DataObject) args[0]); + return rpc.invoke((DataObject) requireNonNull(args[0])); } switch (method.getName()) { case "toString": - if (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": - if (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": - if (method.getReturnType().equals(boolean.class) && method.getParameterTypes().length == 1 + if (method.getReturnType().equals(boolean.class) && method.getParameterCount() == 1 && method.getParameterTypes()[0] == Object.class) { return proxy == args[0]; } @@ -114,97 +114,87 @@ class RpcServiceAdapter implements InvocationHandler { } private abstract class RpcInvocationStrategy { + private final @NonNull NodeIdentifier inputIdentifier; + private final @NonNull Absolute outputPath; - private final SchemaPath rpcName; - - protected RpcInvocationStrategy(final SchemaPath path) { - rpcName = path; + RpcInvocationStrategy(final QName rpcName) { + final var namespace = rpcName.getModule(); + outputPath = Absolute.of(rpcName, YangConstants.operationOutputQName(namespace).intern()).intern(); + inputIdentifier = NodeIdentifier.create(YangConstants.operationInputQName(namespace.intern())); } final ListenableFuture> invoke(final DataObject input) { - return invoke0(rpcName, serialize(input)); + return invoke0(serialize(input)); } abstract ContainerNode serialize(DataObject input); - final ListenableFuture> invokeEmpty() { - return invoke0(rpcName, null); + final @NonNull NodeIdentifier inputIdentifier() { + return inputIdentifier; } - final SchemaPath getRpcName() { - return rpcName; - } - - ListenableFuture> invoke0(final SchemaPath schemaPath, final ContainerNode input) { - final ListenableFuture result = delegate.invokeRpc(schemaPath, input); - if (result instanceof BindingRpcFutureAware) { + private ListenableFuture> invoke0(final ContainerNode input) { + final ListenableFuture result = + delegate.invokeRpc(outputPath.firstNodeIdentifier(), input); + if (ENABLE_CODEC_SHORTCUT && result instanceof BindingRpcFutureAware) { return ((BindingRpcFutureAware) result).getBindingFuture(); } - return transformFuture(schemaPath, result, codec.getCodecFactory()); + return transformFuture(result, adapterContext.currentSerializer()); } - private ListenableFuture> transformFuture(final SchemaPath rpc, - final ListenableFuture domFuture, final BindingNormalizedNodeCodecRegistry resultCodec) { + private ListenableFuture> transformFuture(final ListenableFuture domFuture, + final BindingNormalizedNodeSerializer resultCodec) { return Futures.transform(domFuture, input -> { - final NormalizedNode domData = input.getResult(); + 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); + bindingResult = resultCodec.fromNormalizedNodeRpcData(outputPath, (ContainerNode) domData); } else { bindingResult = null; } - // DOMRpcResult does not have a notion of success, hence we have to reverse-engineer it by looking - // at reported errors and checking whether they are just warnings. - final Collection errors = input.getErrors(); - return RpcResult.class.cast(RpcResultBuilder.status(errors.stream() - .noneMatch(error -> error.getSeverity() == ErrorSeverity.ERROR)) - .withResult(bindingResult).withRpcErrors(errors).build()); + return RpcResultUtil.rpcResultFromDOM(input.getErrors(), bindingResult); }, MoreExecutors.directExecutor()); } } private final class NonRoutedStrategy extends RpcInvocationStrategy { - - protected NonRoutedStrategy(final SchemaPath path) { - super(path); + NonRoutedStrategy(final QName rpcName) { + super(rpcName); } @Override ContainerNode serialize(final DataObject input) { - return LazySerializedContainerNode.create(getRpcName(), input, codec.getCodecRegistry()); + return LazySerializedContainerNode.create(inputIdentifier(), input, adapterContext.currentSerializer()); } - } private final class RoutedStrategy extends RpcInvocationStrategy { - private final ContextReferenceExtractor refExtractor; private final NodeIdentifier contextName; - protected RoutedStrategy(final SchemaPath path, final Method rpcMethod, final QName leafName) { - super(path); + RoutedStrategy(final QName rpcName, final Method rpcMethod, final QName leafName) { + super(rpcName); final Optional> maybeInputType = BindingReflections.resolveRpcInputClass(rpcMethod); - Preconditions.checkState(maybeInputType.isPresent(), "RPC method %s has no input", rpcMethod.getName()); + 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); + contextName = new NodeIdentifier(leafName); } @Override ContainerNode serialize(final DataObject input) { final InstanceIdentifier bindingII = refExtractor.extract(input); + final CurrentAdapterSerializer serializer = adapterContext.currentSerializer(); + if (bindingII != null) { - final YangInstanceIdentifier yangII = codec.toYangInstanceIdentifierCached(bindingII); + final YangInstanceIdentifier yangII = serializer.toCachedYangInstanceIdentifier(bindingII); final LeafNode contextRef = ImmutableNodes.leafNode(contextName, yangII); - return LazySerializedContainerNode.withContextRef(getRpcName(), input, contextRef, - codec.getCodecRegistry()); + return LazySerializedContainerNode.withContextRef(inputIdentifier(), input, contextRef, serializer); } - return LazySerializedContainerNode.create(getRpcName(), input, codec.getCodecRegistry()); + return LazySerializedContainerNode.create(inputIdentifier(), input, serializer); } }