Add DOMDataTreeQueryOperations
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / AbstractForwardedTransaction.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. 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 com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Preconditions.checkState;
12 import static java.util.Objects.requireNonNull;
13
14 import com.google.common.util.concurrent.FluentFuture;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import java.util.Optional;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.mdsal.binding.api.query.QueryExpression;
19 import org.opendaylight.mdsal.binding.api.query.QueryResult;
20 import org.opendaylight.mdsal.binding.dom.adapter.query.DefaultQuery;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.mdsal.dom.api.DOMDataTreeQueryOperations;
23 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadOperations;
24 import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
25 import org.opendaylight.mdsal.dom.api.query.DOMQuery;
26 import org.opendaylight.mdsal.dom.api.query.DOMQueryResult;
27 import org.opendaylight.mdsal.dom.spi.query.DOMQueryEvaluator;
28 import org.opendaylight.mdsal.dom.spi.query.EagerDOMQueryResult;
29 import org.opendaylight.yangtools.concepts.Delegator;
30 import org.opendaylight.yangtools.concepts.Identifiable;
31 import org.opendaylight.yangtools.yang.binding.DataObject;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 abstract class AbstractForwardedTransaction<T extends DOMDataTreeTransaction> implements Delegator<T>,
38         Identifiable<Object> {
39     private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedTransaction.class);
40
41     private final @NonNull AdapterContext adapterContext;
42     private final @NonNull T delegate;
43
44     AbstractForwardedTransaction(final AdapterContext adapterContext, final T delegateTx) {
45         this.adapterContext = requireNonNull(adapterContext, "Codec must not be null");
46         this.delegate = requireNonNull(delegateTx, "Delegate must not be null");
47     }
48
49     @Override
50     public final Object getIdentifier() {
51         return delegate.getIdentifier();
52     }
53
54     @Override
55     public final T getDelegate() {
56         return delegate;
57     }
58
59     protected final <S extends DOMDataTreeTransaction> S getDelegateChecked(final Class<S> txType) {
60         checkState(txType.isInstance(delegate));
61         return txType.cast(delegate);
62     }
63
64     protected final AdapterContext adapterContext() {
65         return adapterContext;
66     }
67
68     protected final <D extends DataObject> @NonNull FluentFuture<Optional<D>> doRead(
69             final DOMDataTreeReadOperations readOps, final LogicalDatastoreType store,
70             final InstanceIdentifier<D> path) {
71         checkArgument(!path.isWildcarded(), "Invalid read of wildcarded path %s", path);
72
73         final CurrentAdapterSerializer codec = adapterContext.currentSerializer();
74         final YangInstanceIdentifier domPath = codec.toYangInstanceIdentifier(path);
75
76         return readOps.read(store, domPath)
77                 .transform(optData -> optData.map(domData -> (D) codec.fromNormalizedNode(domPath, domData).getValue()),
78                     MoreExecutors.directExecutor());
79     }
80
81     protected final @NonNull FluentFuture<Boolean> doExists(final DOMDataTreeReadOperations readOps,
82             final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
83         checkArgument(!path.isWildcarded(), "Invalid exists of wildcarded path %s", path);
84         return readOps.exists(store, adapterContext.currentSerializer().toYangInstanceIdentifier(path));
85     }
86
87     protected final <T extends @NonNull DataObject> @NonNull FluentFuture<QueryResult<T>> doExecute(
88             final DOMDataTreeReadOperations readOps, final @NonNull LogicalDatastoreType store,
89             final @NonNull QueryExpression<T> query) {
90         checkArgument(query instanceof DefaultQuery, "Unsupported query type %s", query);
91         final DefaultQuery<T> defaultQuery = (DefaultQuery<T>) query;
92
93         final FluentFuture<DOMQueryResult> domResult = readOps instanceof DOMDataTreeQueryOperations
94             ? ((DOMDataTreeQueryOperations) readOps).execute(store, defaultQuery.asDOMQuery())
95                 : fallbackExecute(readOps, store, defaultQuery.asDOMQuery());
96
97         return domResult.transform(defaultQuery::toQueryResult, MoreExecutors.directExecutor());
98     }
99
100     private static FluentFuture<DOMQueryResult> fallbackExecute(final @NonNull DOMDataTreeReadOperations readOps,
101             final @NonNull LogicalDatastoreType store, final @NonNull DOMQuery domQuery) {
102         LOG.trace("Fallback evaluation of {} on {}", domQuery, readOps);
103         return readOps.read(store, domQuery.getRoot())
104             .transform(
105                 node -> node.map(data -> DOMQueryEvaluator.evaluateOn(domQuery, data)).orElse(EagerDOMQueryResult.of()),
106                 // TODO: execute on a dedicated thread pool
107                 MoreExecutors.directExecutor());
108     }
109 }