Simplify DOMOperationService API
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / ActionAdapter.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.binding.dom.adapter;
9
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.yangtools.yang.common.YangConstants.operationInputQName;
12
13 import com.google.common.util.concurrent.FluentFuture;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import java.lang.reflect.InvocationHandler;
17 import java.lang.reflect.Method;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
21 import org.opendaylight.mdsal.dom.api.DOMActionResult;
22 import org.opendaylight.mdsal.dom.api.DOMActionService;
23 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
24 import org.opendaylight.yangtools.yang.binding.Action;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
26 import org.opendaylight.yangtools.yang.binding.RpcInput;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
28 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
29
30 @NonNullByDefault
31 final class ActionAdapter extends AbstractBindingAdapter<DOMActionService> implements InvocationHandler {
32     private final Class<? extends Action<?, ?, ?>> type;
33     private final NodeIdentifier inputName;
34     private final SchemaPath schemaPath;
35
36     ActionAdapter(final BindingToNormalizedNodeCodec codec, final DOMActionService delegate,
37             final Class<? extends Action<?, ?, ?>> type) {
38         super(codec, delegate);
39         this.type = requireNonNull(type);
40         this.schemaPath = getCodec().getActionPath(type);
41         this.inputName = NodeIdentifier.create(operationInputQName(schemaPath.getLastComponent().getModule()));
42     }
43
44     @Override public @Nullable Object invoke(final @Nullable Object proxy, final @Nullable Method method,
45             final Object @Nullable [] args) throws Throwable {
46         switch (method.getName()) {
47             case "equals":
48                 if (args.length == 1) {
49                     return proxy == args[0];
50                 }
51                 break;
52             case "hashCode":
53                 if (args.length == 0) {
54                     return System.identityHashCode(proxy);
55                 }
56                 break;
57             case "toString":
58                 if (args.length == 0) {
59                     return type.getName() + "$Adapter{delegate=" + getDelegate() + "}";
60                 }
61                 break;
62             case "invoke":
63                 if (args.length == 2) {
64                     final InstanceIdentifier<?> path = (InstanceIdentifier<?>) requireNonNull(args[0]);
65                     final RpcInput input = (RpcInput) requireNonNull(args[1]);
66                     final FluentFuture<? extends DOMActionResult> future = getDelegate().invokeAction(schemaPath,
67                         new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, getCodec().toNormalized(path)),
68                         getCodec().toLazyNormalizedNodeActionInput(type, inputName, input));
69
70                     // Invocation returned a future we know about -- return that future instead
71                     if (future instanceof BindingRpcFutureAware) {
72                         return ((BindingRpcFutureAware) future).getBindingFuture();
73                     }
74
75                     return Futures.transform(future,
76                         dom -> RpcResultUtil.rpcResultFromDOM(dom.getErrors(), dom.getOutput()
77                             .map(output -> getCodec().fromNormalizedNodeActionOutput(type, output))
78                             .orElse(null)), MoreExecutors.directExecutor());
79                 }
80                 break;
81             default:
82                 break;
83         }
84
85         throw new NoSuchMethodError("Method " + method.toString() + "is unsupported.");
86     }
87 }