2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.md.sal.dom.broker.impl.compat;
10 import static com.google.common.base.Preconditions.checkNotNull;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.Iterator;
15 import java.util.List;
17 import java.util.Map.Entry;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.Future;
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.util.compat.DataNormalizationException;
25 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
26 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
27 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
28 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
29 import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
30 import org.opendaylight.yangtools.concepts.Delegator;
31 import org.opendaylight.yangtools.concepts.ListenerRegistration;
32 import org.opendaylight.yangtools.yang.common.RpcResult;
33 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
34 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
36 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
37 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
38 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
43 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 import com.google.common.base.Optional;
48 import com.google.common.base.Preconditions;
49 import com.google.common.collect.Iterables;
50 import com.google.common.util.concurrent.ListenableFuture;
52 public abstract class BackwardsCompatibleTransaction<T extends DOMDataReadTransaction> implements
53 DataModificationTransaction, Delegator<T> {
55 private static final Logger LOG = LoggerFactory.getLogger(BackwardsCompatibleTransaction.class);
57 private final T asyncTx;
58 private final DataNormalizer normalizer;
60 protected BackwardsCompatibleTransaction(final T asyncTx, final DataNormalizer normalizer) {
62 this.asyncTx = asyncTx;
63 this.normalizer = normalizer;
66 public static BackwardsCompatibleTransaction<?> readOnlyTransaction(final DOMDataReadTransaction readTx,
67 final DataNormalizer normalizer) {
69 return new BackwardsCompatibleTransaction<DOMDataReadTransaction>(readTx, normalizer) {
72 public TransactionStatus getStatus() {
73 return TransactionStatus.NEW;
77 public Future<RpcResult<TransactionStatus>> commit() {
78 getDelegate().close();
84 public static BackwardsCompatibleTransaction<?> readWriteTransaction(final DOMDataReadWriteTransaction rwTx,
85 final DataNormalizer normalizer) {
86 return new ReadWriteTransaction(rwTx, normalizer);
89 protected DataNormalizer getNormalizer() {
94 public T getDelegate() {
99 public CompositeNode readConfigurationData(final InstanceIdentifier legacyPath) {
101 InstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
103 ListenableFuture<Optional<NormalizedNode<?, ?>>> normalizedData = asyncTx.read(
104 LogicalDatastoreType.CONFIGURATION, normalizedPath);
107 return normalizer.toLegacy(normalizedPath, normalizedData.get().orNull());
108 } catch (InterruptedException | ExecutionException e) {
114 public CompositeNode readOperationalData(final InstanceIdentifier legacyPath) {
115 InstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
117 ListenableFuture<Optional<NormalizedNode<?, ?>>> normalizedData = asyncTx.read(
118 LogicalDatastoreType.OPERATIONAL, normalizedPath);
121 return normalizer.toLegacy(normalizedPath, normalizedData.get().orNull());
122 } catch (InterruptedException | ExecutionException e) {
128 public ListenerRegistration<DataTransactionListener> registerListener(final DataTransactionListener listener) {
129 throw new UnsupportedOperationException();
133 public Map<InstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
134 return Collections.emptyMap();
138 public Map<InstanceIdentifier, CompositeNode> getCreatedOperationalData() {
139 return Collections.emptyMap();
143 public Map<InstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
144 return Collections.emptyMap();
148 public Map<InstanceIdentifier, CompositeNode> getOriginalOperationalData() {
149 return Collections.emptyMap();
153 public Set<InstanceIdentifier> getRemovedConfigurationData() {
154 return Collections.emptySet();
158 public Set<InstanceIdentifier> getRemovedOperationalData() {
159 return Collections.emptySet();
163 public Map<InstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
164 return Collections.emptyMap();
168 public Map<InstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
169 return Collections.emptyMap();
173 public void putConfigurationData(final InstanceIdentifier path, final CompositeNode data) {
174 throw new UnsupportedOperationException();
178 public void putOperationalData(final InstanceIdentifier path, final CompositeNode data) {
179 throw new UnsupportedOperationException();
183 public void removeConfigurationData(final InstanceIdentifier path) {
184 throw new UnsupportedOperationException();
188 public void removeOperationalData(final InstanceIdentifier path) {
189 throw new UnsupportedOperationException();
193 public Object getIdentifier() {
194 return asyncTx.getIdentifier();
197 private static final class ReadWriteTransaction extends BackwardsCompatibleTransaction<DOMDataReadWriteTransaction> {
199 private TransactionStatus status = TransactionStatus.NEW;
201 protected ReadWriteTransaction(final DOMDataReadWriteTransaction asyncTx, final DataNormalizer normalizer) {
202 super(asyncTx, normalizer);
206 public TransactionStatus getStatus() {
211 public Future<RpcResult<TransactionStatus>> commit() {
212 Preconditions.checkState(status == TransactionStatus.NEW);
213 status = TransactionStatus.SUBMITED;
214 return getDelegate().commit();
218 public void putConfigurationData(final InstanceIdentifier legacyPath, final CompositeNode legacyData) {
219 checkNotNull(legacyPath, "Path MUST NOT be null.");
220 checkNotNull(legacyData, "Data for path %s MUST NOT be null",legacyData);
221 Entry<InstanceIdentifier, NormalizedNode<?, ?>> normalizedData = getNormalizer().toNormalized(legacyPath, legacyData);
222 putWithEnsuredParents(LogicalDatastoreType.CONFIGURATION, normalizedData.getKey(), normalizedData.getValue());
226 public void putOperationalData(final InstanceIdentifier legacyPath, final CompositeNode legacyData) {
227 checkNotNull(legacyPath, "Path MUST NOT be null.");
228 checkNotNull(legacyData, "Data for path %s MUST NOT be null",legacyData);
229 Entry<InstanceIdentifier, NormalizedNode<?, ?>> normalizedData = getNormalizer().toNormalized(legacyPath, legacyData);
230 putWithEnsuredParents(LogicalDatastoreType.OPERATIONAL, normalizedData.getKey(), normalizedData.getValue());
233 private void putWithEnsuredParents(final LogicalDatastoreType store, final InstanceIdentifier normalizedPath,
234 final NormalizedNode<?, ?> normalizedData) {
236 LOG.trace("write {}:{} ",store,normalizedPath);
238 List<PathArgument> currentArguments = new ArrayList<>();
239 DataNormalizationOperation<?> currentOp = getNormalizer().getRootOperation();
240 Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
241 while(iterator.hasNext()) {
242 PathArgument currentArg = iterator.next();
244 currentOp = currentOp.getChild(currentArg);
245 } catch (DataNormalizationException e) {
246 throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", normalizedPath), e);
248 currentArguments.add(currentArg);
249 InstanceIdentifier currentPath = new InstanceIdentifier(currentArguments);
250 boolean isPresent = getDelegate().read(store, currentPath).get().isPresent();
251 if(isPresent == false && iterator.hasNext()) {
252 getDelegate().put(store, currentPath, currentOp.createDefault(currentArg));
255 } catch (InterruptedException | ExecutionException e) {
256 LOG.error("Exception durring read.",e);
259 getDelegate().put(store, normalizedPath, normalizedData);
262 private boolean isAugmentationChild(final InstanceIdentifier normalizedPath) {
263 List<PathArgument> parentArgs = parentPath(normalizedPath).getPath();
264 if(parentArgs.isEmpty()) {
267 return Iterables.getLast(parentArgs) instanceof AugmentationIdentifier;
270 private void ensureParentNode(final LogicalDatastoreType store, final InstanceIdentifier normalizedPath,
271 final NormalizedNode<?, ?> normalizedData) {
272 InstanceIdentifier parentPath = parentPath(normalizedPath);
273 PathArgument parentType = Iterables.getLast(parentPath.getPath());
274 if(parentType instanceof AugmentationIdentifier) {
275 AugmentationNode node = Builders.augmentationBuilder()
276 .withNodeIdentifier((AugmentationIdentifier) parentType)
278 getDelegate().put(store, parentPath, node);
280 if(normalizedData instanceof MapEntryNode) {
281 MapNode mapNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(normalizedData.getNodeType())).build();
282 getDelegate().put(store, parentPath, mapNode);
283 } else if (normalizedData instanceof LeafSetNode<?>){
284 LeafSetNode<Object> leafNode = Builders.leafSetBuilder().withNodeIdentifier(new NodeIdentifier(normalizedData.getNodeType())).build();
285 getDelegate().put(store, parentPath, leafNode);
291 private InstanceIdentifier parentPath(final InstanceIdentifier normalizedPath) {
292 List<PathArgument> childArgs = normalizedPath.getPath();
293 return new InstanceIdentifier(childArgs.subList(0, childArgs.size() -1));
296 private boolean parentNodeDoesNotExists(final LogicalDatastoreType store, final InstanceIdentifier normalizedPath) {
298 return !getDelegate().read(store, parentPath(normalizedPath)).get().isPresent();
299 } catch (InterruptedException | ExecutionException e) {
300 throw new IllegalStateException(e);
305 public void removeConfigurationData(final InstanceIdentifier legacyPath) {
306 checkNotNull(legacyPath, "Path MUST NOT be null.");
307 getDelegate().delete(LogicalDatastoreType.CONFIGURATION, getNormalizer().toNormalized(legacyPath));
311 public void removeOperationalData(final InstanceIdentifier legacyPath) {
312 checkNotNull(legacyPath, "Path MUST NOT be null.");
313 getDelegate().delete(LogicalDatastoreType.OPERATIONAL, getNormalizer().toNormalized(legacyPath));