219e713c868dfdf43bcf69e1c4cf5926a558a1ff
[music.git] / src / main / java / org / onap / music / rest / RestMusicDataAPI.java
1 /*
2  * ============LICENSE_START==========================================
3  * org.onap.music
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
12  *
13  *     http://www.apache.org/licenses/LICENSE-2.0
14  *
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.
20  *
21  * ============LICENSE_END=============================================
22  * ====================================================================
23  */
24
25 package org.onap.music.rest;
26
27 import java.nio.ByteBuffer;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.UUID;
31
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;
48
49 import org.apache.commons.lang3.StringUtils;
50 import org.onap.music.datastore.PreparedQueryObject;
51 import org.onap.music.datastore.jsonobjects.JsonDelete;
52 import org.onap.music.datastore.jsonobjects.JsonInsert;
53 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
54 import org.onap.music.datastore.jsonobjects.JsonTable;
55 import org.onap.music.datastore.jsonobjects.JsonUpdate;
56 import org.onap.music.eelf.logging.EELFLoggerDelegate;
57 import org.onap.music.exceptions.MusicLockingException;
58 import org.onap.music.exceptions.MusicQueryException;
59 import org.onap.music.eelf.logging.format.AppMessages;
60 import org.onap.music.eelf.logging.format.ErrorSeverity;
61 import org.onap.music.eelf.logging.format.ErrorTypes;
62 import org.onap.music.exceptions.MusicServiceException;
63 import org.onap.music.main.MusicCore;
64 import org.onap.music.datastore.Condition;
65 import org.onap.music.datastore.MusicDataStoreHandle;
66 import org.onap.music.main.MusicUtil;
67 import org.onap.music.main.ResultType;
68 import org.onap.music.main.ReturnType;
69 import org.onap.music.response.jsonobjects.JsonResponse;
70
71 import com.datastax.driver.core.DataType;
72 import com.datastax.driver.core.ResultSet;
73 import com.datastax.driver.core.TableMetadata;
74
75 import io.swagger.annotations.Api;
76 import io.swagger.annotations.ApiOperation;
77 import io.swagger.annotations.ApiParam;
78 import io.swagger.annotations.ApiResponses;
79 import io.swagger.annotations.ApiResponse;
80
81 /* Version 2 Class */
82 //@Path("/v{version: [0-9]+}/keyspaces")
83 @Path("/v2/keyspaces")
84 @Api(value = "Data Api")
85 public class RestMusicDataAPI {
86     /*
87      * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR
88      * version back from the client to the server, and from the server back to the client - This
89      * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR
90      * version (if not specified by the client on the request) - Contains a single position value
91      * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on
92      * request; however, this header should be provided if the client needs to take advantage of
93      * MINOR incremented version functionality - Is mandatory for the server on response
94      *
95      *** X-patchVersion *** - Used only to communicate a PATCH version in a response for
96      * troubleshooting purposes only, and will not be provided by the client on request - This will
97      * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version
98      * of the MAJOR (if not specified by the client on the request) - Contains a single position
99      * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the
100      * server on response  (CURRENTLY NOT USED)
101      *
102      *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the
103      * server on response, and shall include the entire version of the API (e.g. if the full version
104      * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are
105      * not using the latest version of the API (CURRENTLY NOT USED)
106      *
107      */
108
109     private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class);
110     private static final String XMINORVERSION = "X-minorVersion";
111     private static final String XPATCHVERSION = "X-patchVersion";
112     private static final String NS = "ns";
113     private static final String VERSION = "v2";
114
115     private class RowIdentifier {
116         public String primarKeyValue;
117         public StringBuilder rowIdString;
118         @SuppressWarnings("unused")
119         public PreparedQueryObject queryObject; // the string with all the row
120                                                 // identifiers separated by AND
121
122         public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
123                         PreparedQueryObject queryObject) {
124             this.primarKeyValue = primaryKeyValue;
125             this.rowIdString = rowIdString;
126             this.queryObject = queryObject;
127         }
128     }
129
130
131     /**
132      * Create Keyspace REST
133      *
134      * @param kspObject
135      * @param keyspaceName
136      * @return
137      * @throws Exception
138      */
139     @POST
140     @Path("/{name}")
141     @ApiOperation(value = "Create Keyspace", response = String.class,hidden = true)
142     @Consumes(MediaType.APPLICATION_JSON)
143     @Produces(MediaType.APPLICATION_JSON)
144     public Response createKeySpace(
145         @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
146         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
147         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
148         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
149         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
150         @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
151         JsonKeySpace kspObject,
152         @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) {
153         try {
154             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
155             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
156             logger.info(EELFLoggerDelegate.applicationLogger,"In Create Keyspace " + keyspaceName);
157             if (MusicUtil.isKeyspaceActive() ) {
158                 logger.info(EELFLoggerDelegate.applicationLogger,"Creating Keyspace " + keyspaceName);
159                 
160                 if(kspObject == null || kspObject.getReplicationInfo() == null) {
161                     response.status(Status.BAD_REQUEST);
162                     return response.entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
163                 }
164         
165                 String consistency = MusicUtil.EVENTUAL;// for now this needs only eventual consistency
166         
167                 PreparedQueryObject queryObject = new PreparedQueryObject();
168                 if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && kspObject.getConsistencyInfo().get("consistency") != null) {
169                     if(MusicUtil.isValidConsistency(kspObject.getConsistencyInfo().get("consistency")))
170                         queryObject.setConsistency(kspObject.getConsistencyInfo().get("consistency"));
171                     else
172                         return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
173                 }
174                 long start = System.currentTimeMillis();
175                 Map<String, Object> replicationInfo = kspObject.getReplicationInfo();
176                 String repString = null;
177                 try {
178                     repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}";
179                 } catch (Exception e) {
180                     logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.MISSINGDATA  ,ErrorSeverity
181                         .CRITICAL, ErrorTypes.DATAERROR, e);
182         
183                 }
184                 queryObject.appendQueryString(
185                                 "CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString);
186                 if (kspObject.getDurabilityOfWrites() != null) {
187                     queryObject.appendQueryString(
188                                     " AND durable_writes = " + kspObject.getDurabilityOfWrites());
189                 }
190         
191                 queryObject.appendQueryString(";");
192                 long end = System.currentTimeMillis();
193                 logger.info(EELFLoggerDelegate.applicationLogger,
194                                 "Time taken for setting up query in create keyspace:" + (end - start));
195         
196                 ResultType result = ResultType.FAILURE;
197                 try {
198                     result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
199                     logger.info(EELFLoggerDelegate.applicationLogger, "result = " + result);
200                 } catch ( MusicServiceException ex) {
201                     logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity
202                         .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
203                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("err:" + ex.getMessage()).toMap()).build();
204                 }
205         
206                 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build();
207             } else {
208                 String vError = "Keyspace Creation has been turned off. Contact DBA to create the keyspace or set keyspace.active to true.";
209                 logger.info(EELFLoggerDelegate.applicationLogger,vError);
210                 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
211                 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
212             }
213         } finally {
214             EELFLoggerDelegate.mdcRemove("keyspace");
215         }
216         
217     }
218
219     /**
220      *
221      * @param kspObject
222      * @param keyspaceName
223      * @return
224      * @throws Exception
225      */
226     @DELETE
227     @Path("/{name}")
228     @ApiOperation(value = "Delete Keyspace", response = String.class,hidden=true)
229     @Produces(MediaType.APPLICATION_JSON)
230     public Response dropKeySpace(
231         @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
232         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
233         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
234         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
235         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
236         @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
237         @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) throws Exception {
238         try {
239             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
240             EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) ");
241             logger.info(EELFLoggerDelegate.applicationLogger,"In Drop Keyspace " + keyspaceName);
242             if (MusicUtil.isKeyspaceActive()) {
243                 String consistency = MusicUtil.EVENTUAL;// for now this needs only
244                 PreparedQueryObject queryObject = new PreparedQueryObject();
245                 queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";");
246                 ResultType result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
247                 if ( result.equals(ResultType.FAILURE) ) {
248                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Deleteing Keyspace " + keyspaceName).toMap()).build();
249                 }
250                 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build();
251             } else {
252                 String vError = "Keyspace deletion has been turned off. Contact DBA to delete the keyspace or set keyspace.active to true.";
253                 logger.info(EELFLoggerDelegate.applicationLogger,vError);
254                 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
255                 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
256             }
257         } finally {
258             EELFLoggerDelegate.mdcRemove("keyspace");
259         }
260     }
261
262     /**
263      *
264      * @param tableObj
265      * @param version
266      * @param keyspace
267      * @param tablename
268      * @param headers
269      * @return
270      * @throws Exception -
271      */
272     @POST
273     @Path("/{keyspace: .*}/tables/{tablename: .*}")
274     @ApiOperation(value = "Create Table", response = String.class)
275     @Consumes(MediaType.APPLICATION_JSON)
276     @Produces(MediaType.APPLICATION_JSON)
277     @ApiResponses(value={
278         @ApiResponse(code= 400, message = "Will return JSON response with message"),
279         @ApiResponse(code= 401, message = "Unautorized User")
280     })
281     public Response createTable(
282         @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
283         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
284         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
285         @ApiParam(value = "AID", required = false,hidden = true) @HeaderParam("aid") String aid,
286         @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
287         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
288         JsonTable tableObj,
289         @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
290         @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename) throws Exception {
291         try {
292             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
293             if ( null == tableObj ) {
294                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
295                         .setError(ResultType.BODYMISSING.getResult()).toMap()).build();
296             }
297             if(keyspace == null || keyspace.isEmpty() || tablename == null || tablename.isEmpty()){
298                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
299                         .setError("One or more path parameters are not set, please check and try again."
300                             + "Parameter values: keyspace='" + keyspace + "' tablename='" + tablename + "'")
301                             .toMap()).build();
302             }
303             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
304             String consistency = MusicUtil.EVENTUAL;
305             // for now this needs only eventual consistency
306             String primaryKey = null;
307             String partitionKey = tableObj.getPartitionKey();
308             String clusterKey = tableObj.getClusteringKey();
309             String filteringKey = tableObj.getFilteringKey();
310             if(filteringKey != null) {
311                 clusterKey = clusterKey + "," + filteringKey;
312             }
313             primaryKey = tableObj.getPrimaryKey(); // get primaryKey if available
314
315             PreparedQueryObject queryObject = new PreparedQueryObject();
316             // first read the information about the table fields
317             Map<String, String> fields = tableObj.getFields();
318             if (fields == null) {
319                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
320                     .setError("Create Table Error: No fields in request").toMap()).build();
321             }
322
323             StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
324             int counter = 0;
325             for (Map.Entry<String, String> entry : fields.entrySet()) {
326                 if (entry.getKey().equals("PRIMARY KEY")) {
327                     primaryKey = entry.getValue(); // replaces primaryKey
328                     primaryKey = primaryKey.trim();
329                 } else {
330                     if (counter == 0 )  fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
331                     else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
332                 }
333
334                 if (counter != (fields.size() - 1) ) {
335                     counter = counter + 1; 
336                 } else {
337             
338                     if((primaryKey != null) && (partitionKey == null)) {
339                         primaryKey = primaryKey.trim();
340                         int count1 = StringUtils.countMatches(primaryKey, ')');
341                         int count2 = StringUtils.countMatches(primaryKey, '(');
342                         if (count1 != count2) {
343                             return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
344                                 .setError("Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey)
345                                 .toMap()).build();
346                         }
347
348                         if ( primaryKey.indexOf('(') == -1  || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) ==  primaryKey.length() ) ) {
349                             if (primaryKey.contains(",") ) {
350                                 partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
351                                 partitionKey=partitionKey.replaceAll("[\\(]+","");
352                                 clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1);  // make sure index
353                                 clusterKey=clusterKey.replaceAll("[)]+", "");
354                             } else {
355                                 partitionKey=primaryKey;
356                                 partitionKey=partitionKey.replaceAll("[\\)]+","");
357                                 partitionKey=partitionKey.replaceAll("[\\(]+","");
358                                 clusterKey="";
359                             }
360                         } else {   // not null and has ) before the last char
361                             partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
362                             partitionKey=partitionKey.replaceAll("[\\(]+","");
363                             partitionKey = partitionKey.trim();
364                             clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
365                             clusterKey=clusterKey.replaceAll("[\\(]+","");
366                             clusterKey=clusterKey.replaceAll("[\\)]+","");
367                             clusterKey = clusterKey.trim();
368                             if (clusterKey.indexOf(',') == 0) {
369                                 clusterKey=clusterKey.substring(1);
370                             }
371                             clusterKey = clusterKey.trim();
372                             if (clusterKey.equals(",") ) clusterKey=""; // print error if needed    ( ... ),)
373                         }
374
375                         if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
376                             && (partitionKey.equalsIgnoreCase(clusterKey) ||
377                             clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
378                             logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
379                             return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
380                                 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")  of"
381                                 + " primary key=" + primaryKey)
382                                 .toMap()).build();
383
384                         }
385
386                         if (partitionKey.isEmpty() )  primaryKey="";
387                         else  if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey  + ")";
388                         else  primaryKey=" (" + partitionKey + ")," + clusterKey;
389
390                 
391                         if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
392
393                     } else { // end of length > 0
394                     
395                         if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
396                             && (partitionKey.equalsIgnoreCase(clusterKey) ||
397                             clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
398                             logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
399                             return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
400                                 "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
401                                 .toMap()).build();
402                         }
403
404                         if (partitionKey.isEmpty() )  primaryKey="";
405                         else  if (clusterKey.isEmpty() ) primaryKey=" (" + partitionKey  + ")";
406                         else  primaryKey=" (" + partitionKey + ")," + clusterKey;
407
408                         if (primaryKey != null) fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
409                     }
410                     fieldsString.append(")");
411
412                 } // end of last field check
413
414             } // end of for each
415             // information about the name-value style properties
416             Map<String, Object> propertiesMap = tableObj.getProperties();
417             StringBuilder propertiesString = new StringBuilder();
418             if (propertiesMap != null) {
419                 counter = 0;
420                 for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
421                     Object ot = entry.getValue();
422                     String value = ot + "";
423                     if (ot instanceof String) {
424                         value = "'" + value + "'";
425                     } else if (ot instanceof Map) {
426                         @SuppressWarnings("unchecked")
427                         Map<String, Object> otMap = (Map<String, Object>) ot;
428                         value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
429                     }
430
431                     propertiesString.append(entry.getKey() + "=" + value + "");
432                     if (counter != propertiesMap.size() - 1)
433                         propertiesString.append(" AND ");
434
435                     counter = counter + 1;
436                 }
437             }
438
439             String clusteringOrder = tableObj.getClusteringOrder();
440
441             if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
442                 String[] arrayClusterOrder = clusteringOrder.split("[,]+");
443
444                 for (int i = 0; i < arrayClusterOrder.length; i++) {
445                     String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
446                     if ( (clusterS.length ==2)  && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
447                         continue;
448                     } else {
449                         return response.status(Status.BAD_REQUEST)
450                         .entity(new JsonResponse(ResultType.FAILURE)
451                         .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname  order; please correct clusteringOrder:"+ clusteringOrder+".")
452                         .toMap()).build();
453                     }
454                     // add validation for column names in cluster key
455                 }
456
457                 if (!(clusterKey.isEmpty())) {
458                     clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
459                     //cjc check if propertiesString.length() >0 instead propertiesMap
460                     if (propertiesMap != null) {
461                         propertiesString.append(" AND  "+ clusteringOrder);
462                     } else {
463                         propertiesString.append(clusteringOrder);
464                     }
465                 } else {
466                     logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
467                 }
468             } //if non empty
469
470             queryObject.appendQueryString(
471                 "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString);
472
473
474             if (propertiesString != null &&  propertiesString.length()>0 )
475                 queryObject.appendQueryString(" WITH " + propertiesString);
476             queryObject.appendQueryString(";");
477             ResultType result = ResultType.FAILURE;
478             try {
479                 result = MusicCore.createTable(keyspace, tablename, queryObject, consistency);
480             } catch (MusicServiceException ex) {
481                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity.CRITICAL, ErrorTypes.MUSICSERVICEERROR);
482                 response.status(Status.BAD_REQUEST);
483                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
484             }
485             if ( result.equals(ResultType.FAILURE) ) {
486                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Creating Table " + tablename).toMap()).build();
487             }
488             return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("TableName " + tablename.trim() + " Created under keyspace " + keyspace.trim()).toMap()).build();
489         } finally {
490             EELFLoggerDelegate.mdcRemove("keyspace");
491         }
492     }
493
494     /**
495      *
496      * @param keyspace
497      * @param tablename
498      * @param fieldName
499      * @param info
500      * @throws Exception
501      */
502     @POST
503     @Path("/{keyspace: .*}/tables/{tablename: .*}/index/{field: .*}")
504     @ApiOperation(value = "Create Index", response = String.class)
505     @Produces(MediaType.APPLICATION_JSON)
506     public Response createIndex(
507         @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
508         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
509         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
510         @ApiParam(value = "AID", required = false) @HeaderParam("aid") String aid,
511         @ApiParam(value = "Application namespace",required = true) @HeaderParam(NS) String ns,
512         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
513         @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
514         @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename,
515         @ApiParam(value = "Field Name",required = true) @PathParam("field") String fieldName,
516         @Context UriInfo info) throws Exception {
517         try {
518             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
519             if ((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty()) || (fieldName == null || fieldName.isEmpty())){
520                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
521                     .setError("one or more path parameters are not set, please check and try again")
522                     .toMap()).build();
523             }
524             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
525             MultivaluedMap<String, String> rowParams = info.getQueryParameters();
526             String indexName = "";
527             if (rowParams.getFirst("index_name") != null)
528                 indexName = rowParams.getFirst("index_name");
529             PreparedQueryObject query = new PreparedQueryObject();
530             query.appendQueryString("Create index if not exists " + indexName + "  on " + keyspace + "."
531                             + tablename + " (" + fieldName + ");");
532
533             ResultType result = ResultType.FAILURE;
534             try {
535                 result = MusicCore.nonKeyRelatedPut(query, "eventual");
536             } catch (MusicServiceException ex) {
537                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity
538                 .CRITICAL, ErrorTypes.GENERALSERVICEERROR, ex);
539                 response.status(Status.BAD_REQUEST);
540                 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
541             }
542             if ( result.equals(ResultType.SUCCESS) ) {
543                 return response.status(Status.OK).entity(new JsonResponse(result).setMessage("Index Created on " + keyspace+"."+tablename+"."+fieldName).toMap()).build();
544             } else {
545                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Unknown Error in create index.").toMap()).build();
546             }
547         } finally {
548             EELFLoggerDelegate.mdcRemove("keyspace");
549         }
550     }
551
552     /**
553      *
554      * @param insObj
555      * @param keyspace
556      * @param tablename
557      * @return
558      * @throws Exception
559      */
560     @POST
561     @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
562     @ApiOperation(value = "Insert Into Table", response = String.class)
563     @Consumes(MediaType.APPLICATION_JSON)
564     @Produces(MediaType.APPLICATION_JSON)
565     public Response insertIntoTable(
566         @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
567         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
568         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
569         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
570         @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
571         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
572         JsonInsert insObj,
573         @ApiParam(value = "Keyspace Name",
574             required = true) @PathParam("keyspace") String keyspace,
575         @ApiParam(value = "Table Name",
576             required = true) @PathParam("tablename") String tablename) {
577         try {
578             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
579             if ( null == insObj ) {
580                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
581                         .setError(ResultType.BODYMISSING.getResult()).toMap()).build();
582             }
583             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
584             return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
585                 .setError("one or more path parameters are not set, please check and try again")
586                 .toMap()).build();
587             }
588             EELFLoggerDelegate.mdcPut("keyspace","(" + keyspace + ")");
589             PreparedQueryObject queryObject = new PreparedQueryObject();
590             TableMetadata tableInfo = null;
591             try {
592                 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
593                 if(tableInfo == null) {
594                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Table name doesn't exists. Please check the table name.").toMap()).build();
595                 }
596             } catch (MusicServiceException e) {
597                 logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
598                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
599             }
600             String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();
601             StringBuilder fieldsString = new StringBuilder("(vector_ts,");
602             String vectorTs =
603                             String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
604             StringBuilder valueString = new StringBuilder("(" + "?" + ",");
605             queryObject.addValue(vectorTs);
606             
607             Map<String, Object> valuesMap = insObj.getValues();
608             if (valuesMap==null) {
609                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
610                         .setError("Nothing to insert. No values provided in request.").toMap()).build();
611             }
612             int counter = 0;
613             String primaryKey = "";
614             for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
615                 fieldsString.append("" + entry.getKey());
616                 Object valueObj = entry.getValue();
617                 if (primaryKeyName.equals(entry.getKey())) {
618                     primaryKey = entry.getValue() + "";
619                     primaryKey = primaryKey.replace("'", "''");
620                 }
621                 DataType colType = null;
622                 try {
623                     colType = tableInfo.getColumn(entry.getKey()).getType();
624                 } catch(NullPointerException ex) {
625                     logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey
626                         (), AppMessages.INCORRECTDATA  ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR, ex);
627                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
628                 }
629
630                 Object formattedValue = null;
631                 try {
632                     formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
633                 } catch (Exception e) {
634                     logger.error(EELFLoggerDelegate.errorLogger,e);
635                 }
636                 valueString.append("?");
637
638                 queryObject.addValue(formattedValue);
639
640                 if (counter == valuesMap.size() - 1) {
641                     fieldsString.append(")");
642                     valueString.append(")");
643                 } else {
644                     fieldsString.append(",");
645                     valueString.append(",");
646                 }
647                 counter = counter + 1;
648             }
649
650             //blobs..
651             Map<String, byte[]> objectMap = insObj.getObjectMap();
652             if(objectMap != null) {
653                 for (Map.Entry<String, byte[]> entry : objectMap.entrySet()) {
654                     if(counter > 0) {
655                         fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ",");
656                         valueString.replace(valueString.length()-1, valueString.length(), ",");
657                     }
658                     fieldsString.append("" + entry.getKey());
659                     byte[] valueObj = entry.getValue();
660                     if (primaryKeyName.equals(entry.getKey())) {
661                         primaryKey = entry.getValue() + "";
662                         primaryKey = primaryKey.replace("'", "''");
663                     }
664                     DataType colType = tableInfo.getColumn(entry.getKey()).getType();
665                     ByteBuffer formattedValue = null;
666                     if(colType.toString().toLowerCase().contains("blob")) {
667                         formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
668                     }
669                     valueString.append("?");
670                     queryObject.addValue(formattedValue);
671                     counter = counter + 1;
672                     fieldsString.append(",");
673                     valueString.append(",");
674                 } 
675             }
676
677             if(primaryKey == null || primaryKey.length() <= 0) {
678                 logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName );
679                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Some required partition key parts are missing: "+primaryKeyName).toMap()).build();
680             }
681
682             fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")");
683             valueString.replace(valueString.length()-1, valueString.length(), ")");
684
685             queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " "
686                             + fieldsString + " VALUES " + valueString);
687
688             String ttl = insObj.getTtl();
689             String timestamp = insObj.getTimestamp();
690
691             if ((ttl != null) && (timestamp != null)) {
692                 logger.info(EELFLoggerDelegate.applicationLogger, "both there");
693                 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
694                 queryObject.addValue(Integer.parseInt(ttl));
695                 queryObject.addValue(Long.parseLong(timestamp));
696             }
697
698             if ((ttl != null) && (timestamp == null)) {
699                 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there");
700                 queryObject.appendQueryString(" USING TTL ?");
701                 queryObject.addValue(Integer.parseInt(ttl));
702             }
703
704             if ((ttl == null) && (timestamp != null)) {
705                 logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there");
706                 queryObject.appendQueryString(" USING TIMESTAMP ?");
707                 queryObject.addValue(Long.parseLong(timestamp));
708             }
709
710             queryObject.appendQueryString(";");
711
712             ReturnType result = null;
713             String consistency = insObj.getConsistencyInfo().get("type");
714             if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && insObj.getConsistencyInfo().get("consistency") != null) {
715                 if(MusicUtil.isValidConsistency(insObj.getConsistencyInfo().get("consistency"))) {
716                     queryObject.setConsistency(insObj.getConsistencyInfo().get("consistency"));
717                 } else {
718                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
719                 }
720             }
721             queryObject.setOperation("insert");
722             try {
723                 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
724                     result = MusicCore.eventualPut(queryObject);
725                 } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
726                     String lockId = insObj.getConsistencyInfo().get("lockId");
727                     if(lockId == null) {
728                         logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
729                                 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
730                         return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
731                                 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
732                     }
733                     result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,null);
734                 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
735                     result = MusicCore.atomicPut(keyspace, tablename, primaryKey, queryObject, null);
736                 }
737             } catch (Exception ex) {
738                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity
739                     .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
740                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
741             }
742             if (result==null) {
743                 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
744                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
745             }else if(result.getResult() == ResultType.FAILURE) {
746                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result.getResult()).setError(result.getMessage()).toMap()).build();
747             }
748             return response.status(Status.OK).entity(new JsonResponse(result.getResult()).setMessage("Insert Successful").toMap()).build();
749         } finally {
750             EELFLoggerDelegate.mdcRemove("keyspace");
751         }
752     }
753
754     /**
755      *
756      * @param insObj
757      * @param keyspace
758      * @param tablename
759      * @param info
760      * @return
761      * @throws MusicServiceException 
762      * @throws MusicQueryException 
763      * @throws Exception
764      */
765     @PUT
766     @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
767     @ApiOperation(value = "Update Table", response = String.class)
768     @Consumes(MediaType.APPLICATION_JSON)
769     @Produces(MediaType.APPLICATION_JSON)
770     public Response updateTable(
771         @ApiParam(value = "Major Version",
772             required = true) @PathParam("version") String version,
773         @ApiParam(value = "Minor Version",
774             required = false) @HeaderParam(XMINORVERSION) String minorVersion,
775         @ApiParam(value = "Patch Version",
776             required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
777         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
778         @ApiParam(value = "Application namespace",
779             required = false, hidden = true) @HeaderParam(NS) String ns,
780         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
781         JsonUpdate updateObj,
782         @ApiParam(value = "Keyspace Name",
783             required = true) @PathParam("keyspace") String keyspace,
784         @ApiParam(value = "Table Name",
785             required = true) @PathParam("tablename") String tablename,
786         @Context UriInfo info) throws MusicQueryException, MusicServiceException {
787         try {
788             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
789             if ( null == updateObj ) {
790                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
791                         .setError(ResultType.BODYMISSING.getResult()).toMap()).build();
792             }
793             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
794                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
795                     .setError("one or more path parameters are not set, please check and try again")
796                     .toMap()).build();
797             }
798             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
799             long startTime = System.currentTimeMillis();
800             String operationId = UUID.randomUUID().toString();  // just for infoging
801                                                                 // purposes.
802             String consistency = updateObj.getConsistencyInfo().get("type");
803
804             logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency
805                 + " update-" + operationId + "-------------------------");
806             // obtain the field value pairs of the update
807
808             PreparedQueryObject queryObject = new PreparedQueryObject();
809             Map<String, Object> valuesMap = updateObj.getValues();
810
811             TableMetadata tableInfo;
812             try {
813                 tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
814             } catch (MusicServiceException e) {
815                 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes
816                     .GENERALSERVICEERROR, e);
817                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
818             }
819             if (tableInfo == null) {
820                 logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+tablename, AppMessages.MISSINGINFO  ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
821                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
822                     .setError("Table information not found. Please check input for table name= "
823                     + keyspace + "." + tablename).toMap()).build();
824             }
825             String vectorTs = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
826             StringBuilder fieldValueString = new StringBuilder("vector_ts=?,");
827             queryObject.addValue(vectorTs);
828             int counter = 0;
829             for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
830                 Object valueObj = entry.getValue();
831                 DataType colType = null;
832                 try {
833                     colType = tableInfo.getColumn(entry.getKey()).getType();
834                 } catch(NullPointerException ex) {
835                     logger.error(EELFLoggerDelegate.errorLogger, ex, "Invalid column name : "+entry.getKey(), ex);
836                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Invalid column name : "+entry.getKey()).toMap()).build();
837                 }
838                 Object valueString = null;
839                 try {
840                     valueString = MusicUtil.convertToActualDataType(colType, valueObj);
841                 } catch (Exception e) {
842                     logger.error(EELFLoggerDelegate.errorLogger,e);
843                 }
844                 fieldValueString.append(entry.getKey() + "= ?");
845                 queryObject.addValue(valueString);
846                 if (counter != valuesMap.size() - 1) {
847                     fieldValueString.append(",");
848                 }    
849                 counter = counter + 1;
850             }
851             String ttl = updateObj.getTtl();
852             String timestamp = updateObj.getTimestamp();
853
854             queryObject.appendQueryString("UPDATE " + keyspace + "." + tablename + " ");
855             if ((ttl != null) && (timestamp != null)) {
856                 logger.info("both there");
857                 queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
858                 queryObject.addValue(Integer.parseInt(ttl));
859                 queryObject.addValue(Long.parseLong(timestamp));
860             }
861
862             if ((ttl != null) && (timestamp == null)) {
863                 logger.info("ONLY TTL there");
864                 queryObject.appendQueryString(" USING TTL ?");
865                 queryObject.addValue(Integer.parseInt(ttl));
866             }
867
868             if ((ttl == null) && (timestamp != null)) {
869                 logger.info("ONLY timestamp there");
870                 queryObject.appendQueryString(" USING TIMESTAMP ?");
871                 queryObject.addValue(Long.parseLong(timestamp));
872             }
873             // get the row specifier
874             RowIdentifier rowId = null;
875             try {
876                 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
877                 if(rowId == null || rowId.primarKeyValue.isEmpty()) {
878                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
879                             .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build();
880                 }
881             } catch (MusicServiceException ex) {
882                 logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes
883                     .GENERALSERVICEERROR, ex);
884                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
885             }
886
887             queryObject.appendQueryString(
888                 " SET " + fieldValueString + " WHERE " + rowId.rowIdString + ";");
889
890             // get the conditional, if any
891             Condition conditionInfo;
892             if (updateObj.getConditions() == null) {
893                 conditionInfo = null;
894             } else {
895                 // to avoid parsing repeatedly, just send the select query to obtain row
896                 PreparedQueryObject selectQuery = new PreparedQueryObject();
897                 selectQuery.appendQueryString("SELECT *  FROM " + keyspace + "." + tablename + " WHERE "
898                     + rowId.rowIdString + ";");
899                 selectQuery.addValue(rowId.primarKeyValue);
900                 conditionInfo = new Condition(updateObj.getConditions(), selectQuery);
901             }
902
903             ReturnType operationResult = null;
904             long jsonParseCompletionTime = System.currentTimeMillis();
905
906             if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && updateObj.getConsistencyInfo().get("consistency") != null) {
907                 if(MusicUtil.isValidConsistency(updateObj.getConsistencyInfo().get("consistency"))) {
908                     queryObject.setConsistency(updateObj.getConsistencyInfo().get("consistency"));
909                 } else {
910                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR).setError("Invalid Consistency type").toMap()).build();
911                 }
912             }
913             queryObject.setOperation("update");
914             if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
915                 operationResult = MusicCore.eventualPut(queryObject);
916             } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
917                 String lockId = updateObj.getConsistencyInfo().get("lockId");
918                 if(lockId == null) {
919                     logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
920                             + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
921                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
922                             + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
923                 }
924                 operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
925                                 queryObject, lockId, conditionInfo);
926             } else if (consistency.equalsIgnoreCase("atomic_delete_lock")) {
927                 // this function is mainly for the benchmarks
928                 try {
929                     operationResult = MusicCore.atomicPutWithDeleteLock(keyspace, tablename,
930                         rowId.primarKeyValue, queryObject, conditionInfo);
931                 } catch (MusicLockingException e) {
932                     logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN,
933                         ErrorTypes.GENERALSERVICEERROR, e);
934                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
935                 }
936             } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
937                 try {
938                     operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
939                         queryObject, conditionInfo);
940                 } catch (MusicLockingException e) {
941                     logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e);
942                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
943                 }
944             } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {
945                 operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
946             }
947             long actualUpdateCompletionTime = System.currentTimeMillis();
948
949             long endTime = System.currentTimeMillis();
950             String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId
951                 + ":" + "|total operation time:" + (endTime - startTime)
952                 + "|json parsing time:" + (jsonParseCompletionTime - startTime)
953                 + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime)
954                 + "|";
955
956             if (operationResult != null && operationResult.getTimingInfo() != null) {
957                 String lockManagementTime = operationResult.getTimingInfo();
958                 timingString = timingString + lockManagementTime;
959             }
960             logger.info(EELFLoggerDelegate.applicationLogger, timingString);
961
962             if (operationResult==null) {
963                 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
964                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
965             }
966             if ( operationResult.getResult() == ResultType.SUCCESS ) {
967                 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
968             } else {
969                 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
970                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(operationResult.getResult()).setError(operationResult.getMessage()).toMap()).build();
971             }
972         } finally {
973             EELFLoggerDelegate.mdcRemove("keyspace");
974         }
975     }
976
977     /**
978      *
979      * @param delObj
980      * @param keyspace
981      * @param tablename
982      * @param info
983      * @return
984      * @throws MusicServiceException 
985      * @throws MusicQueryException 
986      * @throws Exception
987      */
988     @DELETE
989     @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
990     @ApiOperation(value = "Delete From table", response = String.class)
991     @Consumes(MediaType.APPLICATION_JSON)
992     @Produces(MediaType.APPLICATION_JSON)
993     public Response deleteFromTable(
994         @ApiParam(value = "Major Version",
995             required = true) @PathParam("version") String version,
996         @ApiParam(value = "Minor Version",
997             required = false) @HeaderParam(XMINORVERSION) String minorVersion,
998         @ApiParam(value = "Patch Version",
999             required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1000         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
1001         @ApiParam(value = "Application namespace",
1002             required = false, hidden = true) @HeaderParam(NS) String ns,
1003         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1004         JsonDelete delObj,
1005         @ApiParam(value = "Keyspace Name",
1006             required = true) @PathParam("keyspace") String keyspace,
1007         @ApiParam(value = "Table Name",
1008             required = true) @PathParam("tablename") String tablename,
1009         @Context UriInfo info) throws MusicQueryException, MusicServiceException {
1010         try {
1011             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1012             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1013                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1014                     .setError("one or more path parameters are not set, please check and try again")
1015                     .toMap()).build();
1016             }
1017             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1018             if(delObj == null) {
1019                 logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult(), AppMessages.MISSINGDATA  ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
1020                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
1021             }
1022             PreparedQueryObject queryObject = new PreparedQueryObject();
1023             StringBuilder columnString = new StringBuilder();
1024
1025             int counter = 0;
1026             List<String> columnList = delObj.getColumns();
1027             if (columnList != null) {
1028                 for (String column : columnList) {
1029                     columnString.append(column);
1030                     if (counter != columnList.size() - 1)
1031                         columnString.append(",");
1032                     counter = counter + 1;
1033                 }
1034             }
1035
1036             // get the row specifier
1037             RowIdentifier rowId = null;
1038             try {
1039                 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1040             } catch (MusicServiceException ex) {
1041                 logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes
1042                     .GENERALSERVICEERROR, ex);
1043                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1044             }
1045             String rowSpec = rowId.rowIdString.toString();
1046
1047             if ((columnList != null) && (!rowSpec.isEmpty())) {
1048                 queryObject.appendQueryString("DELETE " + columnString + " FROM " + keyspace + "."
1049                                 + tablename + " WHERE " + rowSpec + ";");
1050             }
1051
1052             if ((columnList == null) && (!rowSpec.isEmpty())) {
1053                 queryObject.appendQueryString("DELETE FROM " + keyspace + "." + tablename + " WHERE "
1054                                 + rowSpec + ";");
1055             }
1056
1057             if ((columnList != null) && (rowSpec.isEmpty())) {
1058                 queryObject.appendQueryString(
1059                                 "DELETE " + columnString + " FROM " + keyspace + "." + rowSpec + ";");
1060             }
1061             // get the conditional, if any
1062             Condition conditionInfo;
1063             if (delObj.getConditions() == null) {
1064                 conditionInfo = null;
1065             } else {
1066                 // to avoid parsing repeatedly, just send the select query to
1067                 // obtain row
1068                 PreparedQueryObject selectQuery = new PreparedQueryObject();
1069                 selectQuery.appendQueryString("SELECT *  FROM " + keyspace + "." + tablename + " WHERE "
1070                     + rowId.rowIdString + ";");
1071                 selectQuery.addValue(rowId.primarKeyValue);
1072                 conditionInfo = new Condition(delObj.getConditions(), selectQuery);
1073             }
1074
1075             String consistency = delObj.getConsistencyInfo().get("type");
1076
1077
1078             if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && delObj.getConsistencyInfo().get("consistency")!=null) {
1079                 if(MusicUtil.isValidConsistency(delObj.getConsistencyInfo().get("consistency"))) {
1080                     queryObject.setConsistency(delObj.getConsistencyInfo().get("consistency"));
1081                 } else {
1082                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR)
1083                         .setError("Invalid Consistency type").toMap()).build();
1084                 }
1085             }
1086             ReturnType operationResult = null;
1087             queryObject.setOperation("delete");
1088             try {
1089                 if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL))
1090                     operationResult = MusicCore.eventualPut(queryObject);
1091                 else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1092                     String lockId = delObj.getConsistencyInfo().get("lockId");
1093                     if(lockId == null) {
1094                         logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1095                             + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1096                         return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1097                             + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1098                     }
1099                     operationResult = MusicCore.criticalPut(keyspace, tablename, rowId.primarKeyValue,
1100                         queryObject, lockId, conditionInfo);
1101                 } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1102                     operationResult = MusicCore.atomicPut(keyspace, tablename, rowId.primarKeyValue,
1103                         queryObject, conditionInfo);
1104                 } else if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL_NB)) {                    
1105                     operationResult = MusicCore.eventualPut_nb(queryObject, keyspace, tablename, rowId.primarKeyValue);
1106                 }
1107             } catch (MusicLockingException e) {
1108                 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e);
1109                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1110                         .setError("Unable to perform Delete operation. Exception from music").toMap()).build();
1111             }
1112             if (operationResult==null) {
1113                 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1114                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
1115             }
1116             if (operationResult.getResult().equals(ResultType.SUCCESS)) {
1117                 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
1118             } else {
1119                 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
1120                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap()).build();
1121             }
1122         } finally {
1123             EELFLoggerDelegate.mdcRemove("keyspace");
1124         }
1125     }
1126
1127     /**
1128      *
1129      * @param tabObj
1130      * @param keyspace
1131      * @param tablename
1132      * @throws Exception
1133      */
1134     @DELETE
1135     @Path("/{keyspace: .*}/tables/{tablename: .*}")
1136     @ApiOperation(value = "Drop Table", response = String.class)
1137     @Produces(MediaType.APPLICATION_JSON)
1138     public Response dropTable(
1139         @ApiParam(value = "Major Version",
1140             required = true) @PathParam("version") String version,
1141         @ApiParam(value = "Minor Version",
1142             required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1143         @ApiParam(value = "Patch Version",
1144             required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1145         @ApiParam(value = "AID", required = false,hidden = true) @HeaderParam("aid") String aid,
1146         @ApiParam(value = "Application namespace",
1147             required = false, hidden = true) @HeaderParam(NS) String ns,
1148         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1149         @ApiParam(value = "Keyspace Name",
1150             required = true) @PathParam("keyspace") String keyspace,
1151         @ApiParam(value = "Table Name",
1152             required = true) @PathParam("tablename") String tablename) throws Exception {
1153         try {
1154             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1155             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1156                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1157                     .setError("one or more path parameters are not set, please check and try again")
1158                     .toMap()).build();
1159             }
1160             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1161             String consistency = "eventual";// for now this needs only eventual consistency
1162             PreparedQueryObject query = new PreparedQueryObject();
1163             query.appendQueryString("DROP TABLE  " + keyspace + "." + tablename + ";");
1164             try {
1165                 return response.status(Status.OK).entity(new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency)).toMap()).build();
1166             } catch (MusicServiceException ex) {
1167                 logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.MISSINGINFO  ,ErrorSeverity.WARN, ErrorTypes
1168                     .GENERALSERVICEERROR);
1169                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1170             }
1171         } finally {
1172             EELFLoggerDelegate.mdcRemove("keyspace");
1173         }
1174     }
1175
1176     /**
1177      *
1178      * @param selObj
1179      * @param keyspace
1180      * @param tablename
1181      * @param info
1182      * @return
1183      */
1184     @PUT
1185     @Path("/{keyspace: .*}/tables/{tablename: .*}/rows/criticalget")
1186     @ApiOperation(value = "Select Critical", response = Map.class)
1187     @Consumes(MediaType.APPLICATION_JSON)
1188     @Produces(MediaType.APPLICATION_JSON)
1189     public Response selectCritical(
1190         @ApiParam(value = "Major Version",
1191             required = true) @PathParam("version") String version,
1192         @ApiParam(value = "Minor Version",
1193             required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1194         @ApiParam(value = "Patch Version",
1195             required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1196         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
1197         @ApiParam(value = "Application namespace",
1198             required = false, hidden = true) @HeaderParam(NS) String ns,
1199         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1200         JsonInsert selObj,
1201         @ApiParam(value = "Keyspace Name",
1202             required = true) @PathParam("keyspace") String keyspace,
1203         @ApiParam(value = "Table Name",
1204             required = true) @PathParam("tablename") String tablename,
1205         @Context UriInfo info) throws Exception {
1206         try {
1207             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1208             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1209                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1210                     .setError("one or more path parameters are not set, please check and try again")
1211                     .toMap()).build();
1212             }
1213             if(selObj == null) {
1214                 logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult(), AppMessages.MISSINGDATA  ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
1215                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
1216             }
1217
1218             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
1219             String lockId = selObj.getConsistencyInfo().get("lockId");
1220             PreparedQueryObject queryObject = new PreparedQueryObject();
1221             RowIdentifier rowId = null;
1222             try {
1223                 rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
1224             } catch (MusicServiceException ex) {
1225                 logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes
1226                     .GENERALSERVICEERROR, ex);
1227                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1228             }
1229             queryObject.appendQueryString(
1230                 "SELECT *  FROM " + keyspace + "." + tablename + " WHERE " + rowId.rowIdString + ";");
1231
1232             ResultSet results = null;
1233
1234             String consistency = selObj.getConsistencyInfo().get("type");
1235             try {
1236             if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
1237                 if(lockId == null) {
1238                     logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
1239                         + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
1240                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
1241                         + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
1242                 }
1243                 results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,lockId);
1244             } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
1245                 results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject);
1246             }
1247             }catch(Exception ex) {
1248                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1249             }
1250             
1251             if(results!=null && results.getAvailableWithoutFetching() >0) {
1252                 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1253             }
1254             return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").toMap()).build();
1255         } finally {
1256             EELFLoggerDelegate.mdcRemove("keyspace");
1257         }
1258     }
1259
1260     /**
1261      *
1262      * @param keyspace
1263      * @param tablename
1264      * @param info
1265      * @return
1266      * @throws Exception
1267      */
1268     @GET
1269     @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
1270     @ApiOperation(value = "Select All or Select Specific", response = Map.class)
1271     @Produces(MediaType.APPLICATION_JSON)
1272     public Response select(
1273         @ApiParam(value = "Major Version",
1274             required = true) @PathParam("version") String version,
1275         @ApiParam(value = "Minor Version",
1276             required = false) @HeaderParam(XMINORVERSION) String minorVersion,
1277         @ApiParam(value = "Patch Version",
1278             required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
1279         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
1280         @ApiParam(value = "Application namespace",
1281             required = false,hidden = true) @HeaderParam(NS) String ns,
1282         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
1283         @ApiParam(value = "Keyspace Name",
1284             required = true) @PathParam("keyspace") String keyspace,
1285         @ApiParam(value = "Table Name",
1286             required = true) @PathParam("tablename") String tablename,
1287         @Context UriInfo info) throws Exception {
1288         try { 
1289             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
1290             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
1291                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
1292                     .setError("one or more path parameters are not set, please check and try again")
1293                     .toMap()).build();
1294             }
1295             EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspace + " ) ");
1296             PreparedQueryObject queryObject = new PreparedQueryObject();
1297
1298             if (info.getQueryParameters().isEmpty()) { // select all
1299                 queryObject.appendQueryString("SELECT *  FROM " + keyspace + "." + tablename + ";");
1300             } else {
1301                 int limit = -1; // do not limit the number of results
1302                 try {
1303                     queryObject = selectSpecificQuery(keyspace, tablename, info, limit);
1304                 } catch (MusicServiceException ex) {
1305                     logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN,
1306                         ErrorTypes.GENERALSERVICEERROR, ex);
1307                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1308                 }
1309             }
1310             try {
1311                 ResultSet results = MusicCore.get(queryObject);
1312                 if(results.getAvailableWithoutFetching() >0) {
1313                     return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
1314                 }
1315                 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).setError("No data found").toMap()).build();
1316             } catch (MusicServiceException ex) {
1317                 logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR  ,ErrorSeverity.ERROR,
1318                     ErrorTypes.MUSICSERVICEERROR, ex);
1319                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
1320             }
1321         } finally {
1322             EELFLoggerDelegate.mdcRemove("keyspace");
1323         }
1324     }
1325
1326     /**
1327      *
1328      * @param keyspace
1329      * @param tablename
1330      * @param info
1331      * @param limit
1332      * @return
1333      * @throws MusicServiceException
1334      */
1335     public PreparedQueryObject selectSpecificQuery(String keyspace,
1336         String tablename, UriInfo info, int limit)
1337         throws MusicServiceException {
1338         PreparedQueryObject queryObject = new PreparedQueryObject();
1339         StringBuilder rowIdString = getRowIdentifier(keyspace, 
1340             tablename,info.getQueryParameters(),queryObject).rowIdString;
1341         queryObject.appendQueryString(
1342             "SELECT *  FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
1343         if (limit != -1) {
1344             queryObject.appendQueryString(" LIMIT " + limit);
1345         }
1346         queryObject.appendQueryString(";");
1347         return queryObject;
1348     }
1349
1350     /**
1351      *
1352      * @param keyspace
1353      * @param tablename
1354      * @param rowParams
1355      * @param queryObject
1356      * @return
1357      * @throws MusicServiceException
1358      */
1359     private RowIdentifier getRowIdentifier(String keyspace, String tablename,
1360         MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
1361         throws MusicServiceException {
1362         StringBuilder rowSpec = new StringBuilder();
1363         int counter = 0;
1364         TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
1365         if (tableInfo == null) {
1366             logger.error(EELFLoggerDelegate.errorLogger,
1367                 "Table information not found. Please check input for table name= "
1368                 + keyspace + "." + tablename);
1369             throw new MusicServiceException(
1370                 "Table information not found. Please check input for table name= "
1371                 + keyspace + "." + tablename);
1372         }
1373         StringBuilder primaryKey = new StringBuilder();
1374         for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
1375             String keyName = entry.getKey();
1376             List<String> valueList = entry.getValue();
1377             String indValue = valueList.get(0);
1378             DataType colType = null;
1379             Object formattedValue = null;
1380             try {
1381                 colType = tableInfo.getColumn(entry.getKey()).getType();
1382                 formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
1383             } catch (Exception e) {
1384                 logger.error(EELFLoggerDelegate.errorLogger,e);
1385             }
1386             if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) {
1387                 primaryKey.append(indValue);
1388             }
1389             rowSpec.append(keyName + "= ?");
1390             queryObject.addValue(formattedValue);
1391             if (counter != rowParams.size() - 1) {
1392                 rowSpec.append(" AND ");
1393             }
1394             counter = counter + 1;
1395         }
1396         return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);
1397     }
1398 }