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%2FBindingDOMRpcImplementationAdapter.java;h=5e995dc6ca01d15acb73581804dc1a5a7d17c874;hb=8980139ca24fe883ed2168cc4bbac8ee3c760158;hp=a7f4bb882525655adde8b7ea069002f0a952f34a;hpb=79f105509b5071563fe7c2a63414468ee582f0fa;p=mdsal.git diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMRpcImplementationAdapter.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMRpcImplementationAdapter.java index a7f4bb8825..5e995dc6ca 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMRpcImplementationAdapter.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingDOMRpcImplementationAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -7,87 +7,64 @@ */ package org.opendaylight.mdsal.binding.dom.adapter; -import com.google.common.base.Preconditions; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.util.concurrent.CheckedFuture; -import com.google.common.util.concurrent.JdkFutureAdapters; +import static com.google.common.base.Verify.verifyNotNull; +import static java.util.Objects.requireNonNull; +import static org.opendaylight.mdsal.binding.dom.adapter.StaticConfiguration.ENABLE_CODEC_SHORTCUT; + import com.google.common.util.concurrent.ListenableFuture; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import org.opendaylight.mdsal.dom.api.DOMRpcException; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingLazyContainerNode; import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier; import org.opendaylight.mdsal.dom.api.DOMRpcImplementation; import org.opendaylight.mdsal.dom.api.DOMRpcResult; -import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.RpcService; -import org.opendaylight.yangtools.yang.binding.util.BindingReflections; -import org.opendaylight.yangtools.yang.binding.util.RpcServiceInvoker; +import org.opendaylight.yangtools.yang.binding.Rpc; +import org.opendaylight.yangtools.yang.binding.RpcInput; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; -import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.model.api.SchemaPath; - -public class BindingDOMRpcImplementationAdapter implements DOMRpcImplementation { - - private static final Cache, RpcServiceInvoker> SERVICE_INVOKERS = CacheBuilder.newBuilder().weakKeys().build(); +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; - private final BindingNormalizedNodeCodecRegistry codec; - private final RpcServiceInvoker invoker; - private final RpcService delegate; - private final QName inputQname; +final class BindingDOMRpcImplementationAdapter implements DOMRpcImplementation { + private final @NonNull AdapterContext adapterContext; + private final @NonNull QName rpcName; + @SuppressWarnings("rawtypes") + private final @NonNull Rpc delegate; - public BindingDOMRpcImplementationAdapter(final BindingNormalizedNodeCodecRegistry codec, final Class type, final Map localNameToMethod, final T delegate) { - try { - this.invoker = SERVICE_INVOKERS.get(type, new Callable() { - @Override - public RpcServiceInvoker call() { - final Map map = new HashMap<>(); - for (Entry e : localNameToMethod.entrySet()) { - map.put(e.getKey().getLastComponent(), e.getValue()); - } - - return RpcServiceInvoker.from(map); - } - }); - } catch (ExecutionException e) { - throw new IllegalArgumentException("Failed to create invokers for type " + type, e); - } + BindingDOMRpcImplementationAdapter(final AdapterContext adapterContext, final QName rpcName, + final Rpc delegate) { + this.adapterContext = requireNonNull(adapterContext); + this.rpcName = requireNonNull(rpcName); + this.delegate = requireNonNull(delegate); + } - this.codec = Preconditions.checkNotNull(codec); - this.delegate = Preconditions.checkNotNull(delegate); - inputQname = QName.create(BindingReflections.getQNameModule(type), "input").intern(); + @Override + public long invocationCost() { + // Default implementations are 0, we need to perform some translation, hence we have a slightly higher cost + return 1; } @Override - public CheckedFuture invokeRpc(final DOMRpcIdentifier rpc, final NormalizedNode input) { - final SchemaPath schemaPath = rpc.getType(); - final DataObject bindingInput = input != null ? deserilialize(rpc.getType(),input) : null; - final ListenableFuture> bindingResult = invoke(schemaPath,bindingInput); - return transformResult(schemaPath,bindingResult); + public ListenableFuture invokeRpc(final DOMRpcIdentifier rpc, final ContainerNode input) { + final var serializer = adapterContext.currentSerializer(); + @SuppressWarnings("unchecked") + final var future = delegate.invoke(deserialize(serializer, input)); + return LazyDOMRpcResultFuture.create(serializer, future); } - private DataObject deserilialize(final SchemaPath rpcPath, final NormalizedNode input) { - if (input instanceof LazySerializedContainerNode) { - return ((LazySerializedContainerNode) input).bindingData(); + private @NonNull RpcInput deserialize(final @NonNull CurrentAdapterSerializer serializer, + final @NonNull ContainerNode input) { + if (ENABLE_CODEC_SHORTCUT && input instanceof BindingLazyContainerNode lazy) { + return (RpcInput) lazy.getDataObject(); } - final SchemaPath inputSchemaPath = rpcPath.createChild(inputQname); - return codec.fromNormalizedNodeRpcData(inputSchemaPath, (ContainerNode) input); - } - private ListenableFuture> invoke(final SchemaPath schemaPath, final DataObject input) { - return JdkFutureAdapters.listenInPoolThread(invoker.invokeRpc(delegate, schemaPath.getLastComponent(), input)); - } + final var inputName = input.name().getNodeType(); + if (!"input".equals(inputName.getLocalName()) || !rpcName.getModule().equals(inputName.getModule())) { + throw new IllegalArgumentException("Unexpected RPC " + rpcName + " input " + input.prettyTree()); + } - private CheckedFuture transformResult(final SchemaPath schemaPath, - final ListenableFuture> bindingResult) { - return LazyDOMRpcResultFuture.create(codec, bindingResult); + // TODO: this is a bit inefficient: typically we get the same CurrentAdapterSerializer and the path is also + // constant, hence we should be able to cache this lookup and just have the appropriate + // BindingDataObjectCodecTreeNode and reuse it directly + // FIXME: should be a guaranteed return, as input is @NonNull + return verifyNotNull((RpcInput) serializer.fromNormalizedNodeRpcData(Absolute.of(rpcName, inputName), input)); } - }