2 * Copyright (c) 2016 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
9 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
18 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
19 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
20 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
21 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
22 import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
23 import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
24 import org.opendaylight.restconf.nb.rfc8040.RestConnectorProvider;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
27 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
28 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
29 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
34 * Util class for common methods of transactions.
37 public final class TransactionUtil {
39 private static final Logger LOG = LoggerFactory.getLogger(TransactionUtil.class);
41 private TransactionUtil() {
42 throw new UnsupportedOperationException("Util class");
46 * Merged parents of data.
50 * @param schemaContext
51 * {@link SchemaContext}
55 public static void ensureParentsByMerge(final YangInstanceIdentifier path, final SchemaContext schemaContext,
56 final DOMDataWriteTransaction writeTx) {
57 final List<PathArgument> normalizedPathWithoutChildArgs = new ArrayList<>();
58 YangInstanceIdentifier rootNormalizedPath = null;
60 final Iterator<PathArgument> it = path.getPathArguments().iterator();
62 while (it.hasNext()) {
63 final PathArgument pathArgument = it.next();
64 if (rootNormalizedPath == null) {
65 rootNormalizedPath = YangInstanceIdentifier.create(pathArgument);
69 normalizedPathWithoutChildArgs.add(pathArgument);
73 if (normalizedPathWithoutChildArgs.isEmpty()) {
77 Preconditions.checkArgument(rootNormalizedPath != null, "Empty path received");
79 final NormalizedNode<?, ?> parentStructure = ImmutableNodes.fromInstanceId(schemaContext,
80 YangInstanceIdentifier.create(normalizedPathWithoutChildArgs));
81 writeTx.merge(LogicalDatastoreType.CONFIGURATION, rootNormalizedPath, parentStructure);
85 * Check if items already exists at specified {@code path}. Throws {@link RestconfDocumentedException} if
86 * data does NOT already exists.
87 * @param transactionChain Transaction chain
88 * @param rwTransaction Transaction
89 * @param store Datastore
90 * @param path Path to be checked
91 * @param operationType Type of operation (READ, POST, PUT, DELETE...)
93 public static void checkItemExists(final DOMTransactionChain transactionChain,
94 final DOMDataReadWriteTransaction rwTransaction,
95 final LogicalDatastoreType store, final YangInstanceIdentifier path,
96 final String operationType) {
97 final CheckedFuture<Boolean, ReadFailedException> future = rwTransaction.exists(store, path);
98 final FutureDataFactory<Boolean> response = new FutureDataFactory<>();
100 FutureCallbackTx.addCallback(future, operationType, response);
102 if (!response.result) {
103 // close transaction and reset transaction chain
104 rwTransaction.cancel();
105 RestConnectorProvider.resetTransactionChainForAdapaters(transactionChain);
108 final String errMsg = "Operation via Restconf was not executed because data does not exist";
109 LOG.trace("{}:{}", errMsg, path);
110 throw new RestconfDocumentedException(
111 "Data does not exist", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, path);
116 * Check if items do NOT already exists at specified {@code path}. Throws {@link RestconfDocumentedException} if
117 * data already exists.
118 * @param transactionChain Transaction chain
119 * @param rwTransaction Transaction
120 * @param store Datastore
121 * @param path Path to be checked
122 * @param operationType Type of operation (READ, POST, PUT, DELETE...)
124 public static void checkItemDoesNotExists(final DOMTransactionChain transactionChain,
125 final DOMDataReadWriteTransaction rwTransaction,
126 final LogicalDatastoreType store, final YangInstanceIdentifier path,
127 final String operationType) {
128 final CheckedFuture<Boolean, ReadFailedException> future = rwTransaction.exists(store, path);
129 final FutureDataFactory<Boolean> response = new FutureDataFactory<>();
131 FutureCallbackTx.addCallback(future, operationType, response);
133 if (response.result) {
134 // close transaction and reset transaction chain
135 rwTransaction.cancel();
136 RestConnectorProvider.resetTransactionChainForAdapaters(transactionChain);
139 final String errMsg = "Operation via Restconf was not executed because data already exists";
140 LOG.trace("{}:{}", errMsg, path);
141 throw new RestconfDocumentedException(
142 "Data already exists", ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS, path);