Binding v2 runtime - adapters - impl - operations 49/59449/1
authorJakub Toth <jakub.toth@pantheon.tech>
Tue, 20 Jun 2017 12:39:03 +0000 (14:39 +0200)
committerMartin Ciglan <martin.ciglan@pantheon.tech>
Fri, 23 Jun 2017 09:06:02 +0000 (09:06 +0000)
Change-Id: I2d95df66996bff0ae340c2f7799e6399081af6ef
Signed-off-by: Jakub Toth <jakub.toth@pantheon.tech>
(cherry picked from commit 20e925231d9a4d8bec35fe328c0f92f79886837d)

19 files changed:
binding2/mdsal-binding2-api/src/main/java/org/opendaylight/mdsal/binding/javav2/api/RpcActionConsumerRegistry.java
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/extractor/ContextReferenceExtractor.java
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationImplementationAdapter.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationProviderServiceAdapter.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationServiceAdapter.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/LazyDOMOperationResultFuture.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/RpcServiceAdapter.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/AbstractMappedOperationInvoker.java
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvoker.java
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvokerWithInput.java
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationMethodInvokerWithoutInput.java
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/OperationServiceInvoker.java
binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/spi/loader/BindingDOMAdapterLoader.java
binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/ClassBaseOperationServiceInvokerTest.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/api/serializer/BindingNormalizedNodeSerializer.java
binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingNormalizedNodeCodecRegistry.java
binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/BindingToNormalizedNodeCodec.java
binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/serialized/LazySerializedContainerNode.java

index 8da31d334ea7d148a06168bd5d2a58e27b7e87ea..860e0bcea02c4acfb05a39184ae12fa2c3a56f1a 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.annotations.Beta;
 import org.opendaylight.mdsal.binding.javav2.spec.base.Action;
 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;
 
 /**
  * Provides access to registered Remote Procedure Call (RPC) and Action service implementations.
@@ -34,7 +35,7 @@ public interface RpcActionConsumerRegistry extends BindingService {
      * @param <T> interface type
      * @return returns proxy for the requested RPC
      */
-    <T extends Rpc> T getRpcService(Class<T> serviceInterface);
+    <T extends Rpc<?, ?>> T getRpcService(Class<T> serviceInterface);
 
     /**
      * Returns an implementation of a requested Action service.
@@ -47,7 +48,7 @@ public interface RpcActionConsumerRegistry extends BindingService {
      * @param <T> interface type
      * @return returns proxy for the requested Action
      */
-    <T extends Action> T getActionService(Class<T> serviceInterface);
+    <T extends Action<? extends TreeNode, ?, ?>> T getActionService(Class<T> serviceInterface);
 
     /**
      * Returns an implementation of a requested ListAction service.
@@ -60,6 +61,6 @@ public interface RpcActionConsumerRegistry extends BindingService {
      * @param <T> interface type
      * @return returns proxy for the requested ListAction
      */
-    <T extends ListAction> T getListActionService(Class<T> serviceInterface);
+    <T extends ListAction<? extends TreeNode, ?, ?>> T getListActionService(Class<T> serviceInterface);
 
 }
index 0db263235c6741ddb22c723c90d9f8d0f9f36866..200239573094893881e2a4fe51a0ccd78eb9a9d6 100644 (file)
@@ -33,7 +33,7 @@ public interface RpcActionProviderService {
      * @param <T> service implementation type
      * @return returns class representing a RPC registration
      */
-    <S extends Rpc, T extends S> ObjectRegistration<T> registerRpcImplementation(Class<S> type,
+    <S extends Rpc<?, ?>, T extends S> ObjectRegistration<T> registerRpcImplementation(Class<S> type,
         T implementation);
 
     /**
@@ -45,7 +45,7 @@ public interface RpcActionProviderService {
      * @param <T> service implementation type
      * @return returns class representing a RPC registration
      */
-    <S extends Rpc, T extends S> ObjectRegistration<T> registerRpcImplementation(Class<S> type,
+    <S extends Rpc<?, ?>, T extends S> ObjectRegistration<T> registerRpcImplementation(Class<S> type,
         T implementation, Set<InstanceIdentifier<?>> paths);
 
     /**
@@ -58,7 +58,8 @@ public interface RpcActionProviderService {
      * @param <T> service implementation type
      * @return returns class representing a Action registration
      */
-    <S extends Action, T extends S, P extends TreeNode> ObjectRegistration<T> registerActionImplementation(
+    <S extends Action<? extends TreeNode, ?, ?>, T extends S, P extends TreeNode> ObjectRegistration<T>
+            registerActionImplementation(
         Class<S> type, InstanceIdentifier<P> parent, T implementation);
 
     /**
@@ -72,6 +73,7 @@ public interface RpcActionProviderService {
      * @param <T> service implementation type
      * @return returns class representing a ListAction registration
      */
-    <S extends ListAction, T extends S, P extends TreeNode, K> ObjectRegistration<T> registerListActionImplementation(
+    <S extends ListAction<? extends TreeNode, ?, ?>, T extends S, P extends TreeNode, K> ObjectRegistration<T>
+            registerListActionImplementation(
             Class<S> type, KeyedInstanceIdentifier<P, K> parent, T implementation);
 }
index 20e2d788f0cbf4114f95112da01050d9b1a097bc..a9bc0d65d0d763f41bb9640d801289d76dcf50d4 100644 (file)
@@ -84,14 +84,14 @@ public abstract class ContextReferenceExtractor {
     /**
      * Extract context-reference (Instance Identifier) from Binding TreeNode.
      *
-     * @param obj
+     * @param input
      *            - TreeNode from which context reference should be extracted.
      *
      * @return Instance Identifier representing context reference or null, if tree node does not contain
      *         context reference.
      */
     @Nullable
-    public abstract InstanceIdentifier<? extends TreeNode> extract(TreeNode obj);
+    public abstract InstanceIdentifier<? extends TreeNode> extract(TreeNode input);
 
     /**
      * Method for return specific extractor of input object.
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
new file mode 100644 (file)
index 0000000..749a9ff
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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.CheckedFuture;
+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.DOMRpcException;
+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();
+    }
+
+    @Nonnull
+    @Override
+    public CheckedFuture<DOMRpcResult, DOMRpcException> 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 CheckedFuture<DOMRpcResult, DOMRpcException>
+            transformResult(final ListenableFuture<RpcResult<?>> 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
new file mode 100644 (file)
index 0000000..68a105f
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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.collect.ImmutableSet;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.mdsal.binding.javav2.api.RpcActionProviderService;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.registration.BindingDOMOperationAdapterRegistration;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+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.mdsal.dom.api.DOMRpcIdentifier;
+import org.opendaylight.mdsal.dom.api.DOMRpcImplementationRegistration;
+import org.opendaylight.mdsal.dom.api.DOMRpcProviderService;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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)
+/**
+ * Operation service provider adapter.
+ */
+@Beta
+public class BindingDOMOperationProviderServiceAdapter implements RpcActionProviderService {
+
+    private static final Set<YangInstanceIdentifier> GLOBAL = ImmutableSet.of(YangInstanceIdentifier.builder().build());
+    private final BindingToNormalizedNodeCodec codec;
+    private final DOMRpcProviderService domRpcRegistry;
+
+    public BindingDOMOperationProviderServiceAdapter(final DOMRpcProviderService domRpcRegistry,
+            final BindingToNormalizedNodeCodec codec) {
+        this.codec = codec;
+        this.domRpcRegistry = domRpcRegistry;
+    }
+
+    @Override
+    public <S extends Rpc<?, ?>, T extends S> ObjectRegistration<T> registerRpcImplementation(final Class<S> type,
+            final T implementation) {
+        return register(type, implementation, GLOBAL);
+    }
+
+    @Override
+    public <S extends Rpc<?, ?>, T extends S> ObjectRegistration<T> registerRpcImplementation(final Class<S> type,
+            final T implementation, final Set<InstanceIdentifier<?>> paths) {
+        return register(type, implementation, toYangInstanceIdentifiers(paths));
+    }
+
+    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);
+        return new BindingDOMOperationAdapterRegistration<>(implementation, domReg);
+    }
+
+    private static Set<DOMRpcIdentifier> createDomRpcIdentifiers(final Set<SchemaPath> rpcs,
+            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));
+            }
+        }
+        return ret;
+    }
+
+    private Collection<YangInstanceIdentifier> toYangInstanceIdentifiers(final Set<InstanceIdentifier<?>> identifiers) {
+        final Collection<YangInstanceIdentifier> ret = new ArrayList<>(identifiers.size());
+        for (final InstanceIdentifier<?> binding : identifiers) {
+            ret.add(codec.toYangInstanceIdentifierCached(binding));
+        }
+        return ret;
+    }
+
+    @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();
+    }
+
+    @Override
+    public <S extends ListAction<? extends TreeNode, ?, ?>, T extends S, P extends TreeNode, K> 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();
+    }
+}
diff --git a/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationServiceAdapter.java b/binding2/mdsal-binding2-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/BindingDOMOperationServiceAdapter.java
new file mode 100644 (file)
index 0000000..c79a6ca
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ClassToInstanceMap;
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.api.RpcActionConsumerRegistry;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder.Factory;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+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.ListAction;
+import org.opendaylight.mdsal.binding.javav2.spec.base.Operation;
+import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
+import org.opendaylight.mdsal.dom.api.DOMService;
+
+//FIXME implement after improve DOM part of MD-SAL for support of Yang 1.1
+/**
+ * Adapter for operation service.
+ */
+@Beta
+public class BindingDOMOperationServiceAdapter implements RpcActionConsumerRegistry {
+
+    public static final Factory<RpcActionConsumerRegistry> BUILDER_FACTORY = Builder::new;
+
+    private final DOMRpcService domService;
+    private final BindingToNormalizedNodeCodec codec;
+    private final LoadingCache<Class<? extends Operation>, RpcServiceAdapter> proxies = CacheBuilder.newBuilder()
+            .weakKeys().build(new CacheLoader<Class<? extends Operation>, RpcServiceAdapter>() {
+
+                @SuppressWarnings("unchecked")
+                private RpcServiceAdapter createProxy(final Class<? extends Operation> key) {
+                    Preconditions.checkArgument(BindingReflections.isBindingClass(key));
+                    Preconditions.checkArgument(key.isInterface(),
+                            "Supplied Operation service type must be interface.");
+                    if (Rpc.class.isAssignableFrom(key)) {
+                        return new RpcServiceAdapter((Class<? extends Rpc<?, ?>>) key, codec, domService);
+                    }
+                    // TODO implement after improve DOM part of MD-SAL for support of Yang 1.1
+                    throw new UnsupportedOperationException();
+                }
+
+                @Nonnull
+                @Override
+                public RpcServiceAdapter load(@Nonnull final Class<? extends Operation> key) throws Exception {
+                    return createProxy(key);
+                }
+
+            });
+
+    public BindingDOMOperationServiceAdapter(final DOMRpcService domService, final BindingToNormalizedNodeCodec codec) {
+        this.domService = Preconditions.checkNotNull(domService);
+        this.codec = Preconditions.checkNotNull(codec);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Rpc<?, ?>> T getRpcService(final Class<T> rpc) {
+        Preconditions.checkArgument(rpc != null, "Rpc needs to be specified.");
+        return (T) proxies.getUnchecked(rpc).getProxy();
+    }
+
+    private static final class Builder extends BindingDOMAdapterBuilder<RpcActionConsumerRegistry> {
+
+        @Override
+        protected RpcActionConsumerRegistry createInstance(final BindingToNormalizedNodeCodec codec,
+                final ClassToInstanceMap<DOMService> delegates) {
+            final DOMRpcService domRpc = delegates.getInstance(DOMRpcService.class);
+            return new BindingDOMOperationServiceAdapter(domRpc, codec);
+        }
+
+        @Override
+        public Set<? extends Class<? extends DOMService>> getRequiredDelegates() {
+            return ImmutableSet.of(DOMRpcService.class);
+        }
+    }
+
+    @Override
+    public <T extends Action<? extends TreeNode, ?, ?>> T getActionService(final Class<T> serviceInterface) {
+        // TODO implement after improve DOM part of MD-SAL for support of Yang 1.1
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <T extends ListAction<? extends TreeNode, ?, ?>> T getListActionService(final Class<T> serviceInterface) {
+        // TODO implement after improve DOM part of MD-SAL for support of Yang 1.1
+        throw new UnsupportedOperationException();
+    }
+}
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/LazyDOMOperationResultFuture.java
new file mode 100644 (file)
index 0000000..878e8e9
--- /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.base.Throwables;
+import com.google.common.util.concurrent.CheckedFuture;
+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.DOMRpcException;
+import org.opendaylight.mdsal.dom.api.DOMRpcResult;
+import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * DOM operation result from Binding.
+ */
+@Beta
+final class LazyDOMOperationResultFuture implements CheckedFuture<DOMRpcResult, DOMRpcException> {
+
+    private final ListenableFuture<RpcResult<?>> bindingFuture;
+    private final BindingNormalizedNodeCodecRegistry codec;
+    private volatile DOMRpcResult result;
+
+    private LazyDOMOperationResultFuture(final ListenableFuture<RpcResult<?>> delegate,
+            final BindingNormalizedNodeCodecRegistry codec) {
+        this.bindingFuture = Preconditions.checkNotNull(delegate, "delegate");
+        this.codec = Preconditions.checkNotNull(codec, "codec");
+    }
+
+    static CheckedFuture<DOMRpcResult, DOMRpcException> create(final BindingNormalizedNodeCodecRegistry codec,
+            final ListenableFuture<RpcResult<?>> bindingResult) {
+        return new LazyDOMOperationResultFuture(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 DOMRpcResult get() throws InterruptedException, ExecutionException {
+        if (result != null) {
+            return result;
+        }
+        return transformIfNecessary(bindingFuture.get());
+    }
+
+    @Override
+    public DOMRpcResult get(@Nonnull final long timeout, final TimeUnit unit)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        if (result != null) {
+            return result;
+        }
+        return transformIfNecessary(bindingFuture.get(timeout, unit));
+    }
+
+    @Override
+    public DOMRpcResult checkedGet() throws DOMRpcException {
+        try {
+            return get();
+        } catch (InterruptedException | ExecutionException e) {
+            // FIXME: Add exception mapping
+            throw Throwables.propagate(e);
+        }
+    }
+
+    @Override
+    public DOMRpcResult checkedGet(@Nonnull final long timeout, final TimeUnit unit)
+            throws TimeoutException, DOMRpcException {
+        try {
+            return get(timeout, unit);
+        } catch (InterruptedException | ExecutionException e) {
+            // FIXME: Add exception mapping
+            throw Throwables.propagate(e);
+        }
+    }
+
+    @Override
+    public boolean isCancelled() {
+        return bindingFuture.isCancelled();
+    }
+
+    @Override
+    public boolean isDone() {
+        return bindingFuture.isDone();
+    }
+
+    private synchronized DOMRpcResult transformIfNecessary(final RpcResult<?> input) {
+        if (result == null) {
+            result = transform(input);
+        }
+        return result;
+    }
+
+    private DOMRpcResult transform(final RpcResult<?> input) {
+        if (input.isSuccessful()) {
+            final Object inputData = input.getResult();
+            if (inputData instanceof DataContainer) {
+                return new DefaultDOMRpcResult(codec.toNormalizedNodeOperationData((TreeNode) inputData));
+            } else {
+                return new DefaultDOMRpcResult((NormalizedNode<?, ?>) null);
+            }
+        }
+        return new DefaultDOMRpcResult(input.getErrors());
+    }
+
+}
\ No newline at end of file
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
new file mode 100644 (file)
index 0000000..e988616
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * 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.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Map.Entry;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.extractor.ContextReferenceExtractor;
+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.InstanceIdentifier;
+import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable;
+import org.opendaylight.mdsal.binding.javav2.spec.base.Rpc;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.dom.api.DOMRpcException;
+import org.opendaylight.mdsal.dom.api.DOMRpcResult;
+import org.opendaylight.mdsal.dom.api.DOMRpcService;
+import org.opendaylight.mdsal.dom.spi.RpcRoutingStrategy;
+import org.opendaylight.yangtools.yang.common.QName;
+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.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.OperationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+@Beta
+class RpcServiceAdapter implements InvocationHandler {
+
+    private final ImmutableMap<Method, RpcInvocationStrategy> rpcNames;
+    private final Class<? extends Rpc<?, ?>> type;
+    private final BindingToNormalizedNodeCodec codec;
+    private final DOMRpcService delegate;
+    private final Rpc<?, ?> proxy;
+
+    RpcServiceAdapter(final Class<? extends Rpc<?, ?>> type, final BindingToNormalizedNodeCodec codec,
+            final DOMRpcService domService) {
+        this.type = Preconditions.checkNotNull(type);
+        this.codec = Preconditions.checkNotNull(codec);
+        this.delegate = Preconditions.checkNotNull(domService);
+        final ImmutableMap.Builder<Method, RpcInvocationStrategy> rpcBuilder = ImmutableMap.builder();
+        for (final Entry<Method, OperationDefinition> rpc : codec.getRPCMethodToSchema(type).entrySet()) {
+            rpcBuilder.put(rpc.getKey(), createStrategy(rpc.getKey(), (RpcDefinition) rpc.getValue()));
+        }
+        rpcNames = rpcBuilder.build();
+        proxy = (Rpc<?, ?>) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, this);
+    }
+
+    private RpcInvocationStrategy createStrategy(final Method method, final RpcDefinition schema) {
+        final RpcRoutingStrategy strategy = RpcRoutingStrategy.from(schema);
+        if (strategy.isContextBasedRouted()) {
+            return new RoutedStrategy(schema.getPath(), method, strategy.getLeaf());
+        }
+        return new NonRoutedStrategy(schema.getPath());
+    }
+
+    Rpc<?, ?> getProxy() {
+        return proxy;
+    }
+
+    @Override
+    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+
+        final RpcInvocationStrategy rpc = rpcNames.get(method);
+        if (rpc != null) {
+            if (method.getParameterTypes().length == 0) {
+                return rpc.invokeEmpty();
+            }
+            if (args.length != 1) {
+                throw new IllegalArgumentException("Input must be provided.");
+            }
+            return rpc.invoke((TreeNode) args[0]);
+        }
+
+        if (isObjectMethod(method)) {
+            return callObjectMethod(proxy, method, args);
+        }
+        throw new UnsupportedOperationException("Method " + method.toString() + "is unsupported.");
+    }
+
+    private static boolean isObjectMethod(final Method method) {
+        switch (method.getName()) {
+            case "toString":
+                return method.getReturnType().equals(String.class) && method.getParameterTypes().length == 0;
+            case "hashCode":
+                return method.getReturnType().equals(int.class) && method.getParameterTypes().length == 0;
+            case "equals":
+                return method.getReturnType().equals(boolean.class) && method.getParameterTypes().length == 1
+                        && method.getParameterTypes()[0] == Object.class;
+            default:
+                return false;
+        }
+    }
+
+    private Object callObjectMethod(final Object self, final Method method, final Object[] args) {
+        switch (method.getName()) {
+            case "toString":
+                return type.getName() + "$Adapter{delegate=" + delegate.toString() + "}";
+            case "hashCode":
+                return System.identityHashCode(self);
+            case "equals":
+                return self == args[0];
+            default:
+                return null;
+        }
+    }
+
+    private abstract class RpcInvocationStrategy {
+
+        private final SchemaPath rpcName;
+
+        protected RpcInvocationStrategy(final SchemaPath path) {
+            rpcName = path;
+        }
+
+        final ListenableFuture<RpcResult<?>> invoke(final TreeNode input) {
+            return invoke0(rpcName, serialize(input));
+        }
+
+        abstract NormalizedNode<?, ?> serialize(TreeNode input);
+
+        final ListenableFuture<RpcResult<?>> invokeEmpty() {
+            return invoke0(rpcName, null);
+        }
+
+        final SchemaPath getRpcName() {
+            return rpcName;
+        }
+
+        private ListenableFuture<RpcResult<?>> invoke0(final SchemaPath schemaPath, final NormalizedNode<?, ?> input) {
+            final CheckedFuture<DOMRpcResult, DOMRpcException> result = delegate.invokeRpc(schemaPath, input);
+
+            if (result instanceof LazyDOMOperationResultFuture) {
+                return ((LazyDOMOperationResultFuture) result).getBindingFuture();
+            }
+
+            return transformFuture(schemaPath, result, codec.getCodecFactory());
+        }
+
+        private ListenableFuture<RpcResult<?>> transformFuture(final SchemaPath rpc,
+                final ListenableFuture<DOMRpcResult> domFuture, final BindingNormalizedNodeCodecRegistry codec) {
+            return Futures.transform(domFuture, (Function<DOMRpcResult, RpcResult<?>>) input -> {
+                final NormalizedNode<?, ?> domData = input.getResult();
+                final TreeNode bindingResult;
+                if (domData != null) {
+                    final SchemaPath rpcOutput = rpc.createChild(QName.create(rpc.getLastComponent(), "output"));
+                    bindingResult = codec.fromNormalizedNodeOperationData(rpcOutput, (ContainerNode) domData);
+                } else {
+                    bindingResult = null;
+                }
+                return RpcResult.class.cast(RpcResultBuilder.success(bindingResult).build());
+            });
+        }
+
+    }
+
+    private final class NonRoutedStrategy extends RpcInvocationStrategy {
+
+        protected NonRoutedStrategy(final SchemaPath path) {
+            super(path);
+        }
+
+        @Override
+        NormalizedNode<?, ?> serialize(final TreeNode input) {
+            return LazySerializedContainerNode.create(getRpcName(), input, codec.getCodecRegistry());
+        }
+
+    }
+
+    private final class RoutedStrategy extends RpcInvocationStrategy {
+
+        private final ContextReferenceExtractor refExtractor;
+        private final NodeIdentifier contextName;
+
+        protected RoutedStrategy(final SchemaPath path, final Method rpcMethod, final QName leafName) {
+            super(path);
+            final Optional<Class<? extends Instantiable<?>>> maybeInputType =
+                    BindingReflections.resolveOperationInputClass(rpcMethod);
+            Preconditions.checkState(maybeInputType.isPresent(), "RPC method %s has no input", rpcMethod.getName());
+            final Class<? extends Instantiable<?>> inputType = maybeInputType.get();
+            refExtractor = ContextReferenceExtractor.from(inputType);
+            this.contextName = new NodeIdentifier(leafName);
+        }
+
+        @SuppressWarnings("rawtypes")
+        @Override
+        NormalizedNode<?, ?> serialize(final TreeNode input) {
+            final InstanceIdentifier<?> bindingII = refExtractor.extract(input);
+            if (bindingII != null) {
+                final YangInstanceIdentifier yangII = codec.toYangInstanceIdentifierCached(bindingII);
+                final LeafNode contextRef = ImmutableNodes.leafNode(contextName, yangII);
+                return LazySerializedContainerNode.withContextRef(getRpcName(), input, contextRef,
+                        codec.getCodecRegistry());
+            }
+            return LazySerializedContainerNode.create(getRpcName(), input, codec.getCodecRegistry());
+        }
+
+    }
+}
\ No newline at end of file
index fe7068e5518e33987a1ad31ee1bde3ddf16009a2..f066898a42098b9bb15595b1f768f2ece2e46d42 100644 (file)
@@ -18,8 +18,8 @@ import java.util.concurrent.Future;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections;
-import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable;
 import org.opendaylight.mdsal.binding.javav2.spec.base.Operation;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
@@ -49,7 +49,7 @@ abstract class AbstractMappedOperationInvoker<T> extends OperationServiceInvoker
 
     @Override
     public final <I extends Operation> Future<RpcResult<?>> invoke(@Nonnull final I impl,
-            @Nonnull final QName operationName, @Nullable final Instantiable<?> input) {
+            @Nonnull final QName operationName, @Nullable final TreeNode input) {
 
         Preconditions.checkNotNull(impl, "Implementation must be supplied");
 
index 17f4f817cb0cc9f396b6ffa478206dc503f94f33..c1549ad3ee352654cc4d1922ef05ca94dd84baad 100644 (file)
@@ -18,6 +18,7 @@ import java.util.concurrent.Future;
 import org.opendaylight.mdsal.binding.javav2.runtime.reflection.BindingReflections;
 import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable;
 import org.opendaylight.mdsal.binding.javav2.spec.base.Operation;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
 @Beta
@@ -25,7 +26,7 @@ abstract class OperationMethodInvoker {
 
     private static final Lookup LOOKUP = MethodHandles.publicLookup();
 
-    protected abstract <T extends Operation> Future<RpcResult<?>> invokeOn(T impl, Instantiable<?> input);
+    protected abstract <T extends Operation> Future<RpcResult<?>> invokeOn(T impl, TreeNode input);
 
     protected static OperationMethodInvoker from(final Method method) {
         final Optional<Class<? extends Instantiable<?>>> input = BindingReflections.resolveOperationInputClass(method);
index f1fa21b41ad98a1fb1dfb67c053f32022df96971..d235e7a121624c51355a1db2822601709e19d098 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable;
 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.Rpc;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
 @Beta
@@ -31,7 +32,7 @@ class OperationMethodInvokerWithInput extends OperationMethodInvoker {
     }
 
     @Override
-    public <T extends Operation> Future<RpcResult<?>> invokeOn(final T impl, final Instantiable<?> input) {
+    public <T extends Operation> Future<RpcResult<?>> invokeOn(final T impl, final TreeNode input) {
         return invoking(handle, impl, input);
     }
 }
index 7316fc7f80ce36dc171d179f4c0f9222076d7a90..e1d8f8b032d3ea4fd5b2d6c722504f12d7cb02eb 100644 (file)
@@ -12,10 +12,10 @@ import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodType;
 import java.util.concurrent.Future;
 import org.opendaylight.mdsal.binding.javav2.spec.base.Action;
-import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable;
 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.Rpc;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
 @Beta
@@ -31,7 +31,7 @@ class OperationMethodInvokerWithoutInput extends OperationMethodInvoker {
     }
 
     @Override
-    public <T extends Operation> Future<RpcResult<?>> invokeOn(final T impl, final Instantiable<?> input) {
+    public <T extends Operation> Future<RpcResult<?>> invokeOn(final T impl, final TreeNode input) {
         return invoking(handle, impl);
     }
 }
index 52b473e12e73a8f88b491422edb69dc0613721ec..4167ba3dc9ee0c2387525eee8f13e53415f99d26 100644 (file)
@@ -14,8 +14,8 @@ import java.util.Map;
 import java.util.concurrent.Future;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable;
 import org.opendaylight.mdsal.binding.javav2.spec.base.Operation;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory;
  *
  * <p>
  * Operation Service invoker provides common invocation interface for any subtype of operation. via
- * {@link #invoke(Operation, QName, Instantiable)} method.
+ * {@link #invoke(Operation, QName, TreeNode)} method.
  */
 @Beta
 public abstract class OperationServiceInvoker {
@@ -87,5 +87,5 @@ public abstract class OperationServiceInvoker {
      * @return Future which will complete once operation processing is finished.
      */
     public abstract <T extends Operation> Future<RpcResult<?>> invoke(@Nonnull T impl, @Nonnull QName operationName,
-            @Nullable Instantiable<?> input);
+            @Nullable TreeNode input);
 }
index 447f60eb6e1452619b29e27d15e5d24df192ed52..fa2742586d9bb1845f943739126f945725957101 100644 (file)
@@ -16,9 +16,11 @@ import org.opendaylight.mdsal.binding.javav2.api.BindingService;
 import org.opendaylight.mdsal.binding.javav2.api.DataBroker;
 import org.opendaylight.mdsal.binding.javav2.api.NotificationPublishService;
 import org.opendaylight.mdsal.binding.javav2.api.NotificationService;
+import org.opendaylight.mdsal.binding.javav2.api.RpcActionConsumerRegistry;
 import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.data.BindingDOMDataBrokerAdapter;
 import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.notification.BindingDOMNotificationPublishServiceAdapter;
 import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.notification.BindingDOMNotificationServiceAdapter;
+import org.opendaylight.mdsal.binding.javav2.dom.adapter.impl.operation.BindingDOMOperationServiceAdapter;
 import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.AdapterBuilder;
 import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder;
 import org.opendaylight.mdsal.binding.javav2.dom.adapter.spi.builder.BindingDOMAdapterBuilder.Factory;
@@ -31,13 +33,13 @@ import org.opendaylight.mdsal.dom.api.DOMService;
 @Beta
 public abstract class BindingDOMAdapterLoader extends AdapterLoader<BindingService, DOMService> {
 
-    // TODO add all factory of services
     @SuppressWarnings("checkstyle:GenericWhitespace")
     private static final Map<Class<?>, BindingDOMAdapterBuilder.Factory<?>> FACTORIES =
             ImmutableMap.<Class<?>, BindingDOMAdapterBuilder.Factory<?>> builder()
                     .put(DataBroker.class, BindingDOMDataBrokerAdapter.BUILDER_FACTORY)
                     .put(NotificationPublishService.class, BindingDOMNotificationPublishServiceAdapter.BUILDER_FACTORY)
                     .put(NotificationService.class, BindingDOMNotificationServiceAdapter.BUILDER_FACTORY)
+                    .put(RpcActionConsumerRegistry.class, BindingDOMOperationServiceAdapter.BUILDER_FACTORY)
                     .build();
 
     private final BindingToNormalizedNodeCodec codec;
diff --git a/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/ClassBaseOperationServiceInvokerTest.java b/binding2/mdsal-binding2-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/adapter/impl/operation/invoker/ClassBaseOperationServiceInvokerTest.java
new file mode 100644 (file)
index 0000000..45023ea
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.invoker;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+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.base.TreeNode;
+
+public class ClassBaseOperationServiceInvokerTest {
+
+    @Test
+    public void rpcTest() {
+        final OperationServiceInvoker serviceInvoker = ClassBasedOperationServiceInvoker.instanceFor(DummyRpc.class);
+        assertNotNull(serviceInvoker);
+    }
+
+    @Test
+    public void actionTest() {
+        final OperationServiceInvoker serviceInvoker = ClassBasedOperationServiceInvoker.instanceFor(DummyAction.class);
+        assertNotNull(serviceInvoker);
+    }
+
+    @SuppressWarnings("rawtypes")
+    private interface DummyRpc extends Rpc, TreeNode {
+    }
+
+    @SuppressWarnings("rawtypes")
+    private interface DummyAction extends Action, TreeNode {
+    }
+}
index 521af6232159f6e64a9612d9248bc314f5acecf4..6a81ed81d78272dbeda32a00dcf11bafa5cac956 100644 (file)
@@ -11,7 +11,6 @@ import java.util.Map.Entry;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
-import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable;
 import org.opendaylight.mdsal.binding.javav2.spec.base.Notification;
 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -128,5 +127,5 @@ public interface BindingNormalizedNodeSerializer {
      * @return NormalizedNode representation of operation data
      */
     @Nonnull
-    ContainerNode toNormalizedNodeOperationData(@Nonnull Instantiable<?> data);
+    ContainerNode toNormalizedNodeOperationData(@Nonnull TreeNode data);
 }
index c2694d29309e99825df2c4f95165a71ba0468436..2ec3aac1e2ce542ae4c43519caad52a321cf6e2b 100644 (file)
@@ -169,16 +169,16 @@ public class BindingNormalizedNodeCodecRegistry implements TreeNodeSerializerReg
     @Nonnull
     @SuppressWarnings("unchecked")
     @Override
-    public ContainerNode toNormalizedNodeOperationData(@Nonnull final Instantiable<?> data) {
+    public ContainerNode toNormalizedNodeOperationData(@Nonnull final TreeNode data) {
         final NormalizedNodeResult result = new NormalizedNodeResult();
         // We create DOM stream writer which produces normalized nodes
         final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
         @SuppressWarnings("rawtypes")
-        final Class<? extends TreeNode> type = (Class) data.implementedInterface();
+        final Class<? extends TreeNode> type = data.getClass();
         final Class<? extends Instantiable<?>> instData = (Class<? extends Instantiable<?>>) data.getClass();
         final BindingStreamEventWriter writer = newOperationWriter(instData, domWriter);
         try {
-            getSerializer(type).serialize((TreeNode) data, writer);
+            getSerializer(type).serialize(data, writer);
         } catch (final IOException e) {
             LOG.error("Unexpected failure while serializing data {}", data, e);
             throw new IllegalStateException("Failed to create normalized node", e);
index 5a20cce332baf4ae0a256d82c11fbd68f245965f..25035070964258467062668ffac6e60812a2c377 100644 (file)
@@ -36,7 +36,6 @@ import org.opendaylight.mdsal.binding.javav2.generator.impl.GeneratedClassLoadin
 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.InstanceIdentifier;
-import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable;
 import org.opendaylight.mdsal.binding.javav2.spec.base.Notification;
 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeArgument;
 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
@@ -228,7 +227,7 @@ public final class BindingToNormalizedNodeCodec
 
     @Nonnull
     @Override
-    public ContainerNode toNormalizedNodeOperationData(@Nonnull final Instantiable<?> data) {
+    public ContainerNode toNormalizedNodeOperationData(@Nonnull final TreeNode data) {
         return codecRegistry.toNormalizedNodeOperationData(data);
     }
 
index 6b543ccf60689fb8e7687e53a278c9d3fbbffa23..0e49aac61709f623075bdce1c1594c8149505566 100644 (file)
@@ -12,7 +12,7 @@ import java.util.Collection;
 import java.util.Map;
 import javax.annotation.Nonnull;
 import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingNormalizedNodeCodecRegistry;
-import org.opendaylight.mdsal.binding.javav2.spec.base.Instantiable;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
@@ -28,12 +28,12 @@ import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 public class LazySerializedContainerNode implements ContainerNode {
 
     private final NodeIdentifier identifier;
-    private final Instantiable<?> bindingData;
+    private final TreeNode bindingData;
 
     private BindingNormalizedNodeCodecRegistry registry;
     private ContainerNode domData;
 
-    private LazySerializedContainerNode(final QName identifier, final Instantiable<?> binding,
+    private LazySerializedContainerNode(final QName identifier, final TreeNode binding,
             final BindingNormalizedNodeCodecRegistry registry) {
         this.identifier = NodeIdentifier.create(identifier);
         this.bindingData = binding;
@@ -52,7 +52,7 @@ public class LazySerializedContainerNode implements ContainerNode {
      *            - specifc codec for operation
      * @return instance of lazy serialized container node
      */
-    public static NormalizedNode<?, ?> create(final SchemaPath operationName, final Instantiable<?> data,
+    public static NormalizedNode<?, ?> create(final SchemaPath operationName, final TreeNode data,
             final BindingNormalizedNodeCodecRegistry codec) {
         return new LazySerializedContainerNode(operationName.getLastComponent(), data, codec);
     }
@@ -71,7 +71,7 @@ public class LazySerializedContainerNode implements ContainerNode {
      *            - specific codec
      * @return insntance of lazy serialized container node with pre-cached serialized leaf
      */
-    public static NormalizedNode<?, ?> withContextRef(final SchemaPath operationName, final Instantiable<?> data,
+    public static NormalizedNode<?, ?> withContextRef(final SchemaPath operationName, final TreeNode data,
             final LeafNode<?> contextRef, final BindingNormalizedNodeCodecRegistry codec) {
         return new WithContextRef(operationName.getLastComponent(), data, contextRef, codec);
     }
@@ -120,7 +120,7 @@ public class LazySerializedContainerNode implements ContainerNode {
      *
      * @return binding data.
      */
-    public final Instantiable<?> bindingData() {
+    public final TreeNode bindingData() {
         return bindingData;
     }
 
@@ -132,7 +132,7 @@ public class LazySerializedContainerNode implements ContainerNode {
 
         private final LeafNode<?> contextRef;
 
-        private WithContextRef(final QName identifier, final Instantiable<?> binding, final LeafNode<?> contextRef,
+        private WithContextRef(final QName identifier, final TreeNode binding, final LeafNode<?> contextRef,
                 final BindingNormalizedNodeCodecRegistry registry) {
             super(identifier, binding, registry);
             this.contextRef = contextRef;