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
8 package org.opendaylight.restconf.restful.utils;
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.CheckedFuture;
13 import javax.ws.rs.core.Response;
14 import javax.ws.rs.core.UriBuilder;
15 import javax.ws.rs.core.UriInfo;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
18 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
19 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
20 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
21 import org.opendaylight.restconf.common.context.NormalizedNodeContext;
22 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
23 import org.opendaylight.restconf.common.references.SchemaContextRef;
24 import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
25 import org.opendaylight.restconf.utils.parser.ParserIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
33 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
34 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
36 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
41 * Util class to post data to DS.
43 * @deprecated move to splitted module restconf-nb-rfc8040
46 public final class PostDataTransactionUtil {
48 private static final Logger LOG = LoggerFactory.getLogger(PostDataTransactionUtil.class);
50 private PostDataTransactionUtil() {
51 throw new UnsupportedOperationException("Util class.");
55 * Check mount point and prepare variables for post data.
61 * @param transactionNode
62 * wrapper for transaction data
63 * @param schemaContextRef
64 * reference to actual {@link SchemaContext}
69 * @return {@link CheckedFuture}
71 public static Response postData(final UriInfo uriInfo, final NormalizedNodeContext payload,
72 final TransactionVarsWrapper transactionNode, final SchemaContextRef schemaContextRef, final String insert,
74 final CheckedFuture<Void, TransactionCommitFailedException> future = submitData(
75 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData(),
76 transactionNode, schemaContextRef.get(), insert, point);
77 final URI location = PostDataTransactionUtil.resolveLocation(uriInfo, transactionNode, schemaContextRef);
78 final ResponseFactory dataFactory = new ResponseFactory(null, location);
79 FutureCallbackTx.addCallback(future, RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory);
80 return dataFactory.build();
90 * @param transactionNode
91 * wrapper for data to transaction
92 * @param schemaContext
93 * schema context of data
98 * @return {@link CheckedFuture}
100 private static CheckedFuture<Void, TransactionCommitFailedException> submitData(final YangInstanceIdentifier path,
101 final NormalizedNode<?, ?> data, final TransactionVarsWrapper transactionNode,
102 final SchemaContext schemaContext, final String insert, final String point) {
103 final DOMTransactionChain domTransactionChain = transactionNode.getTransactionChain();
104 final DOMDataReadWriteTransaction newReadWriteTransaction = domTransactionChain.newReadWriteTransaction();
105 if (insert == null) {
106 makePost(path, data, schemaContext, domTransactionChain, newReadWriteTransaction);
107 return newReadWriteTransaction.submit();
109 final DataSchemaNode schemaNode = PutDataTransactionUtil.checkListAndOrderedType(schemaContext, path);
112 if (schemaNode instanceof ListSchemaNode) {
113 final NormalizedNode<?, ?> readData =
114 PutDataTransactionUtil.readList(path.getParent(), schemaContext, domTransactionChain,
116 final OrderedMapNode readList = (OrderedMapNode) readData;
117 if ((readList == null) || readList.getValue().isEmpty()) {
118 makePost(path, data, schemaContext, domTransactionChain, newReadWriteTransaction);
119 return newReadWriteTransaction.submit();
121 newReadWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION,
122 path.getParent().getParent());
123 simplePost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION, path, data,
124 schemaContext, domTransactionChain);
125 makePost(path, readData, schemaContext, domTransactionChain,
126 newReadWriteTransaction);
127 return newReadWriteTransaction.submit();
130 final NormalizedNode<?, ?> readData = PutDataTransactionUtil
131 .readList(path.getParent(), schemaContext, domTransactionChain, schemaNode);
133 final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
134 if ((readLeafList == null) || readLeafList.getValue().isEmpty()) {
135 makePost(path, data, schemaContext, domTransactionChain, newReadWriteTransaction);
136 return newReadWriteTransaction.submit();
138 newReadWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION,
139 path.getParent().getParent());
140 simplePost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION, path, data,
141 schemaContext, domTransactionChain);
142 makePost(path, readData, schemaContext, domTransactionChain, newReadWriteTransaction);
143 return newReadWriteTransaction.submit();
147 makePost(path, data, schemaContext, domTransactionChain, newReadWriteTransaction);
148 return newReadWriteTransaction.submit();
150 if (schemaNode instanceof ListSchemaNode) {
151 final NormalizedNode<?, ?> readData =
152 PutDataTransactionUtil.readList(path.getParent(), schemaContext, domTransactionChain,
154 final OrderedMapNode readList = (OrderedMapNode) readData;
155 if ((readList == null) || readList.getValue().isEmpty()) {
156 makePost(path, data, schemaContext, domTransactionChain, newReadWriteTransaction);
157 return newReadWriteTransaction.submit();
159 insertWithPointListPost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION, path,
160 data, schemaContext, point, readList, true, domTransactionChain);
161 return newReadWriteTransaction.submit();
164 final NormalizedNode<?, ?> readData =
165 PutDataTransactionUtil.readList(path.getParent(), schemaContext, domTransactionChain,
168 final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
169 if ((readLeafList == null) || readLeafList.getValue().isEmpty()) {
170 makePost(path, data, schemaContext, domTransactionChain, newReadWriteTransaction);
171 return newReadWriteTransaction.submit();
173 insertWithPointLeafListPost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION,
174 path, data, schemaContext, point, readLeafList, true, domTransactionChain);
175 return newReadWriteTransaction.submit();
179 if (schemaNode instanceof ListSchemaNode) {
180 final NormalizedNode<?, ?> readData =
181 PutDataTransactionUtil.readList(path.getParent(), schemaContext, domTransactionChain,
183 final OrderedMapNode readList = (OrderedMapNode) readData;
184 if ((readList == null) || readList.getValue().isEmpty()) {
185 makePost(path, data, schemaContext, domTransactionChain, newReadWriteTransaction);
186 return newReadWriteTransaction.submit();
188 insertWithPointListPost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION, path,
189 data, schemaContext, point, readList, false, domTransactionChain);
190 return newReadWriteTransaction.submit();
193 final NormalizedNode<?, ?> readData =
194 PutDataTransactionUtil.readList(path.getParent(), schemaContext, domTransactionChain,
197 final OrderedLeafSetNode<?> readLeafList = (OrderedLeafSetNode<?>) readData;
198 if ((readLeafList == null) || readLeafList.getValue().isEmpty()) {
199 makePost(path, data, schemaContext, domTransactionChain, newReadWriteTransaction);
200 return newReadWriteTransaction.submit();
202 insertWithPointLeafListPost(newReadWriteTransaction, LogicalDatastoreType.CONFIGURATION,
203 path, data, schemaContext, point, readLeafList, true, domTransactionChain);
204 return newReadWriteTransaction.submit();
208 throw new RestconfDocumentedException(
209 "Used bad value of insert parameter. Possible values are first, last, before or after, "
210 + "but was: " + insert);
215 private static void insertWithPointLeafListPost(final DOMDataReadWriteTransaction rwTransaction,
216 final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
217 final SchemaContext schemaContext, final String point, final OrderedLeafSetNode<?> readLeafList,
218 final boolean before, final DOMTransactionChain domTransactionChain) {
219 rwTransaction.delete(datastore, path.getParent().getParent());
220 final InstanceIdentifierContext<?> instanceIdentifier =
221 ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.absent());
222 int lastItemPosition = 0;
223 for (final LeafSetEntryNode<?> nodeChild : readLeafList.getValue()) {
224 if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
232 int lastInsertedPosition = 0;
233 final NormalizedNode<?, ?> emptySubtree =
234 ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent());
235 rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
236 for (final LeafSetEntryNode<?> nodeChild : readLeafList.getValue()) {
237 if (lastInsertedPosition == lastItemPosition) {
238 TransactionUtil.checkItemDoesNotExists(domTransactionChain, rwTransaction, datastore, path,
239 RestconfDataServiceConstant.PostData.POST_TX_TYPE);
240 rwTransaction.put(datastore, path, payload);
242 final YangInstanceIdentifier childPath = path.getParent().getParent().node(nodeChild.getIdentifier());
243 TransactionUtil.checkItemDoesNotExists(domTransactionChain, rwTransaction, datastore, childPath,
244 RestconfDataServiceConstant.PostData.POST_TX_TYPE);
245 rwTransaction.put(datastore, childPath, nodeChild);
246 lastInsertedPosition++;
250 private static void insertWithPointListPost(final DOMDataReadWriteTransaction rwTransaction,
251 final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
252 final SchemaContext schemaContext, final String point, final MapNode readList, final boolean before,
253 final DOMTransactionChain domTransactionChain) {
254 rwTransaction.delete(datastore, path.getParent().getParent());
255 final InstanceIdentifierContext<?> instanceIdentifier =
256 ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.absent());
257 int lastItemPosition = 0;
258 for (final MapEntryNode mapEntryNode : readList.getValue()) {
259 if (mapEntryNode.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
267 int lastInsertedPosition = 0;
268 final NormalizedNode<?, ?> emptySubtree =
269 ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent());
270 rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
271 for (final MapEntryNode mapEntryNode : readList.getValue()) {
272 if (lastInsertedPosition == lastItemPosition) {
273 TransactionUtil.checkItemDoesNotExists(domTransactionChain, rwTransaction, datastore, path,
274 RestconfDataServiceConstant.PostData.POST_TX_TYPE);
275 rwTransaction.put(datastore, path, payload);
277 final YangInstanceIdentifier childPath = path.getParent().getParent().node(mapEntryNode.getIdentifier());
278 TransactionUtil.checkItemDoesNotExists(domTransactionChain, rwTransaction, datastore, childPath,
279 RestconfDataServiceConstant.PostData.POST_TX_TYPE);
280 rwTransaction.put(datastore, childPath, mapEntryNode);
281 lastInsertedPosition++;
285 private static void makePost(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data,
286 final SchemaContext schemaContext, final DOMTransactionChain transactionChain,
287 final DOMDataReadWriteTransaction transaction) {
288 if (data instanceof MapNode) {
289 boolean merge = false;
290 for (final MapEntryNode child : ((MapNode) data).getValue()) {
291 final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
292 TransactionUtil.checkItemDoesNotExists(
293 transactionChain, transaction, LogicalDatastoreType.CONFIGURATION, childPath,
294 RestconfDataServiceConstant.PostData.POST_TX_TYPE);
297 TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
298 final NormalizedNode<?, ?> emptySubTree = ImmutableNodes.fromInstanceId(schemaContext, path);
299 transaction.merge(LogicalDatastoreType.CONFIGURATION,
300 YangInstanceIdentifier.create(emptySubTree.getIdentifier()), emptySubTree);
302 transaction.put(LogicalDatastoreType.CONFIGURATION, childPath, child);
305 TransactionUtil.checkItemDoesNotExists(
306 transactionChain, transaction, LogicalDatastoreType.CONFIGURATION, path,
307 RestconfDataServiceConstant.PostData.POST_TX_TYPE);
309 TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
310 transaction.put(LogicalDatastoreType.CONFIGURATION, path, data);
315 * Get location from {@link YangInstanceIdentifier} and {@link UriInfo}.
319 * @param transactionNode
320 * wrapper for data of transaction
321 * @param schemaContextRef
322 * reference to {@link SchemaContext}
323 * @return {@link URI}
325 private static URI resolveLocation(final UriInfo uriInfo, final TransactionVarsWrapper transactionNode,
326 final SchemaContextRef schemaContextRef) {
327 if (uriInfo == null) {
331 final UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
332 uriBuilder.path("data");
333 uriBuilder.path(ParserIdentifier
334 .stringFromYangInstanceIdentifier(transactionNode.getInstanceIdentifier().getInstanceIdentifier(),
335 schemaContextRef.get()));
337 return uriBuilder.build();
340 private static void simplePost(final DOMDataReadWriteTransaction rwTransaction,
341 final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
342 final SchemaContext schemaContext, final DOMTransactionChain transactionChain) {
343 TransactionUtil.checkItemDoesNotExists(transactionChain, rwTransaction, datastore, path,
344 RestconfDataServiceConstant.PostData.POST_TX_TYPE);
345 TransactionUtil.ensureParentsByMerge(path, schemaContext, rwTransaction);
346 rwTransaction.put(datastore, path, payload);