From 0d133b38e4d0368ee9d15e39460440d044067228 Mon Sep 17 00:00:00 2001 From: Jie Han Date: Fri, 10 Aug 2018 08:58:11 +0800 Subject: [PATCH] Binding2 - Implement RpcActionProviderService Use inner class to simplify implemetation of adapter as there's only one method 'invoke' in Rpc or Action/ListAction, we then could take the implementation directly instead of initiating xxxInvoker for every adapter. Change-Id: Ide6247c4692aeb496d3bf85c918eef530a4e18cd Signed-off-by: Jie Han --- .../javav2/api/RpcActionProviderService.java | 40 +++-- ...dingDOMOperationImplementationAdapter.java | 108 ------------- ...ingDOMOperationProviderServiceAdapter.java | 152 +++++++++++++++--- .../operation/LazyDOMActionResultFuture.java | 131 +++++++++++++++ ...uture.java => LazyDOMRpcResultFuture.java} | 8 +- .../impl/operation/RpcServiceAdapter.java | 4 +- ...indingDOMOperationAdapterRegistration.java | 7 +- .../dom/adapter/test/BindingTestContext.java | 8 +- .../impl/BindingToNormalizedNodeCodec.java | 59 ++++--- .../generator/context/ModuleContext.java | 5 +- .../context/BindingRuntimeContext.java | 15 +- .../reflection/BindingReflections.java | 2 +- 12 files changed, 346 insertions(+), 193 deletions(-) delete mode 100644 binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationImplementationAdapter.java create mode 100644 binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMActionResultFuture.java rename binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/{LazyDOMOperationResultFuture.java => LazyDOMRpcResultFuture.java} (93%) diff --git a/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionProviderService.java b/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionProviderService.java index 8a2def4df7..577b21ce4a 100644 --- a/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionProviderService.java +++ b/binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionProviderService.java @@ -9,14 +9,13 @@ package org.opendaylight.mdsal.binding.javav2.api; import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableSet; import java.util.Set; import org.opendaylight.mdsal.binding.javav2.spec.base.Action; import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier; -import org.opendaylight.mdsal.binding.javav2.spec.base.KeyedInstanceIdentifier; -import org.opendaylight.mdsal.binding.javav2.spec.base.ListAction; import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; -import org.opendaylight.yangtools.concepts.Identifier; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.yangtools.concepts.ObjectRegistration; /** @@ -50,10 +49,12 @@ public interface RpcActionProviderService { T implementation, Set> paths); /** - * Returns class representing registration of Action. - * @param type Action binding generated interface - * @param parent parent node for Action connected to - * @param implementation Action binding implementation + * Returns class representing registration of Action/ListAction. + * @param type Action/ListAction binding generated interface + * @param implementation Action/ListAction binding implementation + * @param datastore {@link LogicalDatastoreType} on which the implementation operates + * @param validNodes Set of nodes this implementation is constrained to, empty if this implementation can handle + * any target node. * @param service class type * @param

parent type * @param service implementation type @@ -61,20 +62,15 @@ public interface RpcActionProviderService { */ , T extends S, P extends TreeNode> ObjectRegistration registerActionImplementation( - Class type, InstanceIdentifier

parent, T implementation); + Class type, T implementation, LogicalDatastoreType datastore, Set> validNodes); - /** - * Returns class representing registration of ListAction. - * @param type ListAction binding generated interface - * @param parent parent node for ListAction connected to - * @param implementation ListAction binding implementation - * @param service class type - * @param

parent type - * @param key type - * @param service implementation type - * @return returns class representing a ListAction registration - */ - , T extends S, P extends TreeNode, K extends Identifier> - ObjectRegistration registerListActionImplementation(Class type, KeyedInstanceIdentifier parent, - T implementation); + default , T extends S> ObjectRegistration + registerActionImplementation(Class type, T implementation, LogicalDatastoreType datastore) { + return registerActionImplementation(type, implementation, datastore, ImmutableSet.of()); + } + + default , T extends S> ObjectRegistration + registerActionImplementation(Class type, T implementation) { + return registerActionImplementation(type, implementation, LogicalDatastoreType.OPERATIONAL, ImmutableSet.of()); + } } diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationImplementationAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationImplementationAdapter.java deleted file mode 100644 index fc395752b5..0000000000 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationImplementationAdapter.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2017 Pantheon Technologies 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, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.operation; - -import com.google.common.annotations.Beta; -import com.google.common.base.Preconditions; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.util.concurrent.FluentFuture; -import com.google.common.util.concurrent.JdkFutureAdapters; -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.ExecutionException; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.operation.invoker.OperationServiceInvoker; -import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingNormalizedNodeCodecRegistry; -import org.opendaylight.mdsal.binding.javav2.dom.codec.serialized.LazySerializedContainerNode; -import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; -import org.opendaylight.mdsal.binding.javav2.spec.base.Operation; -import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; -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.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; - -/** - * Operation implementation adapter. - */ -@Beta -public class BindingDOMOperationImplementationAdapter implements DOMRpcImplementation { - - private static final Cache, OperationServiceInvoker> SERVICE_INVOKERS = - CacheBuilder.newBuilder().weakKeys().build(); - // Default implementations are 0, we need to perform some translation, hence we have a slightly higher - // cost - private static final int COST = 1; - - private final BindingNormalizedNodeCodecRegistry codec; - private final OperationServiceInvoker invoker; - private final Operation delegate; - private final QName inputQname; - - BindingDOMOperationImplementationAdapter(final BindingNormalizedNodeCodecRegistry codec, - final Class type, final Map localNameToMethod, final T delegate) { - try { - this.invoker = SERVICE_INVOKERS.get(type, () -> { - final Map map = new HashMap<>(); - for (final Entry e : localNameToMethod.entrySet()) { - map.put(e.getKey().getLastComponent(), e.getValue()); - } - - return OperationServiceInvoker.from(map); - }); - } catch (final ExecutionException e) { - throw new IllegalArgumentException("Failed to create invokers for type " + type, e); - } - - this.codec = Preconditions.checkNotNull(codec); - this.delegate = Preconditions.checkNotNull(delegate); - inputQname = QName.create(BindingReflections.getQNameModule(type), "input").intern(); - } - - @SuppressWarnings("deprecation") - @Nonnull - @Override - public FluentFuture invokeRpc(@Nonnull final DOMRpcIdentifier rpc, - @Nullable final NormalizedNode input) { - - final SchemaPath schemaPath = rpc.getType(); - final TreeNode bindingInput = input != null ? deserialize(rpc.getType(), input) : null; - final ListenableFuture> bindingResult = invoke(schemaPath, bindingInput); - return transformResult(bindingResult); - } - - @Override - public long invocationCost() { - return COST; - } - - private TreeNode deserialize(final SchemaPath rpcPath, final NormalizedNode input) { - if (input instanceof LazySerializedContainerNode) { - return ((LazySerializedContainerNode) input).bindingData(); - } - final SchemaPath inputSchemaPath = rpcPath.createChild(inputQname); - return codec.fromNormalizedNodeOperationData(inputSchemaPath, (ContainerNode) input); - } - - private ListenableFuture> invoke(final SchemaPath schemaPath, final TreeNode input) { - return JdkFutureAdapters.listenInPoolThread(invoker.invoke(delegate, schemaPath.getLastComponent(), input)); - } - - private FluentFuture transformResult(final ListenableFuture> bindingResult) { - return LazyDOMOperationResultFuture.create(codec, bindingResult); - } -} diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java index 3f11a114af..dd70882149 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java @@ -8,28 +8,53 @@ package org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.operation; import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; -import java.lang.reflect.Method; +import com.google.common.util.concurrent.FluentFuture; +import com.google.common.util.concurrent.SettableFuture; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.Map; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.mdsal.binding.javav2.api.DataTreeIdentifier; import org.opendaylight.mdsal.binding.javav2.api.RpcActionProviderService; +import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.operation.BindingDOMOperationProviderServiceAdapter.AbstractImplAdapter.ActionAdapter; +import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.operation.BindingDOMOperationProviderServiceAdapter.AbstractImplAdapter.RpcAdapter; import org.opendaylight.mdsal.binding.javav2.dom.adapter.registration.BindingDOMOperationAdapterRegistration; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingNormalizedNodeCodecRegistry; import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec; +import org.opendaylight.mdsal.binding.javav2.dom.codec.serialized.LazySerializedContainerNode; +import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; import org.opendaylight.mdsal.binding.javav2.spec.base.Action; +import org.opendaylight.mdsal.binding.javav2.spec.base.Input; import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier; -import org.opendaylight.mdsal.binding.javav2.spec.base.KeyedInstanceIdentifier; -import org.opendaylight.mdsal.binding.javav2.spec.base.ListAction; +import org.opendaylight.mdsal.binding.javav2.spec.base.Operation; +import org.opendaylight.mdsal.binding.javav2.spec.base.Output; import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; +import org.opendaylight.mdsal.binding.javav2.spec.base.RpcCallback; import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.dom.api.DOMActionImplementation; +import org.opendaylight.mdsal.dom.api.DOMActionInstance; +import org.opendaylight.mdsal.dom.api.DOMActionProviderService; +import org.opendaylight.mdsal.dom.api.DOMActionResult; +import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier; +import org.opendaylight.mdsal.dom.api.DOMRpcImplementation; import org.opendaylight.mdsal.dom.api.DOMRpcImplementationRegistration; import org.opendaylight.mdsal.dom.api.DOMRpcProviderService; -import org.opendaylight.yangtools.concepts.Identifier; +import org.opendaylight.mdsal.dom.api.DOMRpcResult; import org.opendaylight.yangtools.concepts.ObjectRegistration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +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; //FIXME missing support of Action operation (dependence on support of Yang 1.1 in DOM part of MD-SAL) @@ -42,11 +67,13 @@ public class BindingDOMOperationProviderServiceAdapter implements RpcActionProvi private static final Set GLOBAL = ImmutableSet.of(YangInstanceIdentifier.builder().build()); private final BindingToNormalizedNodeCodec codec; private final DOMRpcProviderService domRpcRegistry; + private final DOMActionProviderService domActionRegistry; public BindingDOMOperationProviderServiceAdapter(final DOMRpcProviderService domRpcRegistry, - final BindingToNormalizedNodeCodec codec) { + final DOMActionProviderService domActionRegistry, final BindingToNormalizedNodeCodec codec) { this.codec = codec; this.domRpcRegistry = domRpcRegistry; + this.domActionRegistry = domActionRegistry; } @Override @@ -63,22 +90,18 @@ public class BindingDOMOperationProviderServiceAdapter implements RpcActionProvi private , T extends S> ObjectRegistration register(final Class type, final T implementation, final Collection rpcContextPaths) { - final Map rpcs = codec.getRPCMethodToSchemaPath(type).inverse(); - - final BindingDOMOperationImplementationAdapter adapter = - new BindingDOMOperationImplementationAdapter(codec.getCodecRegistry(), type, rpcs, implementation); - final Set domRpcs = createDomRpcIdentifiers(rpcs.keySet(), rpcContextPaths); - final DOMRpcImplementationRegistration domReg = domRpcRegistry.registerRpcImplementation(adapter, domRpcs); + final SchemaPath path = codec.getRpcPath(type); + final Set domRpcs = createDomRpcIdentifiers(path, rpcContextPaths); + final DOMRpcImplementationRegistration domReg = domRpcRegistry.registerRpcImplementation( + new RpcAdapter(codec.getCodecRegistry(), type, implementation), domRpcs); return new BindingDOMOperationAdapterRegistration<>(implementation, domReg); } - private static Set createDomRpcIdentifiers(final Set rpcs, + private static Set createDomRpcIdentifiers(final SchemaPath rpc, final Collection paths) { final Set ret = new HashSet<>(); for (final YangInstanceIdentifier path : paths) { - for (final SchemaPath rpc : rpcs) { - ret.add(DOMRpcIdentifier.create(rpc, path)); - } + ret.add(DOMRpcIdentifier.create(rpc, path)); } return ret; } @@ -93,17 +116,94 @@ public class BindingDOMOperationProviderServiceAdapter implements RpcActionProvi @Override public , T extends S, P extends TreeNode> ObjectRegistration - registerActionImplementation(final Class type, final InstanceIdentifier

parent, - final T implementation) { - // TODO implement after improve DOM part of MD-SAL for support of Yang 1.1 - throw new UnsupportedOperationException(); + registerActionImplementation(final Class type, final T implementation, + final LogicalDatastoreType datastore, final Set> validNodes) { + final SchemaPath path = codec.getActionPath(type); + final ObjectRegistration domReg = domActionRegistry.registerActionImplementation( + new ActionAdapter(codec.getCodecRegistry(), type, implementation), + DOMActionInstance.of(path, codec.toDOMDataTreeIdentifiers(validNodes))); + return new BindingDOMOperationAdapterRegistration<>(implementation, domReg); } - @Override - public , T extends S, P extends TreeNode, K extends Identifier> - ObjectRegistration registerListActionImplementation(final Class type, - final KeyedInstanceIdentifier parent, final T implementation) { - // TODO implement after improve DOM part of MD-SAL for support of Yang 1.1 - throw new UnsupportedOperationException(); + public abstract static class AbstractImplAdapter { + protected final BindingNormalizedNodeCodecRegistry codec; + protected final D delegate; + private final QName inputQname; + + AbstractImplAdapter(final BindingNormalizedNodeCodecRegistry codec, final Class clazz, + final D delegate) { + this.codec = Preconditions.checkNotNull(codec); + this.delegate = Preconditions.checkNotNull(delegate); + inputQname = QName.create(BindingReflections.getQNameModule(clazz), "input").intern(); + } + + TreeNode deserialize(final SchemaPath path, final NormalizedNode input) { + if (input instanceof LazySerializedContainerNode) { + return ((LazySerializedContainerNode) input).bindingData(); + } + final SchemaPath inputSchemaPath = path.createChild(inputQname); + return codec.fromNormalizedNodeOperationData(inputSchemaPath, (ContainerNode) input); + } + + public static final class RpcAdapter extends AbstractImplAdapter implements DOMRpcImplementation { + + RpcAdapter(BindingNormalizedNodeCodecRegistry codec, Class clazz, + Rpc delegate) { + super(codec, clazz, delegate); + } + + @SuppressWarnings("checkstyle:illegalCatch, unchecked") + @Nonnull + @Override + public FluentFuture invokeRpc(@Nonnull final DOMRpcIdentifier rpc, + @Nullable final NormalizedNode input) { + final TreeNode bindingInput = input != null ? deserialize(rpc.getType(), input) : null; + final SettableFuture> bindingResult = SettableFuture.create(); + CompletableFuture.runAsync(() -> delegate.invoke((Input) bindingInput, + new RpcCallback>() { + public void onSuccess(Output output) { + bindingResult.set(RpcResultBuilder.success(output).build()); + } + + public void onFailure(Throwable error) { + bindingResult.set(RpcResultBuilder.failed().withError(ErrorType.APPLICATION, + error.getMessage()).build()); + } + }) + ); + return LazyDOMRpcResultFuture.create(codec,bindingResult); + } + } + + public static final class ActionAdapter extends AbstractImplAdapter + implements DOMActionImplementation { + + ActionAdapter(BindingNormalizedNodeCodecRegistry codec, Class clazz, + Action delegate) { + super(codec, clazz, delegate); + } + + @SuppressWarnings("checkstyle:illegalCatch, unchecked") + @Nonnull + public FluentFuture invokeAction(SchemaPath type, DOMDataTreeIdentifier path, + ContainerNode input) { + final TreeNode bindingInput = input != null ? deserialize(type, input) : null; + final SettableFuture> bindingResult = SettableFuture.create(); + CompletableFuture.runAsync(() -> delegate.invoke((Input) bindingInput, + codec.fromYangInstanceIdentifier(path.getRootIdentifier()), + new RpcCallback>() { + public void onSuccess(Output output) { + bindingResult.set(RpcResultBuilder.success(output).build()); + } + + public void onFailure(Throwable error) { + bindingResult.set(RpcResultBuilder.failed().withError(ErrorType.APPLICATION, + error.getMessage()).build()); + } + }) + ); + return LazyDOMActionResultFuture.create(codec, bindingResult); + } + } } } diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMActionResultFuture.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMActionResultFuture.java new file mode 100644 index 0000000000..54c1748379 --- /dev/null +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMActionResultFuture.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017 Pantheon Technologies 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, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.operation; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.util.concurrent.AbstractFuture; +import com.google.common.util.concurrent.FluentFuture; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import javax.annotation.Nonnull; +import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingNormalizedNodeCodecRegistry; +import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; +import org.opendaylight.mdsal.dom.api.DOMActionException; +import org.opendaylight.mdsal.dom.api.DOMActionNotAvailableException; +import org.opendaylight.mdsal.dom.api.DOMActionResult; +import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult; +import org.opendaylight.yangtools.util.concurrent.ExceptionMapper; +import org.opendaylight.yangtools.yang.binding.DataContainer; +import org.opendaylight.yangtools.yang.common.RpcResult; + +/** + * DOM operation result from Binding. + */ +@Beta +final class LazyDOMActionResultFuture extends AbstractFuture { + private static final ExceptionMapper DOM_ACTION_EX_MAPPER = + new ExceptionMapper("action", DOMActionException.class) { + @Override + protected DOMActionException newWithCause(String message, Throwable cause) { + return cause instanceof DOMActionException ? (DOMActionException)cause + : new DOMActionNotAvailableException("Action failed", cause); + } + }; + + private final ListenableFuture> bindingFuture; + private final BindingNormalizedNodeCodecRegistry codec; + private volatile DOMActionResult result; + + private LazyDOMActionResultFuture(final ListenableFuture> delegate, + final BindingNormalizedNodeCodecRegistry codec) { + this.bindingFuture = Preconditions.checkNotNull(delegate, "delegate"); + this.codec = Preconditions.checkNotNull(codec, "codec"); + } + + static FluentFuture create(final BindingNormalizedNodeCodecRegistry codec, + final ListenableFuture> bindingResult) { + return new LazyDOMActionResultFuture(bindingResult, codec); + } + + ListenableFuture> getBindingFuture() { + return bindingFuture; + } + + @Override + public boolean cancel(final boolean mayInterruptIfRunning) { + return bindingFuture.cancel(mayInterruptIfRunning); + } + + @Override + public void addListener(@Nonnull final Runnable listener, @Nonnull final Executor executor) { + bindingFuture.addListener(listener, executor); + } + + @Override + public DOMActionResult get() throws InterruptedException, ExecutionException { + if (result != null) { + return result; + } + + try { + return transformIfNecessary(bindingFuture.get()); + } catch (ExecutionException e) { + throw new ExecutionException(e.getMessage(), DOM_ACTION_EX_MAPPER.apply(e)); + } + } + + @Override + public DOMActionResult get(@Nonnull final long timeout, final TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + if (result != null) { + return result; + } + + try { + return transformIfNecessary(bindingFuture.get(timeout, unit)); + } catch (ExecutionException e) { + throw new ExecutionException(e.getMessage(), DOM_ACTION_EX_MAPPER.apply(e)); + } + } + + @Override + public boolean isCancelled() { + return bindingFuture.isCancelled(); + } + + @Override + public boolean isDone() { + return bindingFuture.isDone(); + } + + private synchronized DOMActionResult transformIfNecessary(final RpcResult input) { + if (result == null) { + result = transform(input); + } + return result; + } + + private DOMActionResult transform(final RpcResult input) { + if (input.isSuccessful()) { + final Object inputData = input.getResult(); + if (inputData instanceof DataContainer) { + return new SimpleDOMActionResult(codec.toNormalizedNodeOperationData((TreeNode) inputData), + ImmutableList.of()); + } else { + return new SimpleDOMActionResult(ImmutableList.of()); + } + } + return new SimpleDOMActionResult(input.getErrors()); + } + +} diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMOperationResultFuture.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMRpcResultFuture.java similarity index 93% rename from binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMOperationResultFuture.java rename to binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMRpcResultFuture.java index 946226a9fe..0df3547845 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMOperationResultFuture.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMRpcResultFuture.java @@ -32,7 +32,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; * DOM operation result from Binding. */ @Beta -final class LazyDOMOperationResultFuture extends AbstractFuture { +final class LazyDOMRpcResultFuture extends AbstractFuture { private static final ExceptionMapper DOM_RPC_EX_MAPPER = new ExceptionMapper("rpc", DOMRpcException.class) { @Override @@ -46,15 +46,15 @@ final class LazyDOMOperationResultFuture extends AbstractFuture { private final BindingNormalizedNodeCodecRegistry codec; private volatile DOMRpcResult result; - private LazyDOMOperationResultFuture(final ListenableFuture> delegate, - final BindingNormalizedNodeCodecRegistry codec) { + private LazyDOMRpcResultFuture(final ListenableFuture> delegate, + final BindingNormalizedNodeCodecRegistry codec) { this.bindingFuture = Preconditions.checkNotNull(delegate, "delegate"); this.codec = Preconditions.checkNotNull(codec, "codec"); } static FluentFuture create(final BindingNormalizedNodeCodecRegistry codec, final ListenableFuture> bindingResult) { - return new LazyDOMOperationResultFuture(bindingResult, codec); + return new LazyDOMRpcResultFuture(bindingResult, codec); } ListenableFuture> getBindingFuture() { diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java index c9653a5920..c30d2c8ebb 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java @@ -154,8 +154,8 @@ class RpcServiceAdapter implements InvocationHandler { private ListenableFuture> invoke0(final SchemaPath schemaPath, final NormalizedNode input) { final ListenableFuture listenInPoolThread = JdkFutureAdapters.listenInPoolThread(delegate.invokeRpc(schemaPath, input)); - if (listenInPoolThread instanceof LazyDOMOperationResultFuture) { - return ((LazyDOMOperationResultFuture) listenInPoolThread).getBindingFuture(); + if (listenInPoolThread instanceof LazyDOMRpcResultFuture) { + return ((LazyDOMRpcResultFuture) listenInPoolThread).getBindingFuture(); } return transformFuture(schemaPath, listenInPoolThread, codec.getCodecFactory()); diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/registration/BindingDOMOperationAdapterRegistration.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/registration/BindingDOMOperationAdapterRegistration.java index f30a550d00..1f6f202358 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/registration/BindingDOMOperationAdapterRegistration.java +++ b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/registration/BindingDOMOperationAdapterRegistration.java @@ -9,8 +9,8 @@ package org.opendaylight.mdsal.binding.javav2.dom.adapter.registration; import com.google.common.annotations.Beta; import org.opendaylight.mdsal.binding.javav2.spec.base.Operation; -import org.opendaylight.mdsal.dom.api.DOMRpcImplementationRegistration; import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.concepts.ObjectRegistration; /** * Registration of Binding - DOM Operation adapter. @@ -21,10 +21,9 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; @Beta public class BindingDOMOperationAdapterRegistration extends AbstractObjectRegistration { - private final DOMRpcImplementationRegistration reg; + private final ObjectRegistration reg; - // FIXME : DOM part doesn't work with Yang 1.1 - Action registration isn't implemented yet. - public BindingDOMOperationAdapterRegistration(final T instance, final DOMRpcImplementationRegistration reg) { + public BindingDOMOperationAdapterRegistration(final T instance, final ObjectRegistration reg) { super(instance); this.reg = reg; } diff --git a/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/test/BindingTestContext.java b/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/test/BindingTestContext.java index dcf9d8e241..1e42a9a1d5 100644 --- a/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/test/BindingTestContext.java +++ b/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/test/BindingTestContext.java @@ -36,6 +36,7 @@ import org.opendaylight.mdsal.binding.javav2.runtime.javassist.JavassistUtils; import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; import org.opendaylight.mdsal.binding.javav2.spec.runtime.YangModuleInfo; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.dom.api.DOMActionProviderService; import org.opendaylight.mdsal.dom.api.DOMDataBroker; import org.opendaylight.mdsal.dom.api.DOMMountPointService; import org.opendaylight.mdsal.dom.api.DOMNotificationPublishService; @@ -119,7 +120,8 @@ public class BindingTestContext implements AutoCloseable { checkState(executor != null, "Executor needs to be set"); baConsumerRpc = new BindingDOMOperationServiceAdapter(getDomRpcInvoker(), codec); - baProviderRpc = new BindingDOMOperationProviderServiceAdapter(getDomRpcRegistry(), codec); + baProviderRpc = new BindingDOMOperationProviderServiceAdapter(getDomRpcRegistry(), getDomActionRegistry(), + codec); final MountPointService mountService = new BindingDOMMountPointServiceAdapter(biMountImpl, codec); } @@ -198,6 +200,10 @@ public class BindingTestContext implements AutoCloseable { return domRouter.getRpcProviderService(); } + public DOMActionProviderService getDomActionRegistry() { + return domRouter.getActionProviderService(); + } + public DOMRpcService getDomRpcInvoker() { return domRouter.getRpcService(); } diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java index b86ee27815..2c7cccdbde 100644 --- a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java +++ b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java @@ -7,6 +7,8 @@ */ package org.opendaylight.mdsal.binding.javav2.dom.codec.impl; +import static com.google.common.base.Preconditions.checkArgument; + import com.google.common.annotations.Beta; import com.google.common.base.Preconditions; import com.google.common.cache.CacheBuilder; @@ -33,8 +35,10 @@ import org.opendaylight.mdsal.binding.javav2.dom.codec.api.serializer.BindingNor import org.opendaylight.mdsal.binding.javav2.generator.impl.GeneratedClassLoadingStrategy; import org.opendaylight.mdsal.binding.javav2.runtime.context.BindingRuntimeContext; import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; +import org.opendaylight.mdsal.binding.javav2.spec.base.Action; import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier; import org.opendaylight.mdsal.binding.javav2.spec.base.Notification; +import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; import org.opendaylight.mdsal.binding.javav2.spec.base.TreeArgument; import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode; import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; @@ -320,6 +324,7 @@ public final class BindingToNormalizedNodeCodec * - RPC as binding object * @return map of method with path of specific RPC */ + @Deprecated public ImmutableBiMap getRPCMethodToSchemaPath(final Class key) { final Module module = getModuleBlocking(key); final ImmutableBiMap.Builder ret = ImmutableBiMap.builder(); @@ -335,31 +340,30 @@ public final class BindingToNormalizedNodeCodec } /** - * Resolve method with path of specific Action as binding object. + * Get Action schema path. * - * @param key - * - action as binding object - * @return map of method with path of specific action + * @param type + * - Action implementation class type + * @return schema path of Action */ - public ImmutableBiMap getActionMethodToSchemaPath(final Class key) { - final Module module = getModuleBlocking(key); - - final ImmutableBiMap.Builder ret = ImmutableBiMap.builder(); - try { - for (final ActionDefinition actionDefinition : runtimeContext.getSchemaContext().getActions()) { - final QName qName = actionDefinition.getQName(); - if (qName.getModule().equals(module.getQNameModule())) { - final Method method = runtimeContext.findOperationMethod(key, actionDefinition); - ret.put(method, actionDefinition.getPath()); - } - } - } catch (final NoSuchMethodException e) { - throw new IllegalStateException("Action defined in model does not have representation in generated class.", - e); - } - return ret.build(); + public SchemaPath getActionPath(final Class> type) { + final ActionDefinition schema = runtimeContext.getActionDefinition(type); + checkArgument(schema != null, "Failed to find schema for %s", type); + return schema.getPath(); } + /** + * Get RPC schema path. + * + * @param type + * - RPC implementation class type + * @return schema path of RPC + */ + public SchemaPath getRpcPath(final Class> type) { + final RpcDefinition schema = runtimeContext.getRpcDefinition(type); + checkArgument(schema != null, "Failed to find schema for %s", type); + return schema.getPath(); + } /** * Resolve method with definition of specific RPC as binding object. @@ -455,7 +459,7 @@ public final class BindingToNormalizedNodeCodec final BindingTreeCodec currentCodecTree = codecRegistry.getCodecContext(); final InstanceIdentifier bindingPath = codecRegistry.fromYangInstanceIdentifier(domIdentifier); - Preconditions.checkArgument(bindingPath != null); + checkArgument(bindingPath != null); /** * If we are able to deserialize YANG instance identifier, getSubtreeCodec must return non-null value. */ @@ -544,6 +548,17 @@ public final class BindingToNormalizedNodeCodec return ret; } + //FIXME: avoid the duplication of the function above. + public

Set + toDOMDataTreeIdentifiers(final Set> subtrees) { + final Set ret = new HashSet<>(subtrees.size()); + + for (final DataTreeIdentifier subtree : subtrees) { + ret.add(toDOMDataTreeIdentifier(subtree)); + } + return ret; + } + /** * Create new DOM data tree identifier from Binding data tree identifier. * diff --git a/binding2/mdsal-binding2-generator-api/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/context/ModuleContext.java b/binding2/mdsal-binding2-generator-api/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/context/ModuleContext.java index 9d730b642d..cf3a6adaeb 100644 --- a/binding2/mdsal-binding2-generator-api/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/context/ModuleContext.java +++ b/binding2/mdsal-binding2-generator-api/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/context/ModuleContext.java @@ -33,6 +33,7 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode; import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus; import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; @@ -55,7 +56,7 @@ public final class ModuleContext { private final List augmentations = new ArrayList<>(); private final Multimap typeToAugmentations = HashMultimap.create(); private final BiMap targetToAugmentation = HashBiMap.create(); - private final Map typeToSchema = new HashMap<>(); + private final Map typeToSchema = new HashMap<>(); private final Multimap choiceToCases = HashMultimap.create(); private final BiMap caseTypeToSchema = HashBiMap.create(); private final Map innerTypes = new HashMap<>(); @@ -207,7 +208,7 @@ public final class ModuleContext { * * @return Mapping from type to corresponding schema */ - public Map getTypeToSchema() { + public Map getTypeToSchema() { return Collections.unmodifiableMap(this.typeToSchema); } diff --git a/binding2/mdsal-binding2-runtime/src/main/java/org/opendaylight/mdsal/binding/javav2/runtime/context/BindingRuntimeContext.java b/binding2/mdsal-binding2-runtime/src/main/java/org/opendaylight/mdsal/binding/javav2/runtime/context/BindingRuntimeContext.java index 3a05104cba..868a934121 100755 --- a/binding2/mdsal-binding2-runtime/src/main/java/org/opendaylight/mdsal/binding/javav2/runtime/context/BindingRuntimeContext.java +++ b/binding2/mdsal-binding2-runtime/src/main/java/org/opendaylight/mdsal/binding/javav2/runtime/context/BindingRuntimeContext.java @@ -41,10 +41,13 @@ import org.opendaylight.mdsal.binding.javav2.model.api.Type; import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder; import org.opendaylight.mdsal.binding.javav2.runtime.context.util.BindingSchemaContextUtils; import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections; +import org.opendaylight.mdsal.binding.javav2.spec.base.Action; +import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc; import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentation; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; +import org.opendaylight.yangtools.yang.model.api.ActionDefinition; import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode; import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode; @@ -52,8 +55,10 @@ import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.OperationDefinition; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; @@ -92,7 +97,7 @@ public class BindingRuntimeContext implements Immutable { private final Multimap augmentationToSchemas = HashMultimap.create(); private final BiMap targetToAugmentation = HashBiMap.create(); - private final BiMap typeToDefiningSchema = HashBiMap.create(); + private final BiMap typeToDefiningSchema = HashBiMap.create(); private final Multimap choiceToCases = HashMultimap.create(); private final Map identities = new HashMap<>(); @@ -222,6 +227,14 @@ public class BindingRuntimeContext implements Immutable { return (DataSchemaNode) this.typeToDefiningSchema.get(referencedType(cls)); } + public RpcDefinition getRpcDefinition(final Class> cls) { + return (RpcDefinition) typeToDefiningSchema.get(referencedType(cls)); + } + + public ActionDefinition getActionDefinition(final Class> cls) { + return (ActionDefinition) typeToDefiningSchema.get(referencedType(cls)); + } + /** * Returns defining {@link AugmentationSchemaNode} of target for supplied class. * diff --git a/binding2/mdsal-binding2-runtime/src/main/java/org/opendaylight/mdsal/binding/javav2/runtime/reflection/BindingReflections.java b/binding2/mdsal-binding2-runtime/src/main/java/org/opendaylight/mdsal/binding/javav2/runtime/reflection/BindingReflections.java index bc12722843..b4b7c9f43d 100644 --- a/binding2/mdsal-binding2-runtime/src/main/java/org/opendaylight/mdsal/binding/javav2/runtime/reflection/BindingReflections.java +++ b/binding2/mdsal-binding2-runtime/src/main/java/org/opendaylight/mdsal/binding/javav2/runtime/reflection/BindingReflections.java @@ -284,7 +284,7 @@ public final class BindingReflections { checkArgument(cls != null); final String packageName = getModelRootPackageName(cls.getPackage()); final String potentialClassName = getModuleInfoClassName(packageName); - return ClassLoaderUtils.withClassLoader(cls.getClassLoader(), (Callable) () -> { + return ClassLoaderUtils.callWithClassLoader(cls.getClassLoader(), () -> { final Class moduleInfoClass = Thread.currentThread().getContextClassLoader().loadClass(potentialClassName); return (YangModuleInfo) moduleInfoClass.getMethod("getInstance").invoke(null); }); -- 2.36.6