Bug 6325 - upgrade draft11 to draft15 - added timestamp & etag
[netconf.git] / restconf / sal-rest-connector / src / main / java / org / opendaylight / restconf / restful / services / impl / RestconfDataServiceImpl.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.services.impl;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import java.text.SimpleDateFormat;
13 import java.util.TimeZone;
14 import javax.ws.rs.core.Response;
15 import javax.ws.rs.core.UriInfo;
16 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
17 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
18 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
19 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
20 import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
21 import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
22 import org.opendaylight.netconf.sal.restconf.impl.PATCHContext;
23 import org.opendaylight.netconf.sal.restconf.impl.PATCHStatusContext;
24 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
25 import org.opendaylight.restconf.RestConnectorProvider;
26 import org.opendaylight.restconf.common.references.SchemaContextRef;
27 import org.opendaylight.restconf.handlers.SchemaContextHandler;
28 import org.opendaylight.restconf.handlers.TransactionChainHandler;
29 import org.opendaylight.restconf.restful.services.api.RestconfDataService;
30 import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
31 import org.opendaylight.restconf.restful.utils.DeleteDataTransactionUtil;
32 import org.opendaylight.restconf.restful.utils.PatchDataTransactionUtil;
33 import org.opendaylight.restconf.restful.utils.PostDataTransactionUtil;
34 import org.opendaylight.restconf.restful.utils.PutDataTransactionUtil;
35 import org.opendaylight.restconf.restful.utils.ReadDataTransactionUtil;
36 import org.opendaylight.restconf.restful.utils.RestconfDataServiceConstant;
37 import org.opendaylight.restconf.utils.parser.ParserIdentifier;
38 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
39 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * Implementation of {@link RestconfDataService}
45  */
46 public class RestconfDataServiceImpl implements RestconfDataService {
47
48     private final static Logger LOG = LoggerFactory.getLogger(RestconfDataServiceImpl.class);
49
50     private final SchemaContextHandler schemaContextHandler;
51     private final TransactionChainHandler transactionChainHandler;
52
53     public RestconfDataServiceImpl(final SchemaContextHandler schemaContextHandler,
54             final TransactionChainHandler transactionChainHandler) {
55         this.schemaContextHandler = schemaContextHandler;
56         this.transactionChainHandler = transactionChainHandler;
57     }
58
59     @Override
60     public Response readData(final String identifier, final UriInfo uriInfo) {
61         Preconditions.checkNotNull(identifier);
62         final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
63
64         final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
65                 schemaContextRef.get());
66         final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
67         final String value = uriInfo.getQueryParameters().getFirst(RestconfDataServiceConstant.CONTENT);
68
69         DOMTransactionChain transaction = null;
70         if (mountPoint == null) {
71             transaction = this.transactionChainHandler.get();
72         } else {
73             transaction = transactionOfMountPoint(mountPoint);
74         }
75         final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint,
76                 transaction);
77         final NormalizedNode<?, ?> node = ReadDataTransactionUtil.readData(value, transactionNode);
78         final SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
79         dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
80         final String etag = '"' + node.getNodeType().getModule().getFormattedRevision()
81                 + node.getNodeType().getLocalName() + '"';
82         Response resp = null;
83         if ((value == null) || value.contains(RestconfDataServiceConstant.ReadData.CONFIG)) {
84             resp = Response.status(200).entity(new NormalizedNodeContext(instanceIdentifier, node)).header("ETag", etag)
85                     .header("Last-Modified", dateFormatGmt.toString()).build();
86         } else {
87             resp = Response.status(200).entity(new NormalizedNodeContext(instanceIdentifier, node)).build();
88         }
89         return resp;
90     }
91
92     @Override
93     public Response putData(final String identifier, final NormalizedNodeContext payload) {
94         Preconditions.checkNotNull(identifier);
95         Preconditions.checkNotNull(payload);
96
97         final InstanceIdentifierContext<? extends SchemaNode> iid = payload
98                 .getInstanceIdentifierContext();
99
100         PutDataTransactionUtil.validInputData(iid.getSchemaNode(), payload);
101         PutDataTransactionUtil.validTopLevelNodeName(iid.getInstanceIdentifier(), payload);
102         PutDataTransactionUtil.validateListKeysEqualityInPayloadAndUri(payload);
103
104         final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
105         DOMTransactionChain transaction = null;
106         SchemaContextRef ref = null;
107         if (mountPoint == null) {
108             transaction = this.transactionChainHandler.get();
109             ref = new SchemaContextRef(this.schemaContextHandler.get());
110         } else {
111             transaction = transactionOfMountPoint(mountPoint);
112             ref = new SchemaContextRef(mountPoint.getSchemaContext());
113         }
114
115         final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(
116                 payload.getInstanceIdentifierContext(), mountPoint, transaction);
117         return PutDataTransactionUtil.putData(payload, ref, transactionNode);
118     }
119
120     @Override
121     public Response postData(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) {
122         return postData(payload, uriInfo);
123     }
124
125     @Override
126     public Response postData(final NormalizedNodeContext payload, final UriInfo uriInfo) {
127         Preconditions.checkNotNull(payload);
128
129         final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
130         DOMTransactionChain transaction = null;
131         SchemaContextRef ref = null;
132         if (mountPoint == null) {
133             transaction = this.transactionChainHandler.get();
134             ref = new SchemaContextRef(this.schemaContextHandler.get());
135         } else {
136             transaction = transactionOfMountPoint(mountPoint);
137             ref = new SchemaContextRef(mountPoint.getSchemaContext());
138         }
139         final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(
140                 payload.getInstanceIdentifierContext(), mountPoint, transaction);
141         return PostDataTransactionUtil.postData(uriInfo, payload, transactionNode, ref);
142     }
143
144     @Override
145     public Response deleteData(final String identifier) {
146         final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
147         final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
148                 schemaContextRef.get());
149
150         final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
151         final DOMTransactionChain transaction;
152         if (mountPoint == null) {
153             transaction = this.transactionChainHandler.get();
154         } else {
155             transaction = transactionOfMountPoint(mountPoint);
156         }
157
158         final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint,
159                 transaction);
160         return DeleteDataTransactionUtil.deleteData(transactionNode);
161     }
162
163     @Override
164     public PATCHStatusContext patchData(final String identifier, final PATCHContext context, final UriInfo uriInfo) {
165         Preconditions.checkNotNull(identifier);
166         return patchData(context, uriInfo);
167     }
168
169     @Override
170     public PATCHStatusContext patchData(final PATCHContext context, final UriInfo uriInfo) {
171         Preconditions.checkNotNull(context);
172         final DOMMountPoint mountPoint = context.getInstanceIdentifierContext().getMountPoint();
173
174         final DOMTransactionChain transaction;
175         final SchemaContextRef ref;
176         if (mountPoint == null) {
177             transaction = this.transactionChainHandler.get();
178             ref = new SchemaContextRef(this.schemaContextHandler.get());
179         } else {
180             transaction = transactionOfMountPoint(mountPoint);
181             ref = new SchemaContextRef(mountPoint.getSchemaContext());
182         }
183
184         final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(
185                 context.getInstanceIdentifierContext(), mountPoint, transaction);
186
187         return PatchDataTransactionUtil.patchData(context, transactionNode, ref);
188     }
189
190     /**
191      * Prepare transaction to read data of mount point, if these data are
192      * present.
193      * @param mountPoint
194      * @return {@link DOMDataReadWriteTransaction}
195      */
196     private static DOMTransactionChain transactionOfMountPoint(final DOMMountPoint mountPoint) {
197         final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
198         if (domDataBrokerService.isPresent()) {
199             return domDataBrokerService.get().createTransactionChain(RestConnectorProvider.transactionListener);
200         } else {
201             final String errMsg = "DOM data broker service isn't available for mount point "
202                     + mountPoint.getIdentifier();
203             LOG.warn(errMsg);
204             throw new RestconfDocumentedException(errMsg);
205         }
206     }
207 }