Do not use FluentFuture in RestconfStrategy
[netconf.git] / restconf / restconf-nb / src / main / java / org / opendaylight / restconf / nb / rfc8040 / rests / transactions / NetconfRestconfStrategy.java
1 /*
2  * Copyright (c) 2020 PANTHEON.tech, 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.restconf.nb.rfc8040.rests.transactions;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import com.google.common.util.concurrent.SettableFuture;
17 import java.util.List;
18 import java.util.Optional;
19 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
20 import org.opendaylight.mdsal.common.api.ReadFailedException;
21 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
23 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
24
25 /**
26  * Implementation of RESTCONF operations on top of a raw NETCONF backend.
27  *
28  * @see NetconfDataTreeService
29  */
30 public final class NetconfRestconfStrategy extends RestconfStrategy {
31     private final NetconfDataTreeService netconfService;
32
33     public NetconfRestconfStrategy(final NetconfDataTreeService netconfService) {
34         this.netconfService = requireNonNull(netconfService);
35     }
36
37     @Override
38     public RestconfTransaction prepareWriteExecution() {
39         return new NetconfRestconfTransaction(netconfService);
40     }
41
42     @Override
43     public ListenableFuture<Optional<NormalizedNode>> read(final LogicalDatastoreType store,
44             final YangInstanceIdentifier path) {
45         return switch (store) {
46             case CONFIGURATION -> netconfService.getConfig(path);
47             case OPERATIONAL -> netconfService.get(path);
48         };
49     }
50
51     @Override
52     public ListenableFuture<Optional<NormalizedNode>> read(final LogicalDatastoreType store,
53             final YangInstanceIdentifier path, final List<YangInstanceIdentifier> fields) {
54         return switch (store) {
55             case CONFIGURATION -> netconfService.getConfig(path, fields);
56             case OPERATIONAL -> netconfService.get(path, fields);
57         };
58     }
59
60     @Override
61     public ListenableFuture<Boolean> exists(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
62         return Futures.transform(remapException(read(store, path)),
63             optionalNode -> optionalNode != null && optionalNode.isPresent(),
64             MoreExecutors.directExecutor());
65     }
66
67     private static <T> ListenableFuture<T> remapException(final ListenableFuture<T> input) {
68         final var ret = SettableFuture.<T>create();
69         Futures.addCallback(input, new FutureCallback<T>() {
70             @Override
71             public void onSuccess(final T result) {
72                 ret.set(result);
73             }
74
75             @Override
76             public void onFailure(final Throwable cause) {
77                 ret.setException(cause instanceof ReadFailedException ? cause
78                     : new ReadFailedException("NETCONF operation failed", cause));
79             }
80         }, MoreExecutors.directExecutor());
81         return ret;
82     }
83 }