Merge "Fixed for bug 1197"
[controller.git] / opendaylight / md-sal / sal-dom-broker / src / main / java / org / opendaylight / controller / md / sal / dom / broker / impl / compat / BackwardsCompatibleTransaction.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.controller.md.sal.dom.broker.impl.compat;
9
10 import static com.google.common.base.Preconditions.checkNotNull;
11
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Map.Entry;
18 import java.util.Set;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.Future;
21
22 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
25 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
26 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
27 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
28 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
29 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
30 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
31 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
32 import org.opendaylight.yangtools.concepts.Delegator;
33 import org.opendaylight.yangtools.concepts.ListenerRegistration;
34 import org.opendaylight.yangtools.yang.common.RpcResult;
35 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
36 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
38 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 import com.google.common.base.Optional;
43 import com.google.common.base.Preconditions;
44 import com.google.common.util.concurrent.ListenableFuture;
45
46 public abstract class BackwardsCompatibleTransaction<T extends DOMDataReadTransaction> implements
47 DataModificationTransaction, Delegator<T> {
48
49     private static final Logger LOG = LoggerFactory.getLogger(BackwardsCompatibleTransaction.class);
50
51     private final T asyncTx;
52     private final DataNormalizer normalizer;
53
54     protected BackwardsCompatibleTransaction(final T asyncTx, final DataNormalizer normalizer) {
55         super();
56         this.asyncTx = asyncTx;
57         this.normalizer = normalizer;
58     }
59
60     public static BackwardsCompatibleTransaction<?> readOnlyTransaction(final DOMDataReadOnlyTransaction readTx,
61             final DataNormalizer normalizer) {
62
63         return new BackwardsCompatibleTransaction<DOMDataReadOnlyTransaction>(readTx, normalizer) {
64
65             @Override
66             public TransactionStatus getStatus() {
67                 return TransactionStatus.NEW;
68             }
69
70             @Override
71             public Future<RpcResult<TransactionStatus>> commit() {
72                 getDelegate().close();
73                 return null;
74             }
75         };
76     }
77
78     public static BackwardsCompatibleTransaction<?> readWriteTransaction(final DOMDataReadWriteTransaction rwTx,
79             final DataNormalizer normalizer) {
80         return new ReadWriteTransaction(rwTx, normalizer);
81     }
82
83     protected DataNormalizer getNormalizer() {
84         return normalizer;
85     }
86
87     @Override
88     public T getDelegate() {
89         return asyncTx;
90     };
91
92     @Override
93     public CompositeNode readConfigurationData(final YangInstanceIdentifier legacyPath) {
94
95         YangInstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
96
97         ListenableFuture<Optional<NormalizedNode<?, ?>>> normalizedData = asyncTx.read(
98                 LogicalDatastoreType.CONFIGURATION, normalizedPath);
99
100         try {
101             return normalizer.toLegacy(normalizedPath, normalizedData.get().orNull());
102         } catch (InterruptedException | ExecutionException e) {
103             return null;
104         }
105     }
106
107     @Override
108     public CompositeNode readOperationalData(final YangInstanceIdentifier legacyPath) {
109         YangInstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
110
111         ListenableFuture<Optional<NormalizedNode<?, ?>>> normalizedData = asyncTx.read(
112                 LogicalDatastoreType.OPERATIONAL, normalizedPath);
113
114         try {
115             return normalizer.toLegacy(normalizedPath, normalizedData.get().orNull());
116         } catch (InterruptedException | ExecutionException e) {
117             return null;
118         }
119     }
120
121     @Override
122     public ListenerRegistration<DataTransactionListener> registerListener(final DataTransactionListener listener) {
123         throw new UnsupportedOperationException();
124     }
125
126     @Override
127     public Map<YangInstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
128         return Collections.emptyMap();
129     }
130
131     @Override
132     public Map<YangInstanceIdentifier, CompositeNode> getCreatedOperationalData() {
133         return Collections.emptyMap();
134     }
135
136     @Override
137     public Map<YangInstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
138         return Collections.emptyMap();
139     }
140
141     @Override
142     public Map<YangInstanceIdentifier, CompositeNode> getOriginalOperationalData() {
143         return Collections.emptyMap();
144     }
145
146     @Override
147     public Set<YangInstanceIdentifier> getRemovedConfigurationData() {
148         return Collections.emptySet();
149     }
150
151     @Override
152     public Set<YangInstanceIdentifier> getRemovedOperationalData() {
153         return Collections.emptySet();
154     }
155
156     @Override
157     public Map<YangInstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
158         return Collections.emptyMap();
159     }
160
161     @Override
162     public Map<YangInstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
163         return Collections.emptyMap();
164     }
165
166     @Override
167     public void putConfigurationData(final YangInstanceIdentifier path, final CompositeNode data) {
168         throw new UnsupportedOperationException();
169     }
170
171     @Override
172     public void putOperationalData(final YangInstanceIdentifier path, final CompositeNode data) {
173         throw new UnsupportedOperationException();
174     }
175
176     @Override
177     public void removeConfigurationData(final YangInstanceIdentifier path) {
178         throw new UnsupportedOperationException();
179     }
180
181     @Override
182     public void removeOperationalData(final YangInstanceIdentifier path) {
183         throw new UnsupportedOperationException();
184     }
185
186     @Override
187     public Object getIdentifier() {
188         return asyncTx.getIdentifier();
189     }
190
191     private static final class ReadWriteTransaction extends BackwardsCompatibleTransaction<DOMDataReadWriteTransaction> {
192
193         private TransactionStatus status = TransactionStatus.NEW;
194
195         protected ReadWriteTransaction(final DOMDataReadWriteTransaction asyncTx, final DataNormalizer normalizer) {
196             super(asyncTx, normalizer);
197         }
198
199         @Override
200         public TransactionStatus getStatus() {
201             return status;
202         }
203
204         @Override
205         public Future<RpcResult<TransactionStatus>> commit() {
206             Preconditions.checkState(status == TransactionStatus.NEW);
207             status = TransactionStatus.SUBMITED;
208             return AbstractDataTransaction.convertToLegacyCommitFuture(getDelegate().submit());
209         }
210
211         @Override
212         public void putConfigurationData(final YangInstanceIdentifier legacyPath, final CompositeNode legacyData) {
213             checkNotNull(legacyPath, "Path MUST NOT be null.");
214             checkNotNull(legacyData, "Data for path %s MUST NOT be null",legacyData);
215             Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedData = getNormalizer().toNormalized(legacyPath, legacyData);
216             putWithEnsuredParents(LogicalDatastoreType.CONFIGURATION, normalizedData.getKey(), normalizedData.getValue());
217         }
218
219         @Override
220         public void putOperationalData(final YangInstanceIdentifier legacyPath, final CompositeNode legacyData) {
221             checkNotNull(legacyPath, "Path MUST NOT be null.");
222             checkNotNull(legacyData, "Data for path %s MUST NOT be null",legacyData);
223             Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedData = getNormalizer().toNormalized(legacyPath, legacyData);
224             putWithEnsuredParents(LogicalDatastoreType.OPERATIONAL, normalizedData.getKey(), normalizedData.getValue());
225         }
226
227         private void putWithEnsuredParents(final LogicalDatastoreType store, final YangInstanceIdentifier normalizedPath,
228                 final NormalizedNode<?, ?> normalizedData) {
229
230             LOG.trace("write {}:{} ",store,normalizedPath);
231             try {
232                 List<PathArgument> currentArguments = new ArrayList<>();
233                 DataNormalizationOperation<?> currentOp = getNormalizer().getRootOperation();
234                 Iterator<PathArgument> iterator = normalizedPath.getPathArguments().iterator();
235                 while(iterator.hasNext()) {
236                     PathArgument currentArg = iterator.next();
237                     try {
238                         currentOp = currentOp.getChild(currentArg);
239                     } catch (DataNormalizationException e) {
240                         throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", normalizedPath), e);
241                     }
242                     currentArguments.add(currentArg);
243                     YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(currentArguments);
244                     boolean isPresent = getDelegate().read(store, currentPath).get().isPresent();
245                     if(isPresent == false && iterator.hasNext()) {
246                         getDelegate().merge(store, currentPath, currentOp.createDefault(currentArg));
247                     }
248                 }
249             } catch (InterruptedException | ExecutionException e) {
250                 LOG.error("Exception durring read.",e);
251             }
252
253             getDelegate().put(store, normalizedPath, normalizedData);
254         }
255
256         @Override
257         public void removeConfigurationData(final YangInstanceIdentifier legacyPath) {
258             checkNotNull(legacyPath, "Path MUST NOT be null.");
259             getDelegate().delete(LogicalDatastoreType.CONFIGURATION, getNormalizer().toNormalized(legacyPath));
260         }
261
262         @Override
263         public void removeOperationalData(final YangInstanceIdentifier legacyPath) {
264             checkNotNull(legacyPath, "Path MUST NOT be null.");
265             getDelegate().delete(LogicalDatastoreType.OPERATIONAL, getNormalizer().toNormalized(legacyPath));
266         }
267     }
268 }