Implement managed transactions
[mdsal.git] / binding / mdsal-binding-util / src / main / java / org / opendaylight / mdsal / binding / util / TransactionAdapter.java
1 /*
2  * Copyright © 2018 Red Hat, Inc. and others.
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.util;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.ForwardingObject;
14 import com.google.common.util.concurrent.FluentFuture;
15 import java.util.Optional;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.opendaylight.mdsal.binding.api.DataBroker;
18 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
19 import org.opendaylight.mdsal.binding.api.WriteTransaction;
20 import org.opendaylight.mdsal.common.api.CommitInfo;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.yangtools.yang.binding.DataObject;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
24
25 /**
26  * Adapter allowing managed, datastore-constrained transactions to be used with methods expecting
27  * generic {@link DataBroker} transactions.
28  *
29  * <p>The adapted transactions maintain the following constraints: they cannot be cancelled or
30  * submitted (only the transaction manager can do this), and they cannot access a logical datastore
31  * other than the one they were created for.
32  *
33  * @deprecated This is only intended for temporary use during complex migrations to managed transactions.
34  */
35 @Deprecated
36 public final class TransactionAdapter {
37     private TransactionAdapter() {
38     }
39
40     /**
41      * Adapts the given datastore-constrained read-write transaction to a generic read-write transaction.
42      *
43      * @param datastoreTx The transaction to adapt.
44      * @return The adapted transaction.
45      * @throws NullPointerException if the provided transaction is {@code null}.
46      */
47     public static ReadWriteTransaction toReadWriteTransaction(
48             TypedReadWriteTransaction<? extends Datastore> datastoreTx) {
49         if (datastoreTx instanceof TypedReadWriteTransactionImpl) {
50             TypedReadWriteTransactionImpl nonSubmitCancelableDatastoreReadWriteTransaction =
51                     (TypedReadWriteTransactionImpl) datastoreTx;
52             return new ReadWriteTransactionAdapter(nonSubmitCancelableDatastoreReadWriteTransaction.datastoreType,
53                     nonSubmitCancelableDatastoreReadWriteTransaction);
54         }
55         throw new IllegalArgumentException(
56                 "Unsupported TypedWriteTransaction implementation " + datastoreTx.getClass());
57     }
58
59     /**
60      * Adapts the given datastore-constrained write transaction to a generic write transaction. Note that this
61      * can be used to adapt a read-write transaction to a write transaction.
62      *
63      * @param datastoreTx The transaction to adapt.
64      * @return The adapted transaction.
65      */
66     public static WriteTransaction toWriteTransaction(TypedWriteTransaction<? extends Datastore> datastoreTx) {
67         if (datastoreTx instanceof TypedWriteTransactionImpl) {
68             TypedWriteTransactionImpl nonSubmitCancelableDatastoreWriteTransaction =
69                     (TypedWriteTransactionImpl) datastoreTx;
70             return new WriteTransactionAdapter(nonSubmitCancelableDatastoreWriteTransaction.datastoreType,
71                     nonSubmitCancelableDatastoreWriteTransaction);
72         }
73         throw new IllegalArgumentException(
74                 "Unsupported TypedWriteTransaction implementation " + datastoreTx.getClass());
75     }
76
77     // We want to subclass this class, even though it has a private constructor
78     @SuppressWarnings("FinalClass")
79     private static class WriteTransactionAdapter<D extends Datastore, T extends TypedWriteTransaction<D>>
80             extends ForwardingObject implements WriteTransaction {
81         private final LogicalDatastoreType datastoreType;
82         private final T delegate;
83
84         private WriteTransactionAdapter(LogicalDatastoreType datastoreType, T delegate) {
85             this.datastoreType = datastoreType;
86             this.delegate = delegate;
87         }
88
89         @Override
90         public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
91             checkStore(store);
92             delegate.put(path, data);
93         }
94
95         @Override
96         public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data,
97                 boolean createMissingParents) {
98             checkStore(store);
99             delegate.put(path, data, createMissingParents);
100         }
101
102         @Override
103         public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
104             checkStore(store);
105             delegate.merge(path, data);
106         }
107
108         @Override
109         public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data,
110                 boolean createMissingParents) {
111             checkStore(store);
112             delegate.merge(path, data, createMissingParents);
113         }
114
115         @Override
116         public boolean cancel() {
117             throw new UnsupportedOperationException("Managed transactions must not be cancelled");
118         }
119
120         @Override
121         public void delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
122             checkStore(store);
123             delegate.delete(path);
124         }
125
126         @Override
127         public @NonNull FluentFuture<? extends CommitInfo> commit() {
128             throw new UnsupportedOperationException("Managed transactions must not be committed");
129         }
130
131         void checkStore(LogicalDatastoreType store) {
132             checkArgument(datastoreType.equals(store), "Invalid datastore %s used instead of %s", store, datastoreType);
133         }
134
135         @Override
136         public Object getIdentifier() {
137             return delegate.getIdentifier();
138         }
139
140         @Override
141         protected T delegate() {
142             return delegate;
143         }
144     }
145
146     private static final class ReadWriteTransactionAdapter<D extends Datastore>
147             extends WriteTransactionAdapter<D, TypedReadWriteTransaction<D>> implements ReadWriteTransaction {
148         private ReadWriteTransactionAdapter(LogicalDatastoreType datastoreType, TypedReadWriteTransaction<D> delegate) {
149             super(datastoreType, delegate);
150         }
151
152         @Override
153         public <T extends DataObject> FluentFuture<Optional<T>> read(LogicalDatastoreType store,
154                 InstanceIdentifier<T> path) {
155             checkStore(store);
156             return delegate().read(path);
157         }
158     }
159 }