2 * ============LICENSE_START==========================================
4 * ===================================================================
5 * Copyright (c) 2017 AT&T Intellectual Property
6 * ===================================================================
7 * Modifications Copyright (c) 2019 Samsung
8 * ===================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ============LICENSE_END=============================================
22 * ====================================================================
25 package org.onap.music.rest;
27 import java.nio.ByteBuffer;
28 import java.util.List;
30 import java.util.UUID;
32 import javax.ws.rs.Consumes;
33 import javax.ws.rs.DELETE;
34 import javax.ws.rs.GET;
35 import javax.ws.rs.HeaderParam;
36 import javax.ws.rs.POST;
37 import javax.ws.rs.PUT;
38 import javax.ws.rs.Path;
39 import javax.ws.rs.PathParam;
40 import javax.ws.rs.Produces;
41 import javax.ws.rs.core.Context;
42 import javax.ws.rs.core.MediaType;
43 import javax.ws.rs.core.MultivaluedMap;
44 import javax.ws.rs.core.Response;
45 import javax.ws.rs.core.Response.ResponseBuilder;
46 import javax.ws.rs.core.Response.Status;
47 import javax.ws.rs.core.UriInfo;
49 import org.apache.commons.lang3.StringUtils;
50 import org.mindrot.jbcrypt.BCrypt;
51 import org.onap.music.authentication.CachingUtil;
52 import org.onap.music.authentication.MusicAuthentication;
53 import org.onap.music.authentication.MusicAuthenticator;
54 import org.onap.music.authentication.MusicAuthenticator.Operation;
55 import org.onap.music.datastore.PreparedQueryObject;
56 import org.onap.music.datastore.jsonobjects.JsonDelete;
57 import org.onap.music.datastore.jsonobjects.JsonInsert;
58 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
59 import org.onap.music.datastore.jsonobjects.JsonTable;
60 import org.onap.music.datastore.jsonobjects.JsonUpdate;
61 import org.onap.music.eelf.logging.EELFLoggerDelegate;
62 import org.onap.music.exceptions.MusicLockingException;
63 import org.onap.music.exceptions.MusicQueryException;
64 import org.onap.music.eelf.logging.format.AppMessages;
65 import org.onap.music.eelf.logging.format.ErrorSeverity;
66 import org.onap.music.eelf.logging.format.ErrorTypes;
67 import org.onap.music.exceptions.MusicServiceException;
68 import org.onap.music.main.MusicCore;
69 import org.onap.music.datastore.Condition;
70 import org.onap.music.datastore.MusicDataStoreHandle;
71 import org.onap.music.main.MusicUtil;
72 import org.onap.music.main.ResultType;
73 import org.onap.music.main.ReturnType;
74 import org.onap.music.response.jsonobjects.JsonResponse;
76 import com.datastax.driver.core.DataType;
77 import com.datastax.driver.core.ResultSet;
78 import com.datastax.driver.core.Row;
79 import com.datastax.driver.core.TableMetadata;
81 import io.swagger.annotations.Api;
82 import io.swagger.annotations.ApiOperation;
83 import io.swagger.annotations.ApiParam;
84 import io.swagger.annotations.ApiResponses;
85 import io.swagger.annotations.ApiResponse;
88 //@Path("/v{version: [0-9]+}/keyspaces")
89 @Path("/v2/keyspaces")
90 @Api(value = "Data Api")
91 public class RestMusicDataAPI {
93 * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR
94 * version back from the client to the server, and from the server back to the client - This
95 * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR
96 * version (if not specified by the client on the request) - Contains a single position value
97 * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on
98 * request; however, this header should be provided if the client needs to take advantage of
99 * MINOR incremented version functionality - Is mandatory for the server on response
101 *** X-patchVersion *** - Used only to communicate a PATCH version in a response for
102 * troubleshooting purposes only, and will not be provided by the client on request - This will
103 * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version
104 * of the MAJOR (if not specified by the client on the request) - Contains a single position
105 * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the
106 * server on response (CURRENTLY NOT USED)
108 *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the
109 * server on response, and shall include the entire version of the API (e.g. if the full version
110 * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are
111 * not using the latest version of the API (CURRENTLY NOT USED)
115 private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class);
116 private static final String XMINORVERSION = "X-minorVersion";
117 private static final String XPATCHVERSION = "X-patchVersion";
118 private static final String NS = "ns";
119 private static final String VERSION = "v2";
120 private MusicAuthenticator authenticator = new MusicAuthentication();
121 // Set to true in env like ONAP. Where access to creating and dropping keyspaces exist.
122 private static final boolean KEYSPACE_ACTIVE = false;
124 private class RowIdentifier {
125 public String primarKeyValue;
126 public StringBuilder rowIdString;
127 @SuppressWarnings("unused")
128 public PreparedQueryObject queryObject;// the string with all the row
129 // identifiers separated by AND
131 public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
132 PreparedQueryObject queryObject) {
133 this.primarKeyValue = primaryKeyValue;
134 this.rowIdString = rowIdString;
135 this.queryObject = queryObject;
141 * Create Keyspace REST
144 * @param keyspaceName
150 @ApiOperation(value = "Create Keyspace", response = String.class,hidden = true)
151 @Consumes(MediaType.APPLICATION_JSON)
152 @Produces(MediaType.APPLICATION_JSON)
153 public Response createKeySpace(
154 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
155 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
156 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
157 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
158 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
159 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
160 JsonKeySpace kspObject,
161 @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) {
163 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
164 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
165 logger.info(EELFLoggerDelegate.applicationLogger,"In Create Keyspace " + keyspaceName);
166 if ( KEYSPACE_ACTIVE ) {
167 logger.info(EELFLoggerDelegate.applicationLogger,"Creating Keyspace " + keyspaceName);
168 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
169 String userId = userCredentials.get(MusicUtil.USERID);
170 String password = userCredentials.get(MusicUtil.PASSWORD);
171 Map<String, Object> authMap = CachingUtil.verifyOnboarding(ns, userId, password);
172 if (!authMap.isEmpty()) {
173 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
174 response.status(Status.UNAUTHORIZED);
175 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
177 if(kspObject == null || kspObject.getReplicationInfo() == null) {
178 response.status(Status.BAD_REQUEST);
179 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
184 authMap = MusicAuthentication.autheticateUser(ns, userId, password, keyspaceName, aid,
186 } catch (Exception e) {
187 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
188 response.status(Status.BAD_REQUEST);
189 return response.entity(new JsonResponse(ResultType.FAILURE).setError("Unable to authenticate.").toMap()).build();
191 String newAid = null;
192 if (!authMap.isEmpty()) {
193 if (authMap.containsKey("aid")) {
194 newAid = (String) authMap.get("aid");
196 logger.error(EELFLoggerDelegate.errorLogger,String.valueOf(authMap.get("Exception")), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
197 response.status(Status.UNAUTHORIZED);
198 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
202 String consistency = MusicUtil.EVENTUAL;// for now this needs only
203 // eventual consistency
205 PreparedQueryObject queryObject = new PreparedQueryObject();
206 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && kspObject.getConsistencyInfo().get("consistency") != null) {
207 if(MusicUtil.isValidConsistency(kspObject.getConsistencyInfo().get("consistency")))
208 queryObject.setConsistency(kspObject.getConsistencyInfo().get("consistency"));
210 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
212 long start = System.currentTimeMillis();
213 Map<String, Object> replicationInfo = kspObject.getReplicationInfo();
214 String repString = null;
216 repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}";
217 } catch (Exception e) {
218 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
221 queryObject.appendQueryString(
222 "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString);
223 if (kspObject.getDurabilityOfWrites() != null) {
224 queryObject.appendQueryString(
225 " AND durable_writes = " + kspObject.getDurabilityOfWrites());
228 queryObject.appendQueryString(";");
229 long end = System.currentTimeMillis();
230 logger.info(EELFLoggerDelegate.applicationLogger,
231 "Time taken for setting up query in create keyspace:" + (end - start));
233 ResultType result = ResultType.FAILURE;
235 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
236 logger.info(EELFLoggerDelegate.applicationLogger, "result = " + result);
237 } catch ( MusicServiceException ex) {
238 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
239 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("err:" + ex.getMessage()).toMap()).build();
243 queryObject = new PreparedQueryObject();
244 queryObject.appendQueryString("CREATE ROLE IF NOT EXISTS '" + userId
245 + "' WITH PASSWORD = '" + password + "' AND LOGIN = true;");
246 MusicCore.nonKeyRelatedPut(queryObject, consistency);
247 queryObject = new PreparedQueryObject();
248 queryObject.appendQueryString("GRANT ALL PERMISSIONS on KEYSPACE " + keyspaceName
249 + " to '" + userId + "'");
250 queryObject.appendQueryString(";");
251 MusicCore.nonKeyRelatedPut(queryObject, consistency);
252 } catch (Exception e) {
253 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
257 boolean isAAF = Boolean.valueOf(CachingUtil.isAAFApplication(ns));
258 String hashedpwd = BCrypt.hashpw(password, BCrypt.gensalt());
259 queryObject = new PreparedQueryObject();
260 queryObject.appendQueryString(
261 "INSERT into admin.keyspace_master (uuid, keyspace_name, application_name, is_api, "
262 + "password, username, is_aaf) values (?,?,?,?,?,?,?)");
263 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid));
264 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspaceName));
265 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns));
266 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), "True"));
267 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), hashedpwd));
268 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId));
269 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), isAAF));
270 CachingUtil.updateMusicCache(keyspaceName, ns);
271 CachingUtil.updateMusicValidateCache(ns, userId, hashedpwd);
272 MusicCore.eventualPut(queryObject);
273 } catch (Exception e) {
274 logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
275 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
278 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build();
280 String vError = "Keyspace Creation no longer supported after versions 3.2.x. Contact DBA to create the keyspace.";
281 logger.info(EELFLoggerDelegate.applicationLogger,vError);
282 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
283 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
286 EELFLoggerDelegate.mdcRemove("keyspace");
294 * @param keyspaceName
300 @ApiOperation(value = "Delete Keyspace", response = String.class,hidden=true)
301 @Produces(MediaType.APPLICATION_JSON)
302 public Response dropKeySpace(
303 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
304 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
305 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
306 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
307 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
308 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
309 @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) throws Exception {
311 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
312 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
313 logger.info(EELFLoggerDelegate.applicationLogger,"In Drop Keyspace " + keyspaceName);
314 if ( KEYSPACE_ACTIVE ) {
315 Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization);
316 String userId = userCredentials.get(MusicUtil.USERID);
317 String password = userCredentials.get(MusicUtil.PASSWORD);
318 Map<String, Object> authMap = MusicAuthentication.autheticateUser(ns, userId, password,keyspaceName, aid, "dropKeySpace");
319 if (authMap.containsKey("aid"))
320 authMap.remove("aid");
321 if (!authMap.isEmpty()) {
322 logger.error(EELFLoggerDelegate.errorLogger,authMap.get("Exception").toString(), AppMessages.MISSINGDATA ,ErrorSeverity.CRITICAL, ErrorTypes.AUTHENTICATIONERROR);
323 response.status(Status.UNAUTHORIZED);
324 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(authMap.get("Exception"))).toMap()).build();
327 String consistency = MusicUtil.EVENTUAL;// for now this needs only
330 String appName = CachingUtil.getAppName(keyspaceName);
331 String uuid = CachingUtil.getUuidFromMusicCache(keyspaceName);
332 PreparedQueryObject pQuery = new PreparedQueryObject();
333 pQuery.appendQueryString(
334 "select count(*) as count from admin.keyspace_master where application_name=? allow filtering;");
335 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
336 Row row = MusicCore.get(pQuery).one();
337 long count = row.getLong(0);
340 logger.error(EELFLoggerDelegate.errorLogger,"Keyspace not found. Please make sure keyspace exists.", AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
341 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Keyspace not found. Please make sure keyspace exists.").toMap()).build();
343 } else if (count == 1) {
344 pQuery = new PreparedQueryObject();
345 pQuery.appendQueryString(
346 "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;");
347 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
348 MusicUtil.DEFAULTKEYSPACENAME));
349 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
350 MusicCore.nonKeyRelatedPut(pQuery, consistency);
352 pQuery = new PreparedQueryObject();
353 pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?");
354 pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
355 MusicCore.nonKeyRelatedPut(pQuery, consistency);
358 PreparedQueryObject queryObject = new PreparedQueryObject();
359 queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";");
360 ResultType result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
361 if ( result.equals(ResultType.FAILURE) ) {
362 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Deleteing Keyspace " + keyspaceName).toMap()).build();
364 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build();
366 String vError = "Keyspace Droping no longer supported after versions 3.2.x. Contact DBA to drop the keyspace.";
367 logger.info(EELFLoggerDelegate.applicationLogger,vError);
368 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
369 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
372 EELFLoggerDelegate.mdcRemove("keyspace");
387 @Path("/{keyspace: .*}/tables/{tablename: .*}")
388 @ApiOperation(value = "Create Table", response = String.class)
389 @Consumes(MediaType.APPLICATION_JSON)
390 @Produces(MediaType.APPLICATION_JSON)
391 @ApiResponses(value={
392 @ApiResponse(code= 400, message = "Will return JSON response with message"),
393 @ApiResponse(code= 401, message = "Unautorized User")
395 public Response createTable(
396 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
397 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
398 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
399 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
400 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
401 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
403 @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
404 @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename) throws Exception {
406 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
407 if(keyspace == null || keyspace.isEmpty() || tablename == null || tablename.isEmpty()){
408 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
409 .setError("One or more path parameters are not set, please check and try again."
410 + "Parameter values: keyspace='" + keyspace + "' tablename='" + tablename + "'")
413 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
414 if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.CREATE_TABLE)) {
415 return response.status(Status.UNAUTHORIZED)
416 .entity(new JsonResponse(ResultType.FAILURE)
417 .setError("Unauthorized: Please check username, password and make sure your app is onboarded")
421 String consistency = MusicUtil.EVENTUAL;
422 // for now this needs only eventual consistency
424 String primaryKey = null;
425 String partitionKey = tableObj.getPartitionKey();
426 String clusterKey = tableObj.getClusteringKey();
427 String filteringKey = tableObj.getFilteringKey();
428 if(filteringKey != null) {
429 clusterKey = clusterKey + "," + filteringKey;
431 primaryKey = tableObj.getPrimaryKey(); // get primaryKey if available
433 PreparedQueryObject queryObject = new PreparedQueryObject();
434 // first read the information about the table fields
435 Map<String, String> fields = tableObj.getFields();
436 StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
438 for (Map.Entry<String, String> entry : fields.entrySet()) {
439 if (entry.getKey().equals("PRIMARY KEY")) {
440 primaryKey = entry.getValue(); // replaces primaryKey
441 primaryKey = primaryKey.trim();
443 if (counter == 0 ) fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
444 else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
447 if (counter != (fields.size() - 1) ) {
449 counter = counter + 1;
452 if((primaryKey != null) && (partitionKey == null)) {
453 primaryKey = primaryKey.trim();
454 int count1 = StringUtils.countMatches(primaryKey, ')');
455 int count2 = StringUtils.countMatches(primaryKey, '(');
456 if (count1 != count2) {
457 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
458 .setError("Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey)
462 if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) )
464 if (primaryKey.contains(",") ) {
465 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
466 partitionKey=partitionKey.replaceAll("[\\(]+","");
467 clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index
468 clusterKey=clusterKey.replaceAll("[)]+", "");
470 partitionKey=primaryKey;
471 partitionKey=partitionKey.replaceAll("[\\)]+","");
472 partitionKey=partitionKey.replaceAll("[\\(]+","");
475 } else { // not null and has ) before the last char
476 partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
477 partitionKey=partitionKey.replaceAll("[\\(]+","");
478 partitionKey = partitionKey.trim();
479 clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
480 clusterKey=clusterKey.replaceAll("[\\(]+","");
481 clusterKey=clusterKey.replaceAll("[\\)]+","");
482 clusterKey = clusterKey.trim();
483 if (clusterKey.indexOf(',') == 0) clusterKey=clusterKey.substring(1);
484 clusterKey = clusterKey.trim();
485 if (clusterKey.equals(",") ) clusterKey=""; // print error if needed ( ... ),)
488 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
489 && (partitionKey.equalsIgnoreCase(clusterKey) ||
490 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) )
492 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
493 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
494 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of"
495 + " primary key=" + primaryKey)
500 if (partitionKey.isEmpty() ) primaryKey="";
501 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
502 else primaryKey=" (" + partitionKey + ")," + clusterKey;
505 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
507 } // end of length > 0
509 if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
510 && (partitionKey.equalsIgnoreCase(clusterKey) ||
511 clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) )
513 logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
514 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
515 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
519 if (partitionKey.isEmpty() ) primaryKey="";
520 else if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey + ")";
521 else primaryKey=" (" + partitionKey + ")," + clusterKey;
524 if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
526 fieldsString.append(")");
528 } // end of last field check
531 // information about the name-value style properties
532 Map<String, Object> propertiesMap = tableObj.getProperties();
533 StringBuilder propertiesString = new StringBuilder();
534 if (propertiesMap != null) {
536 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
537 Object ot = entry.getValue();
538 String value = ot + "";
539 if (ot instanceof String) {
540 value = "'" + value + "'";
541 } else if (ot instanceof Map) {
542 @SuppressWarnings("unchecked")
543 Map<String, Object> otMap = (Map<String, Object>) ot;
544 value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
547 propertiesString.append(entry.getKey() + "=" + value + "");
548 if (counter != propertiesMap.size() - 1)
549 propertiesString.append(" AND ");
551 counter = counter + 1;
555 String clusteringOrder = tableObj.getClusteringOrder();
557 if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
558 String[] arrayClusterOrder = clusteringOrder.split("[,]+");
560 for (int i = 0; i < arrayClusterOrder.length; i++) {
561 String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
562 if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
565 return response.status(Status.BAD_REQUEST)
566 .entity(new JsonResponse(ResultType.FAILURE)
567 .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".")
570 // add validation for column names in cluster key
573 if (!(clusterKey.isEmpty())) {
574 clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
575 //cjc check if propertiesString.length() >0 instead propertiesMap
576 if (propertiesMap != null) {
577 propertiesString.append(" AND "+ clusteringOrder);
579 propertiesString.append(clusteringOrder);
582 logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
586 queryObject.appendQueryString(
587 "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString);
590 if (propertiesString != null && propertiesString.length()>0 )
591 queryObject.appendQueryString(" WITH " + propertiesString);
592 queryObject.appendQueryString(";");
593 ResultType result = ResultType.FAILURE;
595 result = MusicCore.createTable(keyspace, tablename, queryObject, consistency);
596 } catch (MusicServiceException ex) {
597 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.MUSICSERVICEERROR);
598 response.status(Status.BAD_REQUEST);
599 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
601 if ( result.equals(ResultType.FAILURE) ) {
602 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Creating Table " + tablename).toMap()).build();
604 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("TableName " + tablename.trim() + " Created under keyspace " + keyspace.trim()).toMap()).build();
606 EELFLoggerDelegate.mdcRemove("keyspace");
619 @Path("/{keyspace: .*}/tables/{tablename: .*}/index/{field: .*}")
620 @ApiOperation(value = "Create Index", response = String.class)
621 @Produces(MediaType.APPLICATION_JSON)
622 public Response createIndex(
623 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
624 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
625 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
626 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
627 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
628 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
629 @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
630 @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename,
631 @ApiParam(value = "Field Name",required = true) @PathParam("field") String fieldName,
632 @Context UriInfo info) throws Exception {
634 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
635 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty()) || (fieldName == null || fieldName.isEmpty())){
636 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
637 .setError("one or more path parameters are not set, please check and try again")
640 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
641 if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.CREATE_INDEX)) {
642 return response.status(Status.UNAUTHORIZED)
643 .entity(new JsonResponse(ResultType.FAILURE)
644 .setError("Unauthorized: Please check username, password and make sure your app is onboarded")
648 MultivaluedMap<String, String> rowParams = info.getQueryParameters();
649 String indexName = "";
650 if (rowParams.getFirst("index_name") != null)
651 indexName = rowParams.getFirst("index_name");
652 PreparedQueryObject query = new PreparedQueryObject();
653 query.appendQueryString("Create index if not exists " + indexName + " on " + keyspace + "."
654 + tablename + " (" + fieldName + ");");
656 ResultType result = ResultType.FAILURE;
658 result = MusicCore.nonKeyRelatedPut(query, "eventual");
659 } catch (MusicServiceException ex) {
660 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
661 response.status(Status.BAD_REQUEST);
662 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
664 if ( result.equals(ResultType.SUCCESS) ) {
665 return response.status(Status.OK).entity(new JsonResponse(result).setMessage("Index Created on " + keyspace+"."+tablename+"."+fieldName).toMap()).build();
667 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Unknown Error in create index.").toMap()).build();
670 EELFLoggerDelegate.mdcRemove("keyspace");
683 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
684 @ApiOperation(value = "Insert Into Table", response = String.class)
685 @Consumes(MediaType.APPLICATION_JSON)
686 @Produces(MediaType.APPLICATION_JSON)
687 public Response insertIntoTable(
688 @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
689 @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
690 @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
691 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
692 @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
693 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
695 @ApiParam(value = "Keyspace Name",
696 required = true) @PathParam("keyspace") String keyspace,
697 @ApiParam(value = "Table Name",
698 required = true) @PathParam("tablename") String tablename) {
700 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
701 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
702 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
703 .setError("one or more path parameters are not set, please check and try again")
706 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
707 if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.INSERT_INTO_TABLE)) {
708 return response.status(Status.UNAUTHORIZED)
709 .entity(new JsonResponse(ResultType.FAILURE)
710 .setError("Unauthorized: Please check username, password and make sure your app is onboarded")
714 Map<String, Object> valuesMap = insObj.getValues();
715 PreparedQueryObject queryObject = new PreparedQueryObject();
716 TableMetadata tableInfo = null;
718 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
719 if(tableInfo == null) {
720 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Table name doesn't exists. Please check the table name.").toMap()).build();
722 } catch (MusicServiceException e) {
723 logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
724 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
726 String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();
727 StringBuilder fieldsString = new StringBuilder("(vector_ts,");
729 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
730 StringBuilder valueString = new StringBuilder("(" + "?" + ",");
731 queryObject.addValue(vectorTs);
733 String primaryKey = "";
734 Map<String, byte[]> objectMap = insObj.getObjectMap();
735 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
736 fieldsString.append("" + entry.getKey());
737 Object valueObj = entry.getValue();
738 if (primaryKeyName.equals(entry.getKey())) {
739 primaryKey = entry.getValue() + "";
740 primaryKey = primaryKey.replace("'", "''");
742 DataType colType = null;
744 colType = tableInfo.getColumn(entry.getKey()).getType();
745 } catch(NullPointerException ex) {
746 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey(), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
747 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
750 Object formattedValue = null;
752 formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
753 } catch (Exception e) {
754 logger.error(EELFLoggerDelegate.errorLogger,e);
756 valueString.append("?");
758 queryObject.addValue(formattedValue);
760 if (counter == valuesMap.size() - 1) {
761 fieldsString.append(")");
762 valueString.append(")");
764 fieldsString.append(",");
765 valueString.append(",");
767 counter = counter + 1;
771 if(objectMap != null) {
772 for (Map.Entry<String, byte[]> entry : objectMap.entrySet()) {
774 fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ",");
775 valueString.replace(valueString.length()-1, valueString.length(), ",");
777 fieldsString.append("" + entry.getKey());
778 byte[] valueObj = entry.getValue();
779 if (primaryKeyName.equals(entry.getKey())) {
780 primaryKey = entry.getValue() + "";
781 primaryKey = primaryKey.replace("'", "''");
784 DataType colType = tableInfo.getColumn(entry.getKey()).getType();
786 ByteBuffer formattedValue = null;
788 if(colType.toString().toLowerCase().contains("blob"))
789 formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
791 valueString.append("?");
793 queryObject.addValue(formattedValue);
794 counter = counter + 1;
795 /*if (counter == valuesMap.size() - 1) {
796 fieldsString.append(")");
797 valueString.append(")");
799 fieldsString.append(",");
800 valueString.append(",");
804 if(primaryKey == null || primaryKey.length() <= 0) {
805 logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName );
806 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build();
809 fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")");
810 valueString.replace(valueString.length()-1, valueString.length(), ")");
812 queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " "
813 + fieldsString + " VALUES " + valueString);
815 String ttl = insObj.getTtl();
816 String timestamp = insObj.getTimestamp();
818 if ((ttl != null) && (timestamp != null)) {
819 logger.info(EELFLoggerDelegate.applicationLogger, "both there");
820 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
821 queryObject.addValue(Integer.parseInt(ttl));
822 queryObject.addValue(Long.parseLong(timestamp));
825 if ((ttl != null) && (timestamp == null)) {
826 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there");
827 queryObject.appendQueryString(" USING TTL ?");
828 queryObject.addValue(Integer.parseInt(ttl));
831 if ((ttl == null) && (timestamp != null)) {
832 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there");
833 queryObject.appendQueryString(" USING TIMESTAMP ?");
834 queryObject.addValue(Long.parseLong(timestamp));
837 queryObject.appendQueryString(";");
839 ReturnType result = null;
840 String consistency = insObj.getConsistencyInfo().get("type");
841 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && insObj.getConsistencyInfo().get("consistency") != null) {
842 if(MusicUtil.isValidConsistency(insObj.getConsistencyInfo().get("consistency")))
843 queryObject.setConsistency(insObj.getConsistencyInfo().get("consistency"));
845 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
847 queryObject.setOperation("insert");
849 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
850 result = MusicCore.eventualPut(queryObject);
851 } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
852 String lockId = insObj.getConsistencyInfo().get("lockId");
854 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
855 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
856 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
857 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
859 result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null);
860 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
862 result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null);
865 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
866 result = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, primaryKey, queryObject, null);
869 } catch (Exception ex) {
870 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
871 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
875 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
876 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
877 }else if(result.getResult() == ResultType.FAILURE) {
878 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result.getResult()).setError(result.getMessage()).toMap()).build();
880 return response.status(Status.OK).entity(new JsonResponse(result.getResult()).setMessage("Insert Successful").toMap()).build();
882 EELFLoggerDelegate.mdcRemove("keyspace");
893 * @throws MusicServiceException
894 * @throws MusicQueryException
898 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
899 @ApiOperation(value = "Update Table", response = String.class)
900 @Consumes(MediaType.APPLICATION_JSON)
901 @Produces(MediaType.APPLICATION_JSON)
902 public Response updateTable(
903 @ApiParam(value = "Major Version",
904 required = true) @PathParam("version") String version,
905 @ApiParam(value = "Minor Version",
906 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
907 @ApiParam(value = "Patch Version",
908 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
909 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
910 @ApiParam(value = "Application namespace",
911 required = true) @HeaderParam(NS) String ns,
912 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
913 JsonUpdate updateObj,
914 @ApiParam(value = "Keyspace Name",
915 required = true) @PathParam("keyspace") String keyspace,
916 @ApiParam(value = "Table Name",
917 required = true) @PathParam("tablename") String tablename,
918 @Context UriInfo info) throws MusicQueryException, MusicServiceException {
920 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
921 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
922 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
923 .setError("one or more path parameters are not set, please check and try again")
926 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
927 if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.UPDATE_TABLE)) {
928 return response.status(Status.UNAUTHORIZED)
929 .entity(new JsonResponse(ResultType.FAILURE)
930 .setError("Unauthorized: Please check username, password and make sure your app is onboarded")
934 long startTime = System.currentTimeMillis();
935 String operationId = UUID.randomUUID().toString();// just for infoging
937 String consistency = updateObj.getConsistencyInfo().get("type");
939 logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency
940 + " update-" + operationId + "-------------------------");
941 // obtain the field value pairs of the update
943 PreparedQueryObject queryObject = new PreparedQueryObject();
944 Map<String, Object> valuesMap = updateObj.getValues();
946 TableMetadata tableInfo;
948 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
949 } catch (MusicServiceException e) {
950 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
951 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
953 if (tableInfo == null) {
954 logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+tablename, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
955 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
956 .setError("Table information not found. Please check input for table name= "
957 + keyspace + "." + tablename).toMap()).build();
960 String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
961 StringBuilder fieldValueString = new StringBuilder("vector_ts=?,");
962 queryObject.addValue(vectorTs);
964 for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
965 Object valueObj = entry.getValue();
966 DataType colType = null;
968 colType = tableInfo.getColumn(entry.getKey()).getType();
969 } catch(NullPointerException ex) {
970 logger.error(EELFLoggerDelegate.errorLogger, ex, "Invalid column name : "+entry.getKey());
971 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
973 Object valueString = null;
975 valueString = MusicUtil.convertToActualDataType(colType, valueObj);
976 } catch (Exception e) {
977 logger.error(EELFLoggerDelegate.errorLogger,e);
979 fieldValueString.append(entry.getKey() + "= ?");
980 queryObject.addValue(valueString);
981 if (counter != valuesMap.size() - 1)
982 fieldValueString.append(",");
983 counter = counter + 1;
985 String ttl = updateObj.getTtl();
986 String timestamp = updateObj.getTimestamp();
988 queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " ");
989 if ((ttl != null) && (timestamp != null)) {
991 logger.info("both there");
992 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
993 queryObject.addValue(Integer.parseInt(ttl));
994 queryObject.addValue(Long.parseLong(timestamp));
997 if ((ttl != null) && (timestamp == null)) {
998 logger.info("ONLY TTL there");
999 queryObject.appendQueryString(" USING TTL ?");
1000 queryObject.addValue(Integer.parseInt(ttl));
1003 if ((ttl == null) && (timestamp != null)) {
1004 logger.info("ONLY timestamp there");
1005 queryObject.appendQueryString(" USING TIMESTAMP ?");
1006 queryObject.addValue(Long.parseLong(timestamp));
1008 // get the row specifier
1009 RowIdentifier rowId = null;
1011 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1012 if(rowId == null || rowId.primarKeyValue.isEmpty()) {
1013 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1014 .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build();
1016 } catch (MusicServiceException ex) {
1017 logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1018 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1021 queryObject.appendQueryString(
1022 " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";");
1024 // get the conditional, if any
1025 Condition conditionInfo;
1026 if (updateObj.getConditions() == null)
1027 conditionInfo = null;
1028 else {// to avoid parsing repeatedly, just send the select query to
1030 PreparedQueryObject selectQuery = new PreparedQueryObject();
1031 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
1032 + rowId.rowIdString + ";");
1033 selectQuery.addValue(rowId.primarKeyValue);
1034 conditionInfo = new Condition(updateObj.getConditions(), selectQuery);
1037 ReturnType operationResult = null;
1038 long jsonParseCompletionTime = System.currentTimeMillis();
1040 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && updateObj.getConsistencyInfo().get("consistency") != null) {
1041 if(MusicUtil.isValidConsistency(updateObj.getConsistencyInfo().get("consistency")))
1042 queryObject.setConsistency(updateObj.getConsistencyInfo().get("consistency"));
1044 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
1046 queryObject.setOperation("update");
1047 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
1048 operationResult = MusicCore.eventualPut(queryObject);
1049 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1050 String lockId = updateObj.getConsistencyInfo().get("lockId");
1051 if(lockId == null) {
1052 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1053 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1054 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1055 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1057 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1058 queryObject, lockId, conditionInfo);
1059 } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) {
1060 // this function is mainly for the benchmarks
1062 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename,
1063 rowId.primarKeyValue, queryObject, conditionInfo);
1064 } catch (MusicLockingException e) {
1065 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1066 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1068 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1070 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1071 queryObject, conditionInfo);
1072 } catch (MusicLockingException e) {
1073 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1074 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
1076 }else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
1077 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1079 long actualUpdateCompletionTime = System.currentTimeMillis();
1081 long endTime = System.currentTimeMillis();
1082 String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId
1083 + ":" + "|total operation time:" + (endTime - startTime)
1084 + "|json parsing time:" + (jsonParseCompletionTime - startTime)
1085 + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime)
1088 if (operationResult != null && operationResult.getTimingInfo() != null) {
1089 String lockManagementTime = operationResult.getTimingInfo();
1090 timingString = timingString + lockManagementTime;
1092 logger.info(EELFLoggerDelegate.applicationLogger, timingString);
1094 if (operationResult==null) {
1095 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1096 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1098 if ( operationResult.getResult() == ResultType.SUCCESS ) {
1099 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1101 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1102 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(operationResult.getResult()).setError(operationResult.getMessage()).toMap()).build();
1105 EELFLoggerDelegate.mdcRemove("keyspace");
1116 * @throws MusicServiceException
1117 * @throws MusicQueryException
1121 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1122 @ApiOperation(value = "Delete From table", response = String.class)
1123 @Consumes(MediaType.APPLICATION_JSON)
1124 @Produces(MediaType.APPLICATION_JSON)
1125 public Response deleteFromTable(
1126 @ApiParam(value = "Major Version",
1127 required = true) @PathParam("version") String version,
1128 @ApiParam(value = "Minor Version",
1129 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1130 @ApiParam(value = "Patch Version",
1131 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1132 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1133 @ApiParam(value = "Application namespace",
1134 required = true) @HeaderParam(NS) String ns,
1135 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1137 @ApiParam(value = "Keyspace Name",
1138 required = true) @PathParam("keyspace") String keyspace,
1139 @ApiParam(value = "Table Name",
1140 required = true) @PathParam("tablename") String tablename,
1141 @Context UriInfo info) throws MusicQueryException, MusicServiceException {
1143 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1144 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1145 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1146 .setError("one or more path parameters are not set, please check and try again")
1149 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1150 if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.DELETE_FROM_TABLE)) {
1151 return response.status(Status.UNAUTHORIZED)
1152 .entity(new JsonResponse(ResultType.FAILURE)
1153 .setError("Unauthorized: Please check username, password and make sure your app is onboarded")
1157 if(delObj == null) {
1158 logger.error(EELFLoggerDelegate.errorLogger,"Required HTTP Request body is missing.", AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
1159 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Required HTTP Request body is missing.").toMap()).build();
1161 PreparedQueryObject queryObject = new PreparedQueryObject();
1162 StringBuilder columnString = new StringBuilder();
1165 List<String> columnList = delObj.getColumns();
1166 if (columnList != null) {
1167 for (String column : columnList) {
1168 columnString.append(column);
1169 if (counter != columnList.size() - 1)
1170 columnString.append(",");
1171 counter = counter + 1;
1175 // get the row specifier
1176 RowIdentifier rowId = null;
1178 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1179 } catch (MusicServiceException ex) {
1180 logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1181 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1183 String rowSpec = rowId.rowIdString.toString();
1185 if ((columnList != null) && (!rowSpec.isEmpty())) {
1186 queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "."
1187 + tablename + " WHERE " + rowSpec + ";");
1190 if ((columnList == null) && (!rowSpec.isEmpty())) {
1191 queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE "
1195 if ((columnList != null) && (rowSpec.isEmpty())) {
1196 queryObject.appendQueryString(
1197 "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";");
1199 // get the conditional, if any
1200 Condition conditionInfo;
1201 if (delObj.getConditions() == null)
1202 conditionInfo = null;
1203 else {// to avoid parsing repeatedly, just send the select query to
1205 PreparedQueryObject selectQuery = new PreparedQueryObject();
1206 selectQuery.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + " WHERE "
1207 + rowId.rowIdString + ";");
1208 selectQuery.addValue(rowId.primarKeyValue);
1209 conditionInfo = new Condition(delObj.getConditions(), selectQuery);
1212 String consistency = delObj.getConsistencyInfo().get("type");
1215 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && delObj.getConsistencyInfo().get("consistency")!=null) {
1217 if(MusicUtil.isValidConsistency(delObj.getConsistencyInfo().get("consistency")))
1218 queryObject.setConsistency(delObj.getConsistencyInfo().get("consistency"));
1220 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
1223 ReturnType operationResult = null;
1224 queryObject.setOperation("delete");
1226 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
1227 operationResult = MusicCore.eventualPut(queryObject);
1228 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1229 String lockId = delObj.getConsistencyInfo().get("lockId");
1230 if(lockId == null) {
1231 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1232 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1233 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1234 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1236 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1237 queryObject, lockId, conditionInfo);
1238 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1239 operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1240 queryObject, conditionInfo);
1242 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
1243 operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename, rowId.primarKeyValue,
1244 queryObject, conditionInfo);
1245 }else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
1247 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1249 } catch (MusicLockingException e) {
1250 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1251 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1252 .setError("Unable to perform Delete operation. Exception from music").toMap()).build();
1254 if (operationResult==null) {
1255 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1256 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1258 if (operationResult.getResult().equals(ResultType.SUCCESS)) {
1259 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1261 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1262 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap()).build();
1265 EELFLoggerDelegate.mdcRemove("keyspace");
1277 @Path("/{keyspace: .*}/tables/{tablename: .*}")
1278 @ApiOperation(value = "Drop Table", response = String.class)
1279 @Produces(MediaType.APPLICATION_JSON)
1280 public Response dropTable(
1281 @ApiParam(value = "Major Version",
1282 required = true) @PathParam("version") String version,
1283 @ApiParam(value = "Minor Version",
1284 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1285 @ApiParam(value = "Patch Version",
1286 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1287 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1288 @ApiParam(value = "Application namespace",
1289 required = true) @HeaderParam(NS) String ns,
1290 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1291 @ApiParam(value = "Keyspace Name",
1292 required = true) @PathParam("keyspace") String keyspace,
1293 @ApiParam(value = "Table Name",
1294 required = true) @PathParam("tablename") String tablename) throws Exception {
1296 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1297 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1298 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1299 .setError("one or more path parameters are not set, please check and try again")
1302 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1303 if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.DROP_TABLE)) {
1304 return response.status(Status.UNAUTHORIZED)
1305 .entity(new JsonResponse(ResultType.FAILURE)
1306 .setError("Unauthorized: Please check username, password and make sure your app is onboarded")
1310 String consistency = "eventual";// for now this needs only eventual
1312 PreparedQueryObject query = new PreparedQueryObject();
1313 query.appendQueryString("DROP TABLE " + keyspace + "." + tablename + ";");
1315 return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build();
1316 } catch (MusicServiceException ex) {
1317 logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1318 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1321 EELFLoggerDelegate.mdcRemove("keyspace");
1334 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows/criticalget")
1335 @ApiOperation(value = "Select Critical", response = Map.class)
1336 @Consumes(MediaType.APPLICATION_JSON)
1337 @Produces(MediaType.APPLICATION_JSON)
1338 public Response selectCritical(
1339 @ApiParam(value = "Major Version",
1340 required = true) @PathParam("version") String version,
1341 @ApiParam(value = "Minor Version",
1342 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1343 @ApiParam(value = "Patch Version",
1344 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1345 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1346 @ApiParam(value = "Application namespace",
1347 required = true) @HeaderParam(NS) String ns,
1348 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1350 @ApiParam(value = "Keyspace Name",
1351 required = true) @PathParam("keyspace") String keyspace,
1352 @ApiParam(value = "Table Name",
1353 required = true) @PathParam("tablename") String tablename,
1354 @Context UriInfo info) throws Exception {
1356 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1357 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1358 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1359 .setError("one or more path parameters are not set, please check and try again")
1362 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1363 if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.SELECT_CRITICAL)) {
1364 return response.status(Status.UNAUTHORIZED)
1365 .entity(new JsonResponse(ResultType.FAILURE)
1366 .setError("Unauthorized: Please check username, password and make sure your app is onboarded")
1370 String lockId = selObj.getConsistencyInfo().get("lockId");
1372 PreparedQueryObject queryObject = new PreparedQueryObject();
1374 RowIdentifier rowId = null;
1376 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1377 } catch (MusicServiceException ex) {
1378 logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1379 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1381 queryObject.appendQueryString(
1382 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";");
1384 ResultSet results = null;
1386 String consistency = selObj.getConsistencyInfo().get("type");
1388 if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1389 if(lockId == null) {
1390 logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1391 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1392 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1393 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1395 results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,
1397 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1398 results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject);
1401 else if (consistency.equalsIgnoreCase(MusicUtil.ATOMICDELETELOCK)) {
1402 results = MusicCore.atomicGetWithDeleteLock(keyspace, tablename, rowId.primarKeyValue, queryObject);
1404 if(results!=null && results.getAvailableWithoutFetching() >0) {
1405 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1407 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").toMap()).build();
1410 EELFLoggerDelegate.mdcRemove("keyspace");
1423 @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1424 @ApiOperation(value = "Select All or Select Specific", response = Map.class)
1425 @Produces(MediaType.APPLICATION_JSON)
1426 public Response select(
1427 @ApiParam(value = "Major Version",
1428 required = true) @PathParam("version") String version,
1429 @ApiParam(value = "Minor Version",
1430 required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1431 @ApiParam(value = "Patch Version",
1432 required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1433 @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
1434 @ApiParam(value = "Application namespace",
1435 required = true) @HeaderParam(NS) String ns,
1436 @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1437 @ApiParam(value = "Keyspace Name",
1438 required = true) @PathParam("keyspace") String keyspace,
1439 @ApiParam(value = "Table Name",
1440 required = true) @PathParam("tablename") String tablename,
1441 @Context UriInfo info) throws Exception {
1443 ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1444 if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1445 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1446 .setError("one or more path parameters are not set, please check and try again")
1449 EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1450 if (!authenticator.authenticateUser(ns, authorization, keyspace, aid, Operation.SELECT)) {
1451 return response.status(Status.UNAUTHORIZED)
1452 .entity(new JsonResponse(ResultType.FAILURE)
1453 .setError("Unauthorized: Please check username, password and make sure your app is onboarded")
1457 PreparedQueryObject queryObject = new PreparedQueryObject();
1459 if (info.getQueryParameters().isEmpty())// select all
1460 queryObject.appendQueryString("SELECT * FROM " + keyspace + "." + tablename + ";");
1462 int limit = -1; // do not limit the number of results
1464 queryObject = selectSpecificQuery(keyspace, tablename, info, limit);
1465 } catch (MusicServiceException ex) {
1466 logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1467 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1472 ResultSet results = MusicCore.get(queryObject);
1473 if(results.getAvailableWithoutFetching() >0) {
1474 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1476 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).setError("No data found").toMap()).build();
1477 } catch (MusicServiceException ex) {
1478 logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.ERROR, ErrorTypes.MUSICSERVICEERROR);
1479 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1482 EELFLoggerDelegate.mdcRemove("keyspace");
1493 * @throws MusicServiceException
1495 public PreparedQueryObject selectSpecificQuery(String keyspace,
1496 String tablename, UriInfo info, int limit)
1497 throws MusicServiceException {
1499 PreparedQueryObject queryObject = new PreparedQueryObject();
1500 StringBuilder rowIdString = getRowIdentifier(keyspace, tablename, info.getQueryParameters(),
1501 queryObject).rowIdString;
1503 queryObject.appendQueryString(
1504 "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
1507 queryObject.appendQueryString(" LIMIT " + limit);
1510 queryObject.appendQueryString(";");
1520 * @param queryObject
1522 * @throws MusicServiceException
1524 private RowIdentifier getRowIdentifier(String keyspace, String tablename,
1525 MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
1526 throws MusicServiceException {
1527 StringBuilder rowSpec = new StringBuilder();
1529 TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
1530 if (tableInfo == null) {
1531 logger.error(EELFLoggerDelegate.errorLogger,
1532 "Table information not found. Please check input for table name= "
1533 + keyspace + "." + tablename);
1534 throw new MusicServiceException(
1535 "Table information not found. Please check input for table name= "
1536 + keyspace + "." + tablename);
1538 StringBuilder primaryKey = new StringBuilder();
1539 for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
1540 String keyName = entry.getKey();
1541 List<String> valueList = entry.getValue();
1542 String indValue = valueList.get(0);
1543 DataType colType = null;
1544 Object formattedValue = null;
1546 colType = tableInfo.getColumn(entry.getKey()).getType();
1547 formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
1548 } catch (Exception e) {
1549 logger.error(EELFLoggerDelegate.errorLogger,e);
1551 if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey()))
1552 primaryKey.append(indValue);
1553 rowSpec.append(keyName + "= ?");
1554 queryObject.addValue(formattedValue);
1555 if (counter != rowParams.size() - 1)
1556 rowSpec.append(" AND ");
1557 counter = counter + 1;
1559 return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);