Bug 6037 - Check if delete request was successful
[netconf.git] / restconf / sal-rest-connector / src / main / java / org / opendaylight / restconf / restful / utils / PostDataTransactionUtil.java
1 /*
2  * Copyright (c) 2016 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.restconf.restful.utils;
9
10 import com.google.common.util.concurrent.CheckedFuture;
11 import java.net.URI;
12 import javax.ws.rs.core.Response;
13 import javax.ws.rs.core.UriBuilder;
14 import javax.ws.rs.core.UriInfo;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
17 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
18 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
19 import org.opendaylight.restconf.common.references.SchemaContextRef;
20 import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
21 import org.opendaylight.restconf.utils.parser.ParserIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
24 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
28 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
33 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
34 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * Util class to post data to DS
40  *
41  */
42 public final class PostDataTransactionUtil {
43
44     private static final Logger LOG = LoggerFactory.getLogger(PostDataTransactionUtil.class);
45
46     private PostDataTransactionUtil() {
47         throw new UnsupportedOperationException("Util class.");
48     }
49
50     /**
51      * Check mount point and prepare variables for post data
52      *
53      * @param uriInfo
54      *
55      * @param payload
56      *            - data
57      * @param transactionNode
58      *            - wrapper for transaction data
59      * @param schemaContextRef
60      *            - reference to actual {@link SchemaContext}
61      * @return {@link CheckedFuture}
62      */
63     public static Response postData(final UriInfo uriInfo, final NormalizedNodeContext payload,
64             final TransactionVarsWrapper transactionNode, final SchemaContextRef schemaContextRef) {
65         final CheckedFuture<Void, TransactionCommitFailedException> future = submitData(
66                 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData(),
67                 transactionNode, schemaContextRef.get());
68         final URI location = PostDataTransactionUtil.resolveLocation(uriInfo, transactionNode, schemaContextRef);
69         final ResponseFactory dataFactory = new ResponseFactory(
70                 ReadDataTransactionUtil.readData(RestconfDataServiceConstant.ReadData.CONFIG, transactionNode),
71                 location);
72         FutureCallbackTx.addCallback(future, RestconfDataServiceConstant.PostData.POST_TX_TYPE, dataFactory);
73         return dataFactory.build();
74     }
75
76     /**
77      * Post data by type
78      *
79      * @param path
80      *            - path
81      * @param data
82      *            - data
83      * @param transactionNode
84      *            - wrapper for data to transaction
85      * @param schemaContext
86      *            - schema context of data
87      * @return {@link CheckedFuture}
88      */
89     private static CheckedFuture<Void, TransactionCommitFailedException> submitData(final YangInstanceIdentifier path,
90             final NormalizedNode<?, ?> data, final TransactionVarsWrapper transactionNode,
91             final SchemaContext schemaContext) {
92         final DOMDataReadWriteTransaction transaction = transactionNode.getTransaction();
93         final NormalizedNode<?, ?> node = ImmutableNodes.fromInstanceId(schemaContext, path);
94         transaction.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(node.getIdentifier()), node);
95         TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
96
97         if (data instanceof MapNode) {
98             for (final MapEntryNode child : ((MapNode) data).getValue()) {
99                 putChild(child, transaction, path);
100             }
101         } else if (data instanceof AugmentationNode) {
102             for (final DataContainerChild<? extends PathArgument, ?> child : ((AugmentationNode) data).getValue()) {
103                 putChild(child, transaction, path);
104             }
105         } else if (data instanceof ChoiceNode) {
106             for (final DataContainerChild<? extends PathArgument, ?> child : ((ChoiceNode) data).getValue()) {
107                 putChild(child, transaction, path);
108             }
109         } else if (data instanceof LeafSetNode<?>) {
110             for (final LeafSetEntryNode<?> child : ((LeafSetNode<?>) data).getValue()) {
111                 putChild(child, transaction, path);
112             }
113         } else if (data instanceof ContainerNode) {
114             for (final DataContainerChild<? extends PathArgument, ?> child : ((ContainerNode) data).getValue()) {
115                 putChild(child, transaction, path);
116             }
117         }
118         return transaction.submit();
119     }
120
121     /**
122      * Prepare data for submit
123      *
124      * @param child
125      *            - data
126      * @param readWriteTx
127      *            - transaction
128      * @param path
129      *            - path to data
130      */
131     private static void putChild(final NormalizedNode<?, ?> child, final DOMDataReadWriteTransaction readWriteTx,
132             final YangInstanceIdentifier path) {
133         final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
134         TransactionUtil.checkItemDoesNotExists(readWriteTx, LogicalDatastoreType.CONFIGURATION, childPath,
135                 RestconfDataServiceConstant.PostData.POST_TX_TYPE);
136         readWriteTx.put(LogicalDatastoreType.CONFIGURATION, childPath, child);
137     }
138
139     /**
140      * Get location from {@link YangInstanceIdentifier} and {@link UriInfo}
141      *
142      * @param uriInfo
143      *            - uri info
144      * @param transactionNode
145      *            - wrapper for data of transaction
146      * @param schemaContextRef
147      *            -reference to {@link SchemaContext}
148      * @return {@link URI}
149      */
150     private static URI resolveLocation(final UriInfo uriInfo, final TransactionVarsWrapper transactionNode,
151             final SchemaContextRef schemaContextRef) {
152         if (uriInfo == null) {
153             return null;
154         }
155
156         final UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
157         uriBuilder.path("data");
158         uriBuilder.path(ParserIdentifier.stringFromYangInstanceIdentifier(transactionNode.getInstanceIdentifier().getInstanceIdentifier(),
159                 schemaContextRef.get()));
160
161         return uriBuilder.build();
162     }
163 }