2 * ============LICENSE_START========================================== org.onap.music
3 * =================================================================== Copyright (c) 2017 AT&T
4 * Intellectual Property ===================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
6 * in compliance with the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software distributed under the License
11 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12 * or implied. See the License for the specific language governing permissions and limitations under
15 * ============LICENSE_END=============================================
16 * ====================================================================
18 package org.onap.music.rest;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
24 import java.util.UUID;
25 import javax.servlet.http.HttpServletResponse;
26 import javax.ws.rs.Consumes;
27 import javax.ws.rs.DELETE;
28 import javax.ws.rs.GET;
29 import javax.ws.rs.HeaderParam;
30 import javax.ws.rs.POST;
31 import javax.ws.rs.PUT;
32 import javax.ws.rs.Path;
33 import javax.ws.rs.PathParam;
34 import javax.ws.rs.Produces;
35 import javax.ws.rs.core.Context;
36 import javax.ws.rs.core.MediaType;
37 import javax.ws.rs.core.MultivaluedMap;
38 import javax.ws.rs.core.UriInfo;
39 import com.att.eelf.configuration.EELFLogger;
40 import com.att.eelf.configuration.EELFManager;
41 import org.onap.music.datastore.PreparedQueryObject;
42 import org.onap.music.datastore.jsonobjects.JsonDelete;
43 import org.onap.music.datastore.jsonobjects.JsonInsert;
44 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
45 import org.onap.music.datastore.jsonobjects.JsonTable;
46 import org.onap.music.datastore.jsonobjects.JsonUpdate;
47 import org.onap.music.eelf.logging.EELFLoggerDelegate;
48 import org.onap.music.exceptions.MusicServiceException;
49 import org.onap.music.main.CachingUtil;
50 import org.onap.music.main.MusicCore;
51 import org.onap.music.main.MusicCore.Condition;
52 import org.onap.music.main.MusicUtil;
53 import org.onap.music.main.ResultType;
54 import org.onap.music.main.ReturnType;
55 import org.onap.music.response.jsonobjects.JsonResponse;
56 import com.datastax.driver.core.DataType;
57 import com.datastax.driver.core.ResultSet;
58 import com.datastax.driver.core.Row;
59 import com.datastax.driver.core.TableMetadata;
60 import io.swagger.annotations.Api;
61 import io.swagger.annotations.ApiOperation;
62 import io.swagger.annotations.ApiParam;
64 @Path("/v{version: [0-9]+}/keyspaces")
65 @Api(value = "Data Api")
66 public class RestMusicDataAPI {
68 * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR
69 * version back from the client to the server, and from the server back to the client - This
70 * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR
71 * version (if not specified by the client on the request) - Contains a single position value
72 * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on
73 * request; however, this header should be provided if the client needs to take advantage of
74 * MINOR incremented version functionality - Is mandatory for the server on response
76 *** X-patchVersion *** - Used only to communicate a PATCH version in a response for
77 * troubleshooting purposes only, and will not be provided by the client on request - This will
78 * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version
79 * of the MAJOR (if not specified by the client on the request) - Contains a single position
80 * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the
83 *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the
84 * server on response, and shall include the entire version of the API (e.g. if the full version
85 * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are
86 * not using the latest version of the API
90 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class);
91 private static String xLatestVersion = "X-latestVersion";
93 private class RowIdentifier {
94 public String primarKeyValue;
95 public StringBuilder rowIdString;
96 public PreparedQueryObject queryObject;// the string with all the row
97 // identifiers separated by AND
99 public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
100 PreparedQueryObject queryObject) {
101 this.primarKeyValue = primaryKeyValue;
102 this.rowIdString = rowIdString;
103 this.queryObject = queryObject;
107 private String buildVersion(String major, String minor, String patch) {
109 major += "." + minor;
111 major += "." + patch;
118 * Create Keyspace REST
121 * @param keyspaceName
127 @ApiOperation(value = "Create Keyspace", response = String.class)
128 @Consumes(MediaType.APPLICATION_JSON)
129 @Produces(MediaType.APPLICATION_JSON)
130 public Map<String, Object> createKeySpace(
131 @ApiParam(value = "Major Version",
132 required = true) @PathParam("version") String version,
133 @ApiParam(value = "Minor Version",
134 required = false) @HeaderParam("X-minorVersion") String minorVersion,
135 @ApiParam(value = "Patch Version",
136 required = false) @HeaderParam("X-patchVersion") String patchVersion,
137 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
138 @ApiParam(value = "Application namespace",
139 required = true) @HeaderParam("ns") String ns,
140 @ApiParam(value = "userId",
141 required = true) @HeaderParam("userId") String userId,
142 @ApiParam(value = "Password",
143 required = true) @HeaderParam("password") String password,
144 JsonKeySpace kspObject,
145 @ApiParam(value = "Keyspace Name",
146 required = true) @PathParam("name") String keyspaceName,
147 @Context HttpServletResponse response) throws Exception {
148 Map<String, Object> resultMap = CachingUtil.verifyOnboarding(ns, userId, password);
149 response.addHeader(xLatestVersion, MusicUtil.getVersion());
150 if (!resultMap.isEmpty()) {
154 resultMap = MusicCore.autheticateUser(ns, userId, password, keyspaceName, aid,
156 String newAid = null;
157 if (!resultMap.isEmpty()) {
158 if (resultMap.containsKey("aid")) {
159 newAid = (String) resultMap.get("aid");
164 String consistency = MusicUtil.EVENTUAL;// for now this needs only
168 PreparedQueryObject queryObject = new PreparedQueryObject();
169 boolean result = false;
170 long start = System.currentTimeMillis();
171 Map<String, Object> replicationInfo = kspObject.getReplicationInfo();
172 String repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}";
173 queryObject.appendQueryString(
174 "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString);
175 if (kspObject.getDurabilityOfWrites() != null) {
176 queryObject.appendQueryString(
177 " AND durable_writes = " + kspObject.getDurabilityOfWrites());
180 queryObject.appendQueryString(";");
181 long end = System.currentTimeMillis();
182 logger.info(EELFLoggerDelegate.applicationLogger,
183 "Time taken for setting up query in create keyspace:" + (end - start));
186 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
187 logger.error(EELFLoggerDelegate.errorLogger, "resulta = " + result);
188 } catch (Exception e) {
189 logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
192 logger.debug("result = " + result);
194 resultMap.put("Status", String.valueOf(result));
195 resultMap.put("Exception", "Keyspace already exists. Please contact admin.");
196 if (resultMap.get("uuid").equals("new")) {
197 queryObject = new PreparedQueryObject();
198 queryObject.appendQueryString(
199 "DELETE FROM admin.keyspace_master where uuid = " + newAid);
200 queryObject.appendQueryString(";");
201 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
202 resultMap.remove("aid");
203 resultMap.remove("uuid");
207 queryObject = new PreparedQueryObject();
208 queryObject.appendQueryString(
209 "UPDATE admin.keyspace_master SET keyspace_name=?,password=?,is_api=null where uuid = ?;");
210 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(),
211 MusicUtil.DEFAULTKEYSPACENAME));
212 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), null));
213 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid));
214 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
215 resultMap.remove("aid");
216 resultMap.remove("uuid");
222 queryObject = new PreparedQueryObject();
223 queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId
224 + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;");
225 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
227 queryObject = new PreparedQueryObject();
228 queryObject.appendQueryString("GRANT ALL PERMISSIONS on KEYSPACE " + keyspaceName
230 queryObject.appendQueryString(";");
231 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
233 resultMap.remove("uuid");
234 resultMap.put("Exception", "Exception while creating user.");
237 } catch (Exception e) {
238 logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
240 resultMap.remove("uuid");
241 if (CachingUtil.isAAFApplication(ns))
242 resultMap.remove("aid");
243 resultMap.put("Status", String.valueOf(result));
251 * @param keyspaceName
257 @ApiOperation(value = "Delete Keyspace", response = String.class)
258 @Consumes(MediaType.APPLICATION_JSON)
259 @Produces(MediaType.APPLICATION_JSON)
260 public Map<String, Object> dropKeySpace(
261 @ApiParam(value = "Major Version",
262 required = true) @PathParam("version") String version,
263 @ApiParam(value = "Minor Version",
264 required = false) @HeaderParam("X-minorVersion") String minorVersion,
265 @ApiParam(value = "Patch Version",
266 required = false) @HeaderParam("X-patchVersion") String patchVersion,
267 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
268 @ApiParam(value = "Application namespace",
269 required = true) @HeaderParam("ns") String ns,
270 @ApiParam(value = "userId",
271 required = true) @HeaderParam("userId") String userId,
272 @ApiParam(value = "Password",
273 required = true) @HeaderParam("password") String password,
274 JsonKeySpace kspObject,
275 @ApiParam(value = "Keyspace Name",
276 required = true) @PathParam("name") String keyspaceName,
277 @Context HttpServletResponse response) throws Exception {
278 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password,
279 keyspaceName, aid, "dropKeySpace");
280 response.addHeader(xLatestVersion, MusicUtil.getVersion());
281 if (resultMap.containsKey("aid"))
282 resultMap.remove("aid");
283 if (!resultMap.isEmpty()) {
287 String consistency = MusicUtil.EVENTUAL;// for now this needs only
290 String appName = CachingUtil.getAppName(keyspaceName);
291 String uuid = CachingUtil.getUuidFromMusicCache(keyspaceName);
292 PreparedQueryObject pQuery = new PreparedQueryObject();
293 pQuery.appendQueryString(
294 "select count(*) as count from admin.keyspace_master where application_name=? allow filtering;");
295 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
296 Row row = MusicCore.get(pQuery).one();
297 long count = row.getLong(0);
300 resultMap.put("Exception", "Keyspace not found. Please make sure keyspace exists.");
302 } else if (count == 1) {
303 pQuery = new PreparedQueryObject();
304 pQuery.appendQueryString(
305 "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;");
306 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
307 MusicUtil.DEFAULTKEYSPACENAME));
308 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
309 MusicCore.nonKeyRelatedPut(pQuery, consistency);
311 pQuery = new PreparedQueryObject();
312 pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?");
313 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
314 MusicCore.nonKeyRelatedPut(pQuery, consistency);
317 PreparedQueryObject queryObject = new PreparedQueryObject();
318 queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";");
319 return new JsonResponse(MusicCore.nonKeyRelatedPut(queryObject, consistency), "", "")
332 @Path("/{keyspace}/tables/{tablename}")
333 @ApiOperation(value = "Create Table", response = String.class)
334 @Consumes(MediaType.APPLICATION_JSON)
335 @Produces(MediaType.APPLICATION_JSON)
336 public Map<String, Object> createTable(
337 @ApiParam(value = "Major Version",
338 required = true) @PathParam("version") String version,
339 @ApiParam(value = "Minor Version",
340 required = false) @HeaderParam("X-minorVersion") String minorVersion,
341 @ApiParam(value = "Patch Version",
342 required = false) @HeaderParam("X-patchVersion") String patchVersion,
343 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
344 @ApiParam(value = "Application namespace",
345 required = true) @HeaderParam("ns") String ns,
346 @ApiParam(value = "userId",
347 required = true) @HeaderParam("userId") String userId,
348 @ApiParam(value = "Password",
349 required = true) @HeaderParam("password") String password,
351 @ApiParam(value = "Keyspace Name",
352 required = true) @PathParam("keyspace") String keyspace,
353 @ApiParam(value = "Table Name",
354 required = true) @PathParam("tablename") String tablename,
355 @Context HttpServletResponse response) throws Exception {
356 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
358 response.addHeader(xLatestVersion, MusicUtil.getVersion());
359 if (resultMap.containsKey("aid"))
360 resultMap.remove("aid");
361 if (!resultMap.isEmpty()) {
364 String consistency = MusicUtil.EVENTUAL;
365 // for now this needs only eventual consistency
366 PreparedQueryObject queryObject = new PreparedQueryObject();
367 boolean result = false;
368 // first read the information about the table fields
369 Map<String, String> fields = tableObj.getFields();
370 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
373 for (Map.Entry<String, String> entry : fields.entrySet()) {
374 fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
375 if (entry.getKey().equals("PRIMARY KEY")) {
376 primaryKey = entry.getValue().substring(entry.getValue().indexOf('(') + 1);
377 primaryKey = primaryKey.substring(0, primaryKey.indexOf(')'));
379 if (counter == fields.size() - 1)
380 fieldsString.append(")");
382 fieldsString.append(",");
383 counter = counter + 1;
385 // information about the name-value style properties
386 Map<String, Object> propertiesMap = tableObj.getProperties();
387 StringBuilder propertiesString = new StringBuilder();
388 if (propertiesMap != null) {
390 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
391 Object ot = entry.getValue();
392 String value = ot + "";
393 if (ot instanceof String) {
394 value = "'" + value + "'";
395 } else if (ot instanceof Map) {
396 Map<String, Object> otMap = (Map<String, Object>) ot;
397 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
400 propertiesString.append(entry.getKey() + "=" + value + "");
401 if (counter != propertiesMap.size() - 1)
402 propertiesString.append(" AND ");
404 counter = counter + 1;
408 queryObject.appendQueryString(
409 "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString);
411 if (propertiesMap != null)
412 queryObject.appendQueryString(" WITH " + propertiesString);
414 queryObject.appendQueryString(";");
416 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
417 } catch (MusicServiceException ex) {
418 return new JsonResponse(false, ex.getMessage(), "").toMap();
421 return new JsonResponse(result, "", "").toMap();
433 @Path("/{keyspace}/tables/{tablename}/index/{field}")
434 @ApiOperation(value = "Create Index", response = String.class)
435 @Produces(MediaType.APPLICATION_JSON)
436 public Map<String, Object> createIndex(
437 @ApiParam(value = "Major Version",
438 required = true) @PathParam("version") String version,
439 @ApiParam(value = "Minor Version",
440 required = false) @HeaderParam("X-minorVersion") String minorVersion,
441 @ApiParam(value = "Patch Version",
442 required = false) @HeaderParam("X-patchVersion") String patchVersion,
443 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
444 @ApiParam(value = "Application namespace",
445 required = true) @HeaderParam("ns") String ns,
446 @ApiParam(value = "userId",
447 required = true) @HeaderParam("userId") String userId,
448 @ApiParam(value = "Password",
449 required = true) @HeaderParam("password") String password,
450 @ApiParam(value = "Keyspace Name",
451 required = true) @PathParam("keyspace") String keyspace,
452 @ApiParam(value = "Table Name",
453 required = true) @PathParam("tablename") String tablename,
454 @ApiParam(value = "Field Name",
455 required = true) @PathParam("field") String fieldName,
456 @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
457 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
459 response.addHeader(xLatestVersion, MusicUtil.getVersion());
460 if (resultMap.containsKey("aid"))
461 resultMap.remove("aid");
462 if (!resultMap.isEmpty())
464 MultivaluedMap<String, String> rowParams = info.getQueryParameters();
465 String indexName = "";
466 if (rowParams.getFirst("index_name") != null)
467 indexName = rowParams.getFirst("index_name");
468 PreparedQueryObject query = new PreparedQueryObject();
469 query.appendQueryString("Create index " + indexName + " if not exists on " + keyspace + "."
470 + tablename + " (" + fieldName + ");");
471 return new JsonResponse(MusicCore.nonKeyRelatedPut(query, "eventual"), "", "").toMap();
484 @Path("/{keyspace}/tables/{tablename}/rows")
485 @ApiOperation(value = "Insert Into Table", response = String.class)
486 @Consumes(MediaType.APPLICATION_JSON)
487 @Produces(MediaType.APPLICATION_JSON)
488 public Map<String, Object> insertIntoTable(
489 @ApiParam(value = "Major Version",
490 required = true) @PathParam("version") String version,
491 @ApiParam(value = "Minor Version",
492 required = false) @HeaderParam("X-minorVersion") String minorVersion,
493 @ApiParam(value = "Patch Version",
494 required = false) @HeaderParam("X-patchVersion") String patchVersion,
495 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
496 @ApiParam(value = "Application namespace",
497 required = true) @HeaderParam("ns") String ns,
498 @ApiParam(value = "userId",
499 required = true) @HeaderParam("userId") String userId,
500 @ApiParam(value = "Password",
501 required = true) @HeaderParam("password") String password,
503 @ApiParam(value = "Keyspace Name",
504 required = true) @PathParam("keyspace") String keyspace,
505 @ApiParam(value = "Table Name",
506 required = true) @PathParam("tablename") String tablename,
507 @Context HttpServletResponse response) throws Exception {
508 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
509 aid, "insertIntoTable");
510 response.addHeader(xLatestVersion, MusicUtil.getVersion());
511 if (resultMap.containsKey("aid"))
512 resultMap.remove("aid");
513 if (!resultMap.isEmpty()) {
516 ReturnType result = null;
517 Map<String, Object> valuesMap = insObj.getValues();
518 PreparedQueryObject queryObject = new PreparedQueryObject();
519 TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename);
520 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();
521 StringBuilder fieldsString = new StringBuilder("(vector_ts,");
523 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
524 StringBuilder valueString = new StringBuilder("(" + "?" + ",");
525 queryObject.addValue(vectorTs);
527 String primaryKey = "";
529 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
530 fieldsString.append("" + entry.getKey());
531 Object valueObj = entry.getValue();
532 if (primaryKeyName.equals(entry.getKey())) {
533 primaryKey = entry.getValue() + "";
534 primaryKey = primaryKey.replace("'", "''");
537 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
539 Object formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
540 valueString.append("?");
541 queryObject.addValue(formattedValue);
543 if (counter == valuesMap.size() - 1) {
544 fieldsString.append(")");
545 valueString.append(")");
547 fieldsString.append(",");
548 valueString.append(",");
550 counter = counter + 1;
553 queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " "
554 + fieldsString + " VALUES " + valueString);
556 String ttl = insObj.getTtl();
557 String timestamp = insObj.getTimestamp();
559 if ((ttl != null) && (timestamp != null)) {
560 logger.info(EELFLoggerDelegate.applicationLogger, "both there");
561 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
562 queryObject.addValue(Integer.parseInt(ttl));
563 queryObject.addValue(Long.parseLong(timestamp));
566 if ((ttl != null) && (timestamp == null)) {
567 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there");
568 queryObject.appendQueryString(" USING TTL ?");
569 queryObject.addValue(Integer.parseInt(ttl));
572 if ((ttl == null) && (timestamp != null)) {
573 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there");
574 queryObject.appendQueryString(" USING TIMESTAMP ?");
575 queryObject.addValue(Long.parseLong(timestamp));
578 queryObject.appendQueryString(";");
580 String consistency = insObj.getConsistencyInfo().get("type");
582 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
583 result = MusicCore.eventualPut(queryObject);
584 } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
585 String lockId = insObj.getConsistencyInfo().get("lockId");
586 result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,
588 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
589 result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null);
592 return (result != null) ? result.toMap()
593 : new ReturnType(ResultType.FAILURE,
594 "Null result - Please Contact admin").toMap();
595 } catch (Exception ex) {
596 logger.info(EELFLoggerDelegate.applicationLogger, ex.getMessage());
597 return new ReturnType(ResultType.FAILURE, ex.getMessage()).toMap();
611 @Path("/{keyspace}/tables/{tablename}/rows")
612 @ApiOperation(value = "Update Table", response = String.class)
613 @Consumes(MediaType.APPLICATION_JSON)
614 @Produces(MediaType.APPLICATION_JSON)
615 public Map<String, Object> updateTable(
616 @ApiParam(value = "Major Version",
617 required = true) @PathParam("version") String version,
618 @ApiParam(value = "Minor Version",
619 required = false) @HeaderParam("X-minorVersion") String minorVersion,
620 @ApiParam(value = "Patch Version",
621 required = false) @HeaderParam("X-patchVersion") String patchVersion,
622 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
623 @ApiParam(value = "Application namespace",
624 required = true) @HeaderParam("ns") String ns,
625 @ApiParam(value = "userId",
626 required = true) @HeaderParam("userId") String userId,
627 @ApiParam(value = "Password",
628 required = true) @HeaderParam("password") String password,
629 JsonUpdate updateObj,
630 @ApiParam(value = "Keyspace Name",
631 required = true) @PathParam("keyspace") String keyspace,
632 @ApiParam(value = "Table Name",
633 required = true) @PathParam("tablename") String tablename,
634 @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
635 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
637 response.addHeader(xLatestVersion, MusicUtil.getVersion());
638 if (resultMap.containsKey("aid"))
639 resultMap.remove("aid");
640 if (!resultMap.isEmpty()) {
643 long startTime = System.currentTimeMillis();
644 String operationId = UUID.randomUUID().toString();// just for infoging
646 String consistency = updateObj.getConsistencyInfo().get("type");
647 logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency
648 + " update-" + operationId + "-------------------------");
649 // obtain the field value pairs of the update
651 PreparedQueryObject queryObject = new PreparedQueryObject();
652 Map<String, Object> valuesMap = updateObj.getValues();
654 TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename);
655 if (tableInfo == null) {
656 return new ReturnType(ResultType.FAILURE,
657 "Table information not found. Please check input for table name= "
658 + keyspace + "." + tablename).toMap();
661 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
662 StringBuilder fieldValueString = new StringBuilder("vector_ts=?,");
663 queryObject.addValue(vectorTs);
665 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
666 Object valueObj = entry.getValue();
667 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
668 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
669 fieldValueString.append(entry.getKey() + "= ?");
670 queryObject.addValue(valueString);
671 if (counter != valuesMap.size() - 1)
672 fieldValueString.append(",");
673 counter = counter + 1;
675 String ttl = updateObj.getTtl();
676 String timestamp = updateObj.getTimestamp();
678 queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " ");
679 if ((ttl != null) && (timestamp != null)) {
681 logger.info("both there");
682 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
683 queryObject.addValue(Integer.parseInt(ttl));
684 queryObject.addValue(Long.parseLong(timestamp));
687 if ((ttl != null) && (timestamp == null)) {
688 logger.info("ONLY TTL there");
689 queryObject.appendQueryString(" USING TTL ?");
690 queryObject.addValue(Integer.parseInt(ttl));
693 if ((ttl == null) && (timestamp != null)) {
694 logger.info("ONLY timestamp there");
695 queryObject.appendQueryString(" USING TIMESTAMP ?");
696 queryObject.addValue(Long.parseLong(timestamp));
698 // get the row specifier
699 RowIdentifier rowId = null;
701 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
702 } catch (MusicServiceException ex) {
703 return new ReturnType(ResultType.FAILURE, ex.getMessage()).toMap();
706 queryObject.appendQueryString(
707 " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";");
709 // get the conditional, if any
710 Condition conditionInfo;
711 if (updateObj.getConditions() == null)
712 conditionInfo = null;
713 else {// to avoid parsing repeatedly, just send the select query to
715 PreparedQueryObject selectQuery = new PreparedQueryObject();
716 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
717 + rowId.rowIdString + ";");
718 selectQuery.addValue(rowId.primarKeyValue);
719 conditionInfo = new MusicCore.Condition(updateObj.getConditions(), selectQuery);
722 ReturnType operationResult = null;
723 long jsonParseCompletionTime = System.currentTimeMillis();
725 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
726 operationResult = MusicCore.eventualPut(queryObject);
727 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
728 String lockId = updateObj.getConsistencyInfo().get("lockId");
729 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
730 queryObject, lockId, conditionInfo);
731 } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) {
732 // this function is mainly for the benchmarks
733 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename,
734 rowId.primarKeyValue, queryObject, conditionInfo);
735 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
736 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
737 queryObject, conditionInfo);
739 long actualUpdateCompletionTime = System.currentTimeMillis();
741 long endTime = System.currentTimeMillis();
742 String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId
743 + ":" + "|total operation time:" + (endTime - startTime)
744 + "|json parsing time:" + (jsonParseCompletionTime - startTime)
745 + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime)
748 if (operationResult != null && operationResult.getTimingInfo() != null) {
749 String lockManagementTime = operationResult.getTimingInfo();
750 timingString = timingString + lockManagementTime;
752 logger.info(EELFLoggerDelegate.applicationLogger, timingString);
753 return (operationResult != null) ? operationResult.toMap()
754 : new ReturnType(ResultType.FAILURE, "Null result - Please Contact admin")
768 @Path("/{keyspace}/tables/{tablename}/rows")
769 @ApiOperation(value = "Delete From table", response = String.class)
770 @Consumes(MediaType.APPLICATION_JSON)
771 @Produces(MediaType.APPLICATION_JSON)
772 public Map<String, Object> deleteFromTable(
773 @ApiParam(value = "Major Version",
774 required = true) @PathParam("version") String version,
775 @ApiParam(value = "Minor Version",
776 required = false) @HeaderParam("X-minorVersion") String minorVersion,
777 @ApiParam(value = "Patch Version",
778 required = false) @HeaderParam("X-patchVersion") String patchVersion,
779 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
780 @ApiParam(value = "Application namespace",
781 required = true) @HeaderParam("ns") String ns,
782 @ApiParam(value = "userId",
783 required = true) @HeaderParam("userId") String userId,
784 @ApiParam(value = "Password",
785 required = true) @HeaderParam("password") String password,
787 @ApiParam(value = "Keyspace Name",
788 required = true) @PathParam("keyspace") String keyspace,
789 @ApiParam(value = "Table Name",
790 required = true) @PathParam("tablename") String tablename,
791 @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
792 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
793 aid, "deleteFromTable");
794 response.addHeader(xLatestVersion, MusicUtil.getVersion());
795 if (resultMap.containsKey("aid"))
796 resultMap.remove("aid");
797 if (!resultMap.isEmpty()) {
800 PreparedQueryObject queryObject = new PreparedQueryObject();
801 StringBuilder columnString = new StringBuilder();
804 ArrayList<String> columnList = delObj.getColumns();
805 if (columnList != null) {
806 for (String column : columnList) {
807 columnString.append(column);
808 if (counter != columnList.size() - 1)
809 columnString.append(",");
810 counter = counter + 1;
814 // get the row specifier
815 RowIdentifier rowId = null;
817 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
818 } catch (MusicServiceException ex) {
819 return new ReturnType(ResultType.FAILURE, ex.getMessage()).toMap();
821 String rowSpec = rowId.rowIdString.toString();
823 if ((columnList != null) && (!rowSpec.isEmpty())) {
824 queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "."
825 + tablename + " WHERE " + rowSpec + ";");
828 if ((columnList == null) && (!rowSpec.isEmpty())) {
829 queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE "
833 if ((columnList != null) && (rowSpec.isEmpty())) {
834 queryObject.appendQueryString(
835 "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";");
838 // get the conditional, if any
839 Condition conditionInfo;
840 if (delObj.getConditions() == null)
841 conditionInfo = null;
842 else {// to avoid parsing repeatedly, just send the select query to
844 PreparedQueryObject selectQuery = new PreparedQueryObject();
845 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
846 + rowId.rowIdString + ";");
847 selectQuery.addValue(rowId.primarKeyValue);
848 conditionInfo = new MusicCore.Condition(delObj.getConditions(), selectQuery);
851 String consistency = delObj.getConsistencyInfo().get("type");
853 ReturnType operationResult = null;
855 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
856 operationResult = MusicCore.eventualPut(queryObject);
857 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
858 String lockId = delObj.getConsistencyInfo().get("lockId");
859 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
860 queryObject, lockId, conditionInfo);
861 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
862 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
863 queryObject, conditionInfo);
866 return operationResult.toMap();
867 } catch (NullPointerException e) {
868 return new ReturnType(ResultType.FAILURE, e.getMessage()).toMap();
880 @Path("/{keyspace}/tables/{tablename}")
881 @ApiOperation(value = "Drop Table", response = String.class)
882 @Consumes(MediaType.APPLICATION_JSON)
883 @Produces(MediaType.APPLICATION_JSON)
884 public Map<String, Object> dropTable(
885 @ApiParam(value = "Major Version",
886 required = true) @PathParam("version") String version,
887 @ApiParam(value = "Minor Version",
888 required = false) @HeaderParam("X-minorVersion") String minorVersion,
889 @ApiParam(value = "Patch Version",
890 required = false) @HeaderParam("X-patchVersion") String patchVersion,
891 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
892 @ApiParam(value = "Application namespace",
893 required = true) @HeaderParam("ns") String ns,
894 @ApiParam(value = "userId",
895 required = true) @HeaderParam("userId") String userId,
896 @ApiParam(value = "Password",
897 required = true) @HeaderParam("password") String password,
899 @ApiParam(value = "Keyspace Name",
900 required = true) @PathParam("keyspace") String keyspace,
901 @ApiParam(value = "Table Name",
902 required = true) @PathParam("tablename") String tablename,
903 @Context HttpServletResponse response) throws Exception {
904 Map<String, Object> resultMap =
905 MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "dropTable");
906 response.addHeader(xLatestVersion, MusicUtil.getVersion());
907 if (resultMap.containsKey("aid"))
908 resultMap.remove("aid");
909 if (!resultMap.isEmpty()) {
912 String consistency = "eventual";// for now this needs only eventual
914 PreparedQueryObject query = new PreparedQueryObject();
915 query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";");
917 return new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency), "", "").toMap();
918 } catch (MusicServiceException ex) {
919 return new JsonResponse(false, ex.getMessage(), "").toMap();
933 @Path("/{keyspace}/tables/{tablename}/rows/criticalget")
934 @ApiOperation(value = "Select Critical", response = Map.class)
935 @Consumes(MediaType.APPLICATION_JSON)
936 @Produces(MediaType.APPLICATION_JSON)
937 public Map<String, HashMap<String, Object>> selectCritical(
938 @ApiParam(value = "Major Version",
939 required = true) @PathParam("version") String version,
940 @ApiParam(value = "Minor Version",
941 required = false) @HeaderParam("X-minorVersion") String minorVersion,
942 @ApiParam(value = "Patch Version",
943 required = false) @HeaderParam("X-patchVersion") String patchVersion,
944 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
945 @ApiParam(value = "Application namespace",
946 required = true) @HeaderParam("ns") String ns,
947 @ApiParam(value = "userId",
948 required = true) @HeaderParam("userId") String userId,
949 @ApiParam(value = "Password",
950 required = true) @HeaderParam("password") String password,
952 @ApiParam(value = "Keyspace Name",
953 required = true) @PathParam("keyspace") String keyspace,
954 @ApiParam(value = "Table Name",
955 required = true) @PathParam("tablename") String tablename,
956 @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
957 Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
958 aid, "selectCritical");
959 response.addHeader(xLatestVersion, MusicUtil.getVersion());
960 if (resultMap.containsKey("aid"))
961 resultMap.remove("aid");
962 if (!resultMap.isEmpty()) {
963 logger.error("Error while authentication... ");
964 HashMap<String, Object> tempMap = new HashMap<>();
965 tempMap.putAll(resultMap);
966 Map<String, HashMap<String, Object>> results = new HashMap<>();
967 results.put("Result", tempMap);
970 String lockId = selObj.getConsistencyInfo().get("lockId");
972 PreparedQueryObject queryObject = new PreparedQueryObject();
973 StringBuilder rowSpec = new StringBuilder();
975 RowIdentifier rowId = null;
977 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
978 } catch (MusicServiceException ex) {
979 return MusicUtil.setErrorResponse(ex);
981 queryObject.appendQueryString(
982 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowSpec + ";");
984 ResultSet results = null;
986 String consistency = selObj.getConsistencyInfo().get("type");
988 if (consistency.equalsIgnoreCase("critical")) {
989 results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,
991 } else if (consistency.equalsIgnoreCase("atomic")) {
992 results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject);
995 return MusicCore.marshallResults(results);
1007 @Path("/{keyspace}/tables/{tablename}/rows")
1008 @ApiOperation(value = "Select All or Select Specivic", response = Map.class)
1009 @Produces(MediaType.APPLICATION_JSON)
1010 public Map<String, HashMap<String, Object>> select(
1011 @ApiParam(value = "Major Version",
1012 required = true) @PathParam("version") String version,
1013 @ApiParam(value = "Minor Version",
1014 required = false) @HeaderParam("X-minorVersion") String minorVersion,
1015 @ApiParam(value = "Patch Version",
1016 required = false) @HeaderParam("X-patchVersion") String patchVersion,
1017 @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
1018 @ApiParam(value = "Application namespace",
1019 required = true) @HeaderParam("ns") String ns,
1020 @ApiParam(value = "userId",
1021 required = true) @HeaderParam("userId") String userId,
1022 @ApiParam(value = "Password",
1023 required = true) @HeaderParam("password") String password,
1024 @ApiParam(value = "Keyspace Name",
1025 required = true) @PathParam("keyspace") String keyspace,
1026 @ApiParam(value = "Table Name",
1027 required = true) @PathParam("tablename") String tablename,
1028 @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
1029 Map<String, Object> resultMap =
1030 MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "select");
1031 response.addHeader(xLatestVersion, MusicUtil.getVersion());
1032 if (resultMap.containsKey("aid"))
1033 resultMap.remove("aid");
1034 if (!resultMap.isEmpty()) {
1035 logger.error("Error while authentication... ");
1036 HashMap<String, Object> tempMap = new HashMap<>();
1037 tempMap.putAll(resultMap);
1038 Map<String, HashMap<String, Object>> results = new HashMap<>();
1039 results.put("Result", tempMap);
1042 PreparedQueryObject queryObject = new PreparedQueryObject();
1044 if (info.getQueryParameters().isEmpty())// select all
1045 queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";");
1047 int limit = -1; // do not limit the number of results
1049 queryObject = selectSpecificQuery(version, minorVersion, patchVersion, aid, ns,
1050 userId, password, keyspace, tablename, info, limit);
1051 } catch (MusicServiceException ex) {
1052 return MusicUtil.setErrorResponse(ex);
1057 ResultSet results = MusicCore.get(queryObject);
1058 return MusicCore.marshallResults(results);
1059 } catch (MusicServiceException ex) {
1060 return MusicUtil.setErrorResponse(ex);
1072 * @throws MusicServiceException
1075 public PreparedQueryObject selectSpecificQuery(String version, String minorVersion,
1076 String patchVersion, String aid, String ns, String userId, String password,
1077 String keyspace, String tablename, UriInfo info, int limit)
1078 throws MusicServiceException {
1080 PreparedQueryObject queryObject = new PreparedQueryObject();
1081 StringBuilder rowIdString = getRowIdentifier(keyspace, tablename, info.getQueryParameters(),
1082 queryObject).rowIdString;
1084 queryObject.appendQueryString(
1085 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
1088 queryObject.appendQueryString(" LIMIT " + limit);
1091 queryObject.appendQueryString(";");
1101 * @param queryObject
1103 * @throws MusicServiceException
1106 private RowIdentifier getRowIdentifier(String keyspace, String tablename,
1107 MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
1108 throws MusicServiceException {
1109 StringBuilder rowSpec = new StringBuilder();
1111 TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename);
1112 if (tableInfo == null) {
1113 logger.error(EELFLoggerDelegate.errorLogger,
1114 "Table information not found. Please check input for table name= "
1115 + keyspace + "." + tablename);
1116 throw new MusicServiceException(
1117 "Table information not found. Please check input for table name= "
1118 + keyspace + "." + tablename);
1120 StringBuilder primaryKey = new StringBuilder();
1121 for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
1122 String keyName = entry.getKey();
1123 List<String> valueList = entry.getValue();
1124 String indValue = valueList.get(0);
1125 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
1126 Object formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
1127 primaryKey.append(indValue);
1128 rowSpec.append(keyName + "= ?");
1129 queryObject.addValue(formattedValue);
1130 if (counter != rowParams.size() - 1)
1131 rowSpec.append(" AND ");
1132 counter = counter + 1;
1134 return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);