Binding2 - Implement RpcActionProviderService 87/75087/8
authorJie Han <han.jie@zte.com.cn>
Fri, 10 Aug 2018 00:58:11 +0000 (08:58 +0800)
committerRobert Varga <nite@hq.sk>
Mon, 20 Aug 2018 08:07:42 +0000 (08:07 +0000)
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 <han.jie@zte.com.cn>
12 files changed:
binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionProviderService.java
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationImplementationAdapter.java [deleted file]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMActionResultFuture.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMRpcResultFuture.java [moved from binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMOperationResultFuture.java with 93% similarity]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/registration/BindingDOMOperationAdapterRegistration.java
binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/test/BindingTestContext.java
binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java
binding2/mdsal-binding2-generator-api/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/context/ModuleContext.java
binding2/mdsal-binding2-runtime/src/main/java/org/opendaylight/mdsal/binding/javav2/runtime/context/BindingRuntimeContext.java
binding2/mdsal-binding2-runtime/src/main/java/org/opendaylight/mdsal/binding/javav2/runtime/reflection/BindingReflections.java

index 8a2def4df76a573fd348672d36056ad8eb447fbf..577b21ce4a30711a1aff2aee013c6892b6adad36 100644 (file)
@@ -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<InstanceIdentifier<?>> 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 <S> service class type
      * @param <P> parent type
      * @param <T> service implementation type
@@ -61,20 +62,15 @@ public interface RpcActionProviderService {
      */
     <S extends Action<? extends TreeNode, ?, ?, ?>, T extends S, P extends TreeNode> ObjectRegistration<T>
             registerActionImplementation(
-        Class<S> type, InstanceIdentifier<P> parent, T implementation);
+        Class<S> type, T implementation, LogicalDatastoreType datastore, Set<DataTreeIdentifier<P>> 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 <S> service class type
-     * @param <P> parent type
-     * @param <K> key type
-     * @param <T> service implementation type
-     * @return returns class representing a ListAction registration
-     */
-    <S extends ListAction<? extends TreeNode, ?, ?, ?>, T extends S, P extends TreeNode, K extends Identifier>
-            ObjectRegistration<T> registerListActionImplementation(Class<S> type, KeyedInstanceIdentifier<P, K> parent,
-        T implementation);
+    default <S extends Action<? extends TreeNode, ?, ?, ?>, T extends S> ObjectRegistration<T>
+            registerActionImplementation(Class<S> type, T implementation, LogicalDatastoreType datastore) {
+        return registerActionImplementation(type, implementation, datastore, ImmutableSet.of());
+    }
+
+    default <S extends Action<? extends TreeNode, ?, ?, ?>, T extends S> ObjectRegistration<T>
+            registerActionImplementation(Class<S> 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 (file)
index fc39575..0000000
+++ /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<Class<? extends Operation>, 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;
-
-    <T extends Operation> BindingDOMOperationImplementationAdapter(final BindingNormalizedNodeCodecRegistry codec,
-            final Class<T> type, final Map<SchemaPath, Method> localNameToMethod, final T delegate) {
-        try {
-            this.invoker = SERVICE_INVOKERS.get(type, () -> {
-                final Map<QName, Method> map = new HashMap<>();
-                for (final Entry<SchemaPath, Method> 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<DOMRpcResult> 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<RpcResult<?>> 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<RpcResult<?>> invoke(final SchemaPath schemaPath, final TreeNode input) {
-        return JdkFutureAdapters.listenInPoolThread(invoker.invoke(delegate, schemaPath.getLastComponent(), input));
-    }
-
-    private FluentFuture<DOMRpcResult> transformResult(final ListenableFuture<RpcResult<?>> bindingResult) {
-        return LazyDOMOperationResultFuture.create(codec, bindingResult);
-    }
-}
index 3f11a114af6931a638fa1a47fb241f4cbefa4cc7..dd70882149c3a1e823c3a49941e7cbe720202b3e 100644 (file)
@@ -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<YangInstanceIdentifier> 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 <S extends Rpc<?, ?>, T extends S> ObjectRegistration<T> register(final Class<S> type,
             final T implementation, final Collection<YangInstanceIdentifier> rpcContextPaths) {
-        final Map<SchemaPath, Method> rpcs = codec.getRPCMethodToSchemaPath(type).inverse();
-
-        final BindingDOMOperationImplementationAdapter adapter =
-                new BindingDOMOperationImplementationAdapter(codec.getCodecRegistry(), type, rpcs, implementation);
-        final Set<DOMRpcIdentifier> domRpcs = createDomRpcIdentifiers(rpcs.keySet(), rpcContextPaths);
-        final DOMRpcImplementationRegistration<?> domReg = domRpcRegistry.registerRpcImplementation(adapter, domRpcs);
+        final SchemaPath path = codec.getRpcPath(type);
+        final Set<DOMRpcIdentifier> domRpcs = createDomRpcIdentifiers(path, rpcContextPaths);
+        final DOMRpcImplementationRegistration<?> domReg = domRpcRegistry.registerRpcImplementation(
+            new RpcAdapter(codec.getCodecRegistry(), type, implementation), domRpcs);
         return new BindingDOMOperationAdapterRegistration<>(implementation, domReg);
     }
 
-    private static Set<DOMRpcIdentifier> createDomRpcIdentifiers(final Set<SchemaPath> rpcs,
+    private static Set<DOMRpcIdentifier> createDomRpcIdentifiers(final SchemaPath rpc,
             final Collection<YangInstanceIdentifier> paths) {
         final Set<DOMRpcIdentifier> 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 <S extends Action<? extends TreeNode, ?, ?, ?>, T extends S, P extends TreeNode> ObjectRegistration<T>
-            registerActionImplementation(final Class<S> type, final InstanceIdentifier<P> 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<S> type, final T implementation,
+                final LogicalDatastoreType datastore, final Set<DataTreeIdentifier<P>> validNodes) {
+        final SchemaPath path = codec.getActionPath(type);
+        final ObjectRegistration<ActionAdapter> domReg = domActionRegistry.registerActionImplementation(
+            new ActionAdapter(codec.getCodecRegistry(), type, implementation),
+            DOMActionInstance.of(path, codec.toDOMDataTreeIdentifiers(validNodes)));
+        return new BindingDOMOperationAdapterRegistration<>(implementation, domReg);
     }
 
-    @Override
-    public <S extends ListAction<? extends TreeNode, ?, ?, ?>, T extends S, P extends TreeNode, K extends Identifier>
-            ObjectRegistration<T> registerListActionImplementation(final Class<S> type,
-        final KeyedInstanceIdentifier<P, K> 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<D> {
+        protected final BindingNormalizedNodeCodecRegistry codec;
+        protected final D delegate;
+        private final QName inputQname;
+
+        AbstractImplAdapter(final BindingNormalizedNodeCodecRegistry codec, final Class<? extends Operation> 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<Rpc> implements DOMRpcImplementation {
+
+            RpcAdapter(BindingNormalizedNodeCodecRegistry codec, Class<? extends Operation> clazz,
+                    Rpc<?, ?> delegate) {
+                super(codec, clazz, delegate);
+            }
+
+            @SuppressWarnings("checkstyle:illegalCatch, unchecked")
+            @Nonnull
+            @Override
+            public FluentFuture<DOMRpcResult> invokeRpc(@Nonnull final DOMRpcIdentifier rpc,
+                                                        @Nullable final NormalizedNode<?, ?> input) {
+                final TreeNode bindingInput = input != null ? deserialize(rpc.getType(), input) : null;
+                final SettableFuture<RpcResult<?>> bindingResult = SettableFuture.create();
+                CompletableFuture.runAsync(() -> delegate.invoke((Input<?>) bindingInput,
+                    new RpcCallback<Output<?>>() {
+                        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<Action>
+                implements DOMActionImplementation {
+
+            ActionAdapter(BindingNormalizedNodeCodecRegistry codec, Class<? extends Operation> clazz,
+                    Action<?, ?, ?, ?> delegate) {
+                super(codec, clazz, delegate);
+            }
+
+            @SuppressWarnings("checkstyle:illegalCatch, unchecked")
+            @Nonnull
+            public FluentFuture<? extends DOMActionResult> invokeAction(SchemaPath type, DOMDataTreeIdentifier path,
+                    ContainerNode input) {
+                final TreeNode bindingInput = input != null ? deserialize(type, input) : null;
+                final SettableFuture<RpcResult<?>> bindingResult = SettableFuture.create();
+                CompletableFuture.runAsync(() -> delegate.invoke((Input<?>) bindingInput,
+                    codec.fromYangInstanceIdentifier(path.getRootIdentifier()),
+                    new RpcCallback<Output<?>>() {
+                        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 (file)
index 0000000..54c1748
--- /dev/null
@@ -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<DOMActionResult> {
+    private static final ExceptionMapper<DOMActionException> DOM_ACTION_EX_MAPPER =
+            new ExceptionMapper<DOMActionException>("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<RpcResult<?>> bindingFuture;
+    private final BindingNormalizedNodeCodecRegistry codec;
+    private volatile DOMActionResult result;
+
+    private LazyDOMActionResultFuture(final ListenableFuture<RpcResult<?>> delegate,
+                                      final BindingNormalizedNodeCodecRegistry codec) {
+        this.bindingFuture = Preconditions.checkNotNull(delegate, "delegate");
+        this.codec = Preconditions.checkNotNull(codec, "codec");
+    }
+
+    static FluentFuture<DOMActionResult> create(final BindingNormalizedNodeCodecRegistry codec,
+            final ListenableFuture<RpcResult<?>> bindingResult) {
+        return new LazyDOMActionResultFuture(bindingResult, codec);
+    }
+
+    ListenableFuture<RpcResult<?>> 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());
+    }
+
+}
@@ -32,7 +32,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
  * DOM operation result from Binding.
  */
 @Beta
-final class LazyDOMOperationResultFuture extends AbstractFuture<DOMRpcResult> {
+final class LazyDOMRpcResultFuture extends AbstractFuture<DOMRpcResult> {
     private static final ExceptionMapper<DOMRpcException> DOM_RPC_EX_MAPPER =
             new ExceptionMapper<DOMRpcException>("rpc", DOMRpcException.class) {
         @Override
@@ -46,15 +46,15 @@ final class LazyDOMOperationResultFuture extends AbstractFuture<DOMRpcResult> {
     private final BindingNormalizedNodeCodecRegistry codec;
     private volatile DOMRpcResult result;
 
-    private LazyDOMOperationResultFuture(final ListenableFuture<RpcResult<?>> delegate,
-            final BindingNormalizedNodeCodecRegistry codec) {
+    private LazyDOMRpcResultFuture(final ListenableFuture<RpcResult<?>> delegate,
+                                   final BindingNormalizedNodeCodecRegistry codec) {
         this.bindingFuture = Preconditions.checkNotNull(delegate, "delegate");
         this.codec = Preconditions.checkNotNull(codec, "codec");
     }
 
     static FluentFuture<DOMRpcResult> create(final BindingNormalizedNodeCodecRegistry codec,
             final ListenableFuture<RpcResult<?>> bindingResult) {
-        return new LazyDOMOperationResultFuture(bindingResult, codec);
+        return new LazyDOMRpcResultFuture(bindingResult, codec);
     }
 
     ListenableFuture<RpcResult<?>> getBindingFuture() {
index c9653a5920fb10fe1a986e32225404c2a9253470..c30d2c8ebbfe974f2cefdcf9b5b96558108014a1 100644 (file)
@@ -154,8 +154,8 @@ class RpcServiceAdapter implements InvocationHandler {
         private ListenableFuture<RpcResult<?>> invoke0(final SchemaPath schemaPath, final NormalizedNode<?, ?> input) {
             final ListenableFuture<DOMRpcResult> 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());
index f30a550d00b4b35587b9618f80593e20cd447f25..1f6f2023582920b7e2491e0322dc747826e4b943 100644 (file)
@@ -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<T extends Operation> extends AbstractObjectRegistration<T> {
 
-    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;
     }
index dcf9d8e241a506b0eddbfc04aeb8a7acf0a36859..1e42a9a1d554a6ed7eed55e28ef2c9c4b715bd3b 100644 (file)
@@ -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();
     }
index b86ee27815f14b231634cafbc8cfc292f32272e4..2c7cccdbde0f4dcdf563b35a37b73a6cef52aaf9 100644 (file)
@@ -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<Method, SchemaPath> getRPCMethodToSchemaPath(final Class<?> key) {
         final Module module = getModuleBlocking(key);
         final ImmutableBiMap.Builder<Method, SchemaPath> 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<Method, SchemaPath> getActionMethodToSchemaPath(final Class<?> key) {
-        final Module module = getModuleBlocking(key);
-
-        final ImmutableBiMap.Builder<Method, SchemaPath> 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<? extends Action<?, ?, ?, ?>> 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<? extends Rpc<?, ?>> 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 <P extends TreeNode> Set<DOMDataTreeIdentifier>
+            toDOMDataTreeIdentifiers(final Set<DataTreeIdentifier<P>> subtrees) {
+        final Set<DOMDataTreeIdentifier> 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.
      *
index 9d730b642d80859c604c9adc2eaf74220a88a017..cf3a6adaebc7b1888e5cb65eed5dc4d8239fd40b 100644 (file)
@@ -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<GeneratedTypeBuilder> augmentations = new ArrayList<>();
     private final Multimap<Type,AugmentationSchemaNode> typeToAugmentations = HashMultimap.create();
     private final BiMap<SchemaPath,Type> targetToAugmentation = HashBiMap.create();
-    private final Map<Type,Object> typeToSchema = new HashMap<>();
+    private final Map<Type,WithStatus> typeToSchema = new HashMap<>();
     private final Multimap<Type, Type> choiceToCases = HashMultimap.create();
     private final BiMap<Type, CaseSchemaNode> caseTypeToSchema = HashBiMap.create();
     private final Map<SchemaPath, Type> innerTypes = new HashMap<>();
@@ -207,7 +208,7 @@ public final class ModuleContext {
      *
      * @return Mapping from type to corresponding schema
      */
-    public Map<Type, Object> getTypeToSchema() {
+    public Map<Type, WithStatus> getTypeToSchema() {
         return Collections.unmodifiableMap(this.typeToSchema);
     }
 
index 3a05104cba760bf5381fd2f2b223ff22f39c2860..868a93412198e43d5a6c3789c4a230af4e6e056c 100755 (executable)
@@ -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<Type, AugmentationSchemaNode> augmentationToSchemas = HashMultimap.create();
     private final BiMap<SchemaPath,Type> targetToAugmentation = HashBiMap.create();
 
-    private final BiMap<Type, Object> typeToDefiningSchema = HashBiMap.create();
+    private final BiMap<Type, WithStatus> typeToDefiningSchema = HashBiMap.create();
     private final Multimap<Type, Type> choiceToCases = HashMultimap.create();
     private final Map<QName, Type> identities = new HashMap<>();
 
@@ -222,6 +227,14 @@ public class BindingRuntimeContext implements Immutable {
         return (DataSchemaNode) this.typeToDefiningSchema.get(referencedType(cls));
     }
 
+    public RpcDefinition getRpcDefinition(final Class<? extends Rpc<?, ?>> cls) {
+        return (RpcDefinition) typeToDefiningSchema.get(referencedType(cls));
+    }
+
+    public ActionDefinition getActionDefinition(final Class<? extends Action<?, ?, ?, ?>> cls) {
+        return (ActionDefinition) typeToDefiningSchema.get(referencedType(cls));
+    }
+
     /**
      * Returns defining {@link AugmentationSchemaNode} of target for supplied class.
      *
index bc12722843378b36a29c27e8064d98c0de85550b..b4b7c9f43d3b07c548730330667cff40b6bed33f 100644 (file)
@@ -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<YangModuleInfo>) () -> {
+        return ClassLoaderUtils.callWithClassLoader(cls.getClassLoader(), () -> {
             final Class<?> moduleInfoClass = Thread.currentThread().getContextClassLoader().loadClass(potentialClassName);
             return (YangModuleInfo) moduleInfoClass.getMethod("getInstance").invoke(null);
          });