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.restful.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.netconf.sal.restconf.impl.RestconfDocumentedException;
22 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
23 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
24 import org.opendaylight.restconf.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.ListSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.Module;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * Util class for common methods of transactions
39 public final class TransactionUtil {
41 private final static Logger LOG = LoggerFactory.getLogger(TransactionUtil.class);
43 private TransactionUtil() {
44 throw new UnsupportedOperationException("Util class");
48 * Merged parents of data
52 * @param schemaContext
53 * - {@link SchemaContext}
57 public static void ensureParentsByMerge(final YangInstanceIdentifier path, final SchemaContext schemaContext,
58 final DOMDataWriteTransaction writeTx) {
59 final List<PathArgument> normalizedPathWithoutChildArgs = new ArrayList<>();
60 boolean hasList = false;
61 YangInstanceIdentifier rootNormalizedPath = null;
63 final Iterator<PathArgument> it = path.getPathArguments().iterator();
64 final Module module = schemaContext.findModuleByNamespaceAndRevision(
65 path.getLastPathArgument().getNodeType().getModule().getNamespace(),
66 path.getLastPathArgument().getNodeType().getModule().getRevision());
68 while (it.hasNext()) {
69 final PathArgument pathArgument = it.next();
70 if (rootNormalizedPath == null) {
71 rootNormalizedPath = YangInstanceIdentifier.create(pathArgument);
74 normalizedPathWithoutChildArgs.add(pathArgument);
75 if (module.getDataChildByName(pathArgument.getNodeType()) instanceof ListSchemaNode) {
80 if (normalizedPathWithoutChildArgs.isEmpty()) {
84 Preconditions.checkArgument(rootNormalizedPath != null, "Empty path received");
85 final NormalizedNode<?, ?> parentStructure = ImmutableNodes.fromInstanceId(schemaContext,
86 YangInstanceIdentifier.create(normalizedPathWithoutChildArgs));
87 writeTx.merge(LogicalDatastoreType.CONFIGURATION, rootNormalizedPath, parentStructure);
92 * Check if items already exists at specified {@code path}. Throws {@link RestconfDocumentedException} if
93 * data does NOT already exists.
94 * @param transactionChain Transaction chain
95 * @param rWTransaction Transaction
96 * @param store Datastore
97 * @param path Path to be checked
98 * @param operationType Type of operation (READ, POST, PUT, DELETE...)
100 public static void checkItemExists(final DOMTransactionChain transactionChain,
101 final DOMDataReadWriteTransaction rWTransaction,
102 final LogicalDatastoreType store, final YangInstanceIdentifier path,
103 final String operationType) {
104 final CheckedFuture<Boolean, ReadFailedException> future = rWTransaction.exists(store, path);
105 final FutureDataFactory<Boolean> response = new FutureDataFactory<>();
107 FutureCallbackTx.addCallback(future, operationType, response);
109 if (!response.result) {
110 // close transaction and reset transaction chain
111 rWTransaction.cancel();
112 RestConnectorProvider.resetTransactionChainForAdapaters(transactionChain);
115 final String errMsg = "Operation via Restconf was not executed because data does not exist";
116 LOG.trace("{}:{}", errMsg, path);
117 throw new RestconfDocumentedException(
118 "Data does not exist", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, path);
123 * Check if items do NOT already exists at specified {@code path}. Throws {@link RestconfDocumentedException} if
124 * data already exists.
125 * @param transactionChain Transaction chain
126 * @param rWTransaction Transaction
127 * @param store Datastore
128 * @param path Path to be checked
129 * @param operationType Type of operation (READ, POST, PUT, DELETE...)
131 public static void checkItemDoesNotExists(final DOMTransactionChain transactionChain,
132 final DOMDataReadWriteTransaction rWTransaction,
133 final LogicalDatastoreType store, final YangInstanceIdentifier path,
134 final String operationType) {
135 final CheckedFuture<Boolean, ReadFailedException> future = rWTransaction.exists(store, path);
136 final FutureDataFactory<Boolean> response = new FutureDataFactory<>();
138 FutureCallbackTx.addCallback(future, operationType, response);
140 if (response.result) {
141 // close transaction and reset transaction chain
142 rWTransaction.cancel();
143 RestConnectorProvider.resetTransactionChainForAdapaters(transactionChain);
146 final String errMsg = "Operation via Restconf was not executed because data already exists";
147 LOG.trace("{}:{}", errMsg, path);
148 throw new RestconfDocumentedException(
149 "Data already exists", ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS, path);