Remove DataChangeListener and friends
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / databroker / compat / LegacyDOMDataBrokerAdapter.java
1 /*
2  * Copyright (c) 2017 Inocybe Technologies 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.controller.cluster.databroker.compat;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.ForwardingObject;
13 import com.google.common.collect.ImmutableMap;
14 import com.google.common.collect.ImmutableMap.Builder;
15 import com.google.common.util.concurrent.CheckedFuture;
16 import com.google.common.util.concurrent.FluentFuture;
17 import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.MoreExecutors;
19 import com.google.common.util.concurrent.SettableFuture;
20 import java.util.Map;
21 import java.util.concurrent.atomic.AtomicReference;
22 import javax.annotation.Nonnull;
23 import org.opendaylight.controller.cluster.databroker.AbstractDOMBroker;
24 import org.opendaylight.controller.cluster.datastore.compat.LegacyDOMStoreAdapter;
25 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.DataStoreUnavailableException;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
29 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
30 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
31 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
32 import org.opendaylight.controller.md.sal.dom.api.ClusteredDOMDataTreeChangeListener;
33 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
34 import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension;
35 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
36 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
37 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
38 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
39 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeCommitCohortRegistry;
40 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
41 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
42 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
43 import org.opendaylight.mdsal.common.api.CommitInfo;
44 import org.opendaylight.mdsal.common.api.MappingCheckedFuture;
45 import org.opendaylight.mdsal.dom.api.DOMDataTreeCommitCohort;
46 import org.opendaylight.mdsal.dom.api.DOMDataTreeCommitCohortRegistration;
47 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
48 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
49 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
50 import org.opendaylight.yangtools.concepts.ListenerRegistration;
51 import org.opendaylight.yangtools.util.concurrent.ExceptionMapper;
52 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
53 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
54
55 /**
56  * Adapter between the legacy controller API-based DOMDataBroker and the mdsal API-based DOMDataBroker.
57  *
58  * @author Thomas Pantelis
59  */
60 public class LegacyDOMDataBrokerAdapter extends ForwardingObject implements DOMDataBroker {
61     private static final ExceptionMapper<TransactionCommitFailedException> COMMIT_EX_MAPPER =
62             new ExceptionMapper<TransactionCommitFailedException>("commit", TransactionCommitFailedException.class) {
63         @Override
64         protected TransactionCommitFailedException newWithCause(String message, Throwable cause) {
65             if (cause instanceof org.opendaylight.mdsal.common.api.OptimisticLockFailedException) {
66                 return new OptimisticLockFailedException(cause.getMessage(), cause.getCause());
67             } else if (cause instanceof org.opendaylight.mdsal.common.api.TransactionCommitFailedException) {
68                 Throwable rootCause = cause.getCause();
69                 if (rootCause instanceof org.opendaylight.mdsal.common.api.DataStoreUnavailableException) {
70                     rootCause = new DataStoreUnavailableException(rootCause.getMessage(), rootCause.getCause());
71                 }
72
73                 return new TransactionCommitFailedException(cause.getMessage(), rootCause);
74             }
75
76             return new TransactionCommitFailedException(message, cause);
77         }
78     };
79
80     private final AbstractDOMBroker delegate;
81     private final Map<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> extensions;
82
83     public LegacyDOMDataBrokerAdapter(AbstractDOMBroker delegate) {
84         this.delegate = delegate;
85
86         Map<Class<? extends org.opendaylight.mdsal.dom.api.DOMDataBrokerExtension>,
87             org.opendaylight.mdsal.dom.api.DOMDataBrokerExtension> delegateExtensions =
88                 delegate.getSupportedExtensions();
89
90         Builder<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> extBuilder = ImmutableMap.builder();
91         final org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService delegateTreeChangeService =
92                 (org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService) delegateExtensions.get(
93                         org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService.class);
94         if (delegateTreeChangeService != null) {
95             extBuilder.put(DOMDataTreeChangeService.class, new DOMDataTreeChangeService() {
96                 @Override
97                 public <L extends DOMDataTreeChangeListener> ListenerRegistration<L> registerDataTreeChangeListener(
98                         DOMDataTreeIdentifier treeId, final L listener) {
99                     final org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener delegateListener;
100                     if (listener instanceof ClusteredDOMDataTreeChangeListener) {
101                         delegateListener = (org.opendaylight.mdsal.dom.api.ClusteredDOMDataTreeChangeListener)
102                             changes -> listener.onDataTreeChanged(changes);
103                     } else {
104                         delegateListener = changes -> listener.onDataTreeChanged(changes);
105                     }
106
107                     final ListenerRegistration<org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener> reg =
108                         delegateTreeChangeService.registerDataTreeChangeListener(
109                             new org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier(convert(treeId.getDatastoreType()),
110                                     treeId.getRootIdentifier()), delegateListener);
111
112                     return new ListenerRegistration<L>() {
113                         @Override
114                         public L getInstance() {
115                             return listener;
116                         }
117
118                         @Override
119                         public void close() {
120                             reg.close();
121                         }
122                     };
123                 }
124             });
125         }
126
127         final org.opendaylight.mdsal.dom.api.DOMDataTreeCommitCohortRegistry delegateCohortRegistry =
128                 (org.opendaylight.mdsal.dom.api.DOMDataTreeCommitCohortRegistry) delegateExtensions.get(
129                         org.opendaylight.mdsal.dom.api.DOMDataTreeCommitCohortRegistry.class);
130         if (delegateCohortRegistry != null) {
131             extBuilder.put(DOMDataTreeCommitCohortRegistry.class, new DOMDataTreeCommitCohortRegistry() {
132                 @Override
133                 public <T extends DOMDataTreeCommitCohort> DOMDataTreeCommitCohortRegistration<T> registerCommitCohort(
134                         org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier path, T cohort) {
135                     return delegateCohortRegistry.registerCommitCohort(path, cohort);
136                 }
137             });
138         }
139
140         extensions = extBuilder.build();
141     }
142
143     @Override
144     protected AbstractDOMBroker delegate() {
145         return delegate;
146     }
147
148     @Override
149     public Map<Class<? extends DOMDataBrokerExtension>, DOMDataBrokerExtension> getSupportedExtensions() {
150         return extensions;
151     }
152
153     @Override
154     public DOMDataReadOnlyTransaction newReadOnlyTransaction() {
155         return new DOMDataReadOnlyTransactionAdapter(delegate().newReadOnlyTransaction());
156     }
157
158     @Override
159     public DOMDataReadWriteTransaction newReadWriteTransaction() {
160         return new DOMDataTransactionAdapter(delegate().newReadWriteTransaction());
161     }
162
163     @Override
164     public DOMDataWriteTransaction newWriteOnlyTransaction() {
165         return new DOMDataTransactionAdapter(delegate().newWriteOnlyTransaction());
166     }
167
168     @Override
169     public DOMTransactionChain createTransactionChain(final TransactionChainListener listener) {
170         AtomicReference<DOMTransactionChain> legacyChain = new AtomicReference<>();
171         org.opendaylight.mdsal.common.api.TransactionChainListener delegateListener =
172                 new org.opendaylight.mdsal.common.api.TransactionChainListener() {
173             @SuppressWarnings("rawtypes")
174             @Override
175             public void onTransactionChainFailed(final org.opendaylight.mdsal.common.api.TransactionChain<?, ?> chain,
176                     final org.opendaylight.mdsal.common.api.AsyncTransaction<?, ?> transaction, final Throwable cause) {
177                 listener.onTransactionChainFailed(legacyChain.get(),
178                         (AsyncTransaction) () -> transaction.getIdentifier(),
179                             cause instanceof Exception ? COMMIT_EX_MAPPER.apply((Exception)cause) : cause);
180             }
181
182             @Override
183             public void onTransactionChainSuccessful(org.opendaylight.mdsal.common.api.TransactionChain<?, ?> chain) {
184                 listener.onTransactionChainSuccessful(legacyChain.get());
185             }
186         };
187
188         final org.opendaylight.mdsal.dom.api.DOMTransactionChain delegateChain =
189                 delegate().createTransactionChain(delegateListener);
190         legacyChain.set(new DOMTransactionChain() {
191             @Override
192             public DOMDataReadOnlyTransaction newReadOnlyTransaction() {
193                 return new DOMDataReadOnlyTransactionAdapter(delegateChain.newReadOnlyTransaction());
194             }
195
196             @Override
197             public DOMDataReadWriteTransaction newReadWriteTransaction() {
198                 return new DOMDataTransactionAdapter(delegateChain.newReadWriteTransaction());
199             }
200
201             @Override
202             public DOMDataWriteTransaction newWriteOnlyTransaction() {
203                 return new DOMDataTransactionAdapter(delegateChain.newWriteOnlyTransaction());
204             }
205
206             @Override
207             public void close() {
208                 delegateChain.close();
209             }
210         });
211
212         return legacyChain.get();
213     }
214
215     private static org.opendaylight.mdsal.common.api.LogicalDatastoreType convert(LogicalDatastoreType datastoreType) {
216         return org.opendaylight.mdsal.common.api.LogicalDatastoreType.valueOf(datastoreType.name());
217     }
218
219     private static class DOMDataTransactionAdapter implements DOMDataReadWriteTransaction {
220         private final DOMDataTreeReadTransaction readDelegate;
221         private final DOMDataTreeWriteTransaction writeDelegate;
222         private final Object identifier;
223
224         DOMDataTransactionAdapter(@Nonnull DOMDataTreeReadTransaction readDelegate) {
225             this.readDelegate = Preconditions.checkNotNull(readDelegate);
226             this.identifier = readDelegate.getIdentifier();
227             this.writeDelegate = null;
228         }
229
230         DOMDataTransactionAdapter(@Nonnull DOMDataTreeWriteTransaction writeDelegate) {
231             this.writeDelegate = Preconditions.checkNotNull(writeDelegate);
232             this.identifier = writeDelegate.getIdentifier();
233             this.readDelegate = null;
234         }
235
236         DOMDataTransactionAdapter(@Nonnull DOMDataTreeReadWriteTransaction rwDelegate) {
237             this.readDelegate = Preconditions.checkNotNull(rwDelegate);
238             this.writeDelegate = rwDelegate;
239             this.identifier = readDelegate.getIdentifier();
240         }
241
242         DOMDataTreeReadTransaction readDelegate() {
243             return readDelegate;
244         }
245
246         DOMDataTreeWriteTransaction writeDelegate() {
247             return writeDelegate;
248         }
249
250         @Override
251         public Object getIdentifier() {
252             return identifier;
253         }
254
255         @Override
256         public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(LogicalDatastoreType store,
257                 YangInstanceIdentifier path) {
258             return MappingCheckedFuture.create(readDelegate().read(convert(store), path),
259                     LegacyDOMStoreAdapter.READ_EX_MAPPER);
260         }
261
262         @Override
263         public CheckedFuture<Boolean, ReadFailedException> exists(LogicalDatastoreType store,
264                 YangInstanceIdentifier path) {
265             return MappingCheckedFuture.create(readDelegate().exists(convert(store), path),
266                     LegacyDOMStoreAdapter.READ_EX_MAPPER);
267         }
268
269         @Override
270         public void delete(LogicalDatastoreType store, YangInstanceIdentifier path) {
271             writeDelegate().delete(convert(store), path);
272         }
273
274         @Override
275         public void put(LogicalDatastoreType store, YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
276             writeDelegate().put(convert(store), path, data);
277         }
278
279         @Override
280         public void merge(LogicalDatastoreType store, YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
281             writeDelegate().merge(convert(store), path, data);
282         }
283
284         @Override
285         public boolean cancel() {
286             return writeDelegate().cancel();
287         }
288
289         @Override
290         public FluentFuture<? extends CommitInfo> commit() {
291             final SettableFuture<CommitInfo> resultFuture = SettableFuture.create();
292             writeDelegate().commit().addCallback(new FutureCallback<CommitInfo>() {
293                 @Override
294                 public void onSuccess(CommitInfo result) {
295                     resultFuture.set(result);
296                 }
297
298                 @Override
299                 public void onFailure(Throwable ex) {
300                     if (ex instanceof Exception) {
301                         resultFuture.setException(COMMIT_EX_MAPPER.apply((Exception)ex));
302                     } else {
303                         resultFuture.setException(ex);
304                     }
305                 }
306             }, MoreExecutors.directExecutor());
307
308             return resultFuture;
309         }
310     }
311
312     private static class DOMDataReadOnlyTransactionAdapter implements DOMDataReadOnlyTransaction {
313         private final DOMDataTransactionAdapter adapter;
314
315         DOMDataReadOnlyTransactionAdapter(DOMDataTreeReadTransaction delegateTx) {
316             adapter = new DOMDataTransactionAdapter(delegateTx);
317         }
318
319         @Override
320         public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(LogicalDatastoreType store,
321                 YangInstanceIdentifier path) {
322             return adapter.read(store, path);
323         }
324
325         @Override
326         public CheckedFuture<Boolean, ReadFailedException> exists(LogicalDatastoreType store,
327                 YangInstanceIdentifier path) {
328             return adapter.exists(store, path);
329         }
330
331         @Override
332         public Object getIdentifier() {
333             return adapter.getIdentifier();
334         }
335
336         @Override
337         public void close() {
338             adapter.readDelegate().close();
339         }
340     }
341 }