Integrate Action with BindingContract
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / ActionAdapter.java
index 70259f29840a504180a377aca24e70593e38b9a7..fa13ea1cc739b7eb088fbde9e2e66da1f4edf4a0 100644 (file)
@@ -7,42 +7,41 @@
  */
 package org.opendaylight.mdsal.binding.dom.adapter;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Objects.requireNonNull;
+import static org.opendaylight.mdsal.binding.dom.adapter.StaticConfiguration.ENABLE_CODEC_SHORTCUT;
 import static org.opendaylight.yangtools.yang.common.YangConstants.operationInputQName;
 
-import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.api.ActionSpec;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMActionResult;
 import org.opendaylight.mdsal.dom.api.DOMActionService;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
-import org.opendaylight.yangtools.yang.binding.Action;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.RpcInput;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 
-@NonNullByDefault
 final class ActionAdapter extends AbstractBindingAdapter<DOMActionService> implements InvocationHandler {
-    private final Class<? extends Action<?, ?, ?>> type;
-    private final NodeIdentifier inputName;
-    private final SchemaPath schemaPath;
+    private final @NonNull ActionSpec<?, ?> spec;
+    private final @NonNull NodeIdentifier inputName;
+    private final @NonNull Absolute actionPath;
 
-    ActionAdapter(final BindingToNormalizedNodeCodec codec, final DOMActionService delegate,
-            final Class<? extends Action<?, ?, ?>> type) {
+    ActionAdapter(final AdapterContext codec, final DOMActionService delegate, final ActionSpec<?, ?> spec) {
         super(codec, delegate);
-        this.type = requireNonNull(type);
-        this.schemaPath = getCodec().getActionPath(type);
-        this.inputName = NodeIdentifier.create(operationInputQName(schemaPath.getLastComponent().getModule()));
+        this.spec = requireNonNull(spec);
+        actionPath = currentSerializer().getActionPath(spec);
+        inputName = NodeIdentifier.create(operationInputQName(actionPath.lastNodeIdentifier().getModule()));
     }
 
-    @Override public @Nullable Object invoke(final @Nullable Object proxy, final @Nullable Method method,
-            final Object @Nullable [] args) throws Throwable {
+    @Override
+    public Object invoke(final Object proxy, final Method method, final Object [] args) throws Throwable {
         switch (method.getName()) {
             case "equals":
                 if (args.length == 1) {
@@ -56,32 +55,40 @@ final class ActionAdapter extends AbstractBindingAdapter<DOMActionService> imple
                 break;
             case "toString":
                 if (args.length == 0) {
-                    return type.getName() + "$Adapter{delegate=" + getDelegate() + "}";
+                    return spec.type().getName() + "$Adapter{delegate=" + getDelegate() + "}";
                 }
                 break;
             case "invoke":
                 if (args.length == 2) {
                     final InstanceIdentifier<?> path = (InstanceIdentifier<?>) requireNonNull(args[0]);
+                    checkArgument(!path.isWildcarded(), "Cannot invoke action on wildcard path %s", path);
+
                     final RpcInput input = (RpcInput) requireNonNull(args[1]);
-                    final FluentFuture<? extends DOMActionResult> future = getDelegate().invokeAction(schemaPath,
-                        new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, getCodec().toNormalized(path)),
-                        getCodec().toLazyNormalizedNodeActionInput(type, inputName, input));
+                    final CurrentAdapterSerializer serializer = currentSerializer();
+                    final ListenableFuture<? extends DOMActionResult> future = getDelegate().invokeAction(actionPath,
+                        new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL,
+                            serializer.toYangInstanceIdentifier(path)),
+                        serializer.toLazyNormalizedNodeActionInput(spec.type(), inputName, input));
 
                     // Invocation returned a future we know about -- return that future instead
-                    if (future instanceof BindingRpcFutureAware) {
-                        return ((BindingRpcFutureAware) future).getBindingFuture();
+                    if (ENABLE_CODEC_SHORTCUT && future instanceof BindingRpcFutureAware bindingAware) {
+                        return bindingAware.getBindingFuture();
                     }
 
                     return Futures.transform(future,
                         dom -> RpcResultUtil.rpcResultFromDOM(dom.getErrors(), dom.getOutput()
-                            .map(output -> getCodec().fromNormalizedNodeActionOutput(type, output))
-                            .orElse(null)), MoreExecutors.directExecutor());
+                            .map(output -> serializer.fromNormalizedNodeActionOutput(spec.type(), output))
+                            .orElse(null)),
+                        MoreExecutors.directExecutor());
                 }
                 break;
             default:
                 break;
         }
 
+        if (method.isDefault()) {
+            return InvocationHandler.invokeDefault(proxy, method, args);
+        }
         throw new NoSuchMethodError("Method " + method.toString() + "is unsupported.");
     }
 }