MUSIC-ORM-Implemetation
[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  *  Modifications Copyright (C) 2019 IBM 
10  * ===================================================================
11  *  Licensed under the Apache License, Version 2.0 (the "License");
12  *  you may not use this file except in compliance with the License.
13  *  You may obtain a copy of the License at
14  *
15  *     http://www.apache.org/licenses/LICENSE-2.0
16  *
17  *  Unless required by applicable law or agreed to in writing, software
18  *  distributed under the License is distributed on an "AS IS" BASIS,
19  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  *  See the License for the specific language governing permissions and
21  *  limitations under the License.
22  *
23  * ============LICENSE_END=============================================
24  * ====================================================================
25  */
26
27 package org.onap.music.rest;
28
29 import java.util.List;
30 import java.util.Map;
31 import java.util.UUID;
32
33 import javax.ws.rs.Consumes;
34 import javax.ws.rs.DELETE;
35 import javax.ws.rs.GET;
36 import javax.ws.rs.HeaderParam;
37 import javax.ws.rs.POST;
38 import javax.ws.rs.PUT;
39 import javax.ws.rs.Path;
40 import javax.ws.rs.PathParam;
41 import javax.ws.rs.Produces;
42 import javax.ws.rs.core.Context;
43 import javax.ws.rs.core.MediaType;
44 import javax.ws.rs.core.MultivaluedMap;
45 import javax.ws.rs.core.Response;
46 import javax.ws.rs.core.Response.ResponseBuilder;
47 import javax.ws.rs.core.Response.Status;
48 import javax.ws.rs.core.UriInfo;
49
50 import org.onap.music.datastore.MusicDataStoreHandle;
51 import org.onap.music.datastore.PreparedQueryObject;
52 import org.onap.music.datastore.jsonobjects.JsonDelete;
53 import org.onap.music.datastore.jsonobjects.JsonIndex;
54 import org.onap.music.datastore.jsonobjects.JsonInsert;
55 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
56 import org.onap.music.datastore.jsonobjects.JsonSelect;
57 import org.onap.music.datastore.jsonobjects.JsonTable;
58 import org.onap.music.datastore.jsonobjects.JsonUpdate;
59 import org.onap.music.eelf.logging.EELFLoggerDelegate;
60 import org.onap.music.eelf.logging.format.AppMessages;
61 import org.onap.music.eelf.logging.format.ErrorSeverity;
62 import org.onap.music.eelf.logging.format.ErrorTypes;
63 import org.onap.music.exceptions.MusicLockingException;
64 import org.onap.music.exceptions.MusicQueryException;
65 import org.onap.music.exceptions.MusicServiceException;
66 import org.onap.music.main.MusicCore;
67 import org.onap.music.main.MusicUtil;
68 import org.onap.music.main.ResultType;
69 import org.onap.music.main.ReturnType;
70 import org.onap.music.response.jsonobjects.JsonResponse;
71
72 import com.datastax.driver.core.DataType;
73 import com.datastax.driver.core.ResultSet;
74 import com.datastax.driver.core.TableMetadata;
75
76 import io.swagger.annotations.Api;
77 import io.swagger.annotations.ApiOperation;
78 import io.swagger.annotations.ApiParam;
79 import io.swagger.annotations.ApiResponse;
80 import io.swagger.annotations.ApiResponses;
81 import io.swagger.annotations.Example;
82 import io.swagger.annotations.ExampleProperty;
83
84 /* Version 2 Class */
85 //@Path("/v{version: [0-9]+}/keyspaces")
86 @Path("/v2/keyspaces")
87 @Api(value = "Data Api")
88 public class RestMusicDataAPI {
89     /*
90      * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR
91      * version back from the client to the server, and from the server back to the client - This
92      * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR
93      * version (if not specified by the client on the request) - Contains a single position value
94      * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on
95      * request; however, this header should be provided if the client needs to take advantage of
96      * MINOR incremented version functionality - Is mandatory for the server on response
97      *
98      *** X-patchVersion *** - Used only to communicate a PATCH version in a response for
99      * troubleshooting purposes only, and will not be provided by the client on request - This will
100      * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version
101      * of the MAJOR (if not specified by the client on the request) - Contains a single position
102      * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the
103      * server on response  (CURRENTLY NOT USED)
104      *
105      *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the
106      * server on response, and shall include the entire version of the API (e.g. if the full version
107      * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are
108      * not using the latest version of the API (CURRENTLY NOT USED)
109      *
110      */
111
112     private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class);
113     private static final String XMINORVERSION = "X-minorVersion";
114     private static final String XPATCHVERSION = "X-patchVersion";
115     private static final String NS = "ns";
116     private static final String VERSION = "v2";
117     private static final String PARAMETER_ERROR = "Missing Row Identifier. Please provide the parameter of key=value for the row being selected.";
118
119
120     private class RowIdentifier {
121         public String primarKeyValue;
122         public StringBuilder rowIdString;
123         @SuppressWarnings("unused")
124         public PreparedQueryObject queryObject; // the string with all the row
125                                                 // identifiers separated by AND
126
127         public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
128                         PreparedQueryObject queryObject) {
129             this.primarKeyValue = primaryKeyValue;
130             this.rowIdString = rowIdString;
131             this.queryObject = queryObject;
132         }
133     }
134
135
136     /**
137      * Create Keyspace REST
138      *
139      * @param kspObject
140      * @param keyspaceName
141      * @return
142      * @throws Exception
143      */
144     @POST
145     @Path("/{name}")
146     @ApiOperation(value = "Create Keyspace", response = String.class,
147         notes = "This API will not work if MUSIC properties has keyspace.active=false ")
148     @Consumes(MediaType.APPLICATION_JSON)
149     @Produces(MediaType.APPLICATION_JSON)
150     @ApiResponses(value={
151         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
152             @ExampleProperty(mediaType="application/json",value = 
153                 "{\"message\" : \"Keysapce <keyspace> Created\","
154                 + "\"status\" : \"SUCCESS\"}")
155         })),
156         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
157             @ExampleProperty(mediaType="application/json",value = 
158                 "{\"error\" : \"<errorMessage>\","
159                 + "\"status\" : \"FAILURE\"}") 
160         }))
161     })  
162     public Response createKeySpace(
163         @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
164         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
165         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
166         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
167         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
168         @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
169         JsonKeySpace kspObject,
170         @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) {
171         try {
172             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
173             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
174             logger.info(EELFLoggerDelegate.applicationLogger,"In Create Keyspace " + keyspaceName);
175             if (MusicUtil.isKeyspaceActive() ) {
176                 logger.info(EELFLoggerDelegate.applicationLogger,"Creating Keyspace " + keyspaceName);
177                 
178                 if(kspObject == null || kspObject.getReplicationInfo() == null) {
179                     response.status(Status.BAD_REQUEST);
180                     return response.entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
181                 }
182                 ResultType result = ResultType.FAILURE;
183                 try {
184                     kspObject.setKeyspaceName(keyspaceName);
185                     result = MusicCore.createKeyspace(kspObject, MusicUtil.EVENTUAL);
186                     logger.info(EELFLoggerDelegate.applicationLogger, "result = " + result);
187                 } catch ( MusicQueryException ex) {
188                     logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.QUERYERROR 
189                     ,ErrorSeverity.WARN, ErrorTypes.QUERYERROR);
190                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
191                 } catch ( MusicServiceException ex) {
192                     logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity
193                         .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
194                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
195                 }
196         
197                 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Created").toMap()).build();
198             } else {
199                 String vError = "Keyspace Creation has been turned off. Contact DBA to create the keyspace or set keyspace.active to true.";
200                 logger.info(EELFLoggerDelegate.applicationLogger,vError);
201                 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
202                 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
203             }
204         } finally {
205             EELFLoggerDelegate.mdcRemove("keyspace");
206         }
207         
208     }
209
210     /**
211      *
212      * @param kspObject
213      * @param keyspaceName
214      * @return
215      * @throws Exception
216      */
217     @DELETE
218     @Path("/{name}")
219     @ApiOperation(value = "Delete Keyspace", response = String.class,
220         notes = "This API will not work if MUSIC properties has keyspace.active=false ")
221     @Produces(MediaType.APPLICATION_JSON)
222     @ApiResponses(value={
223         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
224             @ExampleProperty(mediaType="application/json",value = 
225                 "{\"message\" : \"Keysapce <keyspace> Deleted\","
226                 + "\"status\" : \"SUCCESS\"}")
227         })),
228         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
229             @ExampleProperty(mediaType="application/json",value = 
230                 "{\"error\" : \"<errorMessage>\","
231                 + "\"status\" : \"FAILURE\"}") 
232         }))
233     })  
234     public Response dropKeySpace(
235         @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
236         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
237         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
238         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
239         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
240         @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
241         @ApiParam(value = "Keyspace Name",required = true) @PathParam("name") String keyspaceName) throws Exception {
242         try {
243             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
244             EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) ");
245             logger.info(EELFLoggerDelegate.applicationLogger,"In Drop Keyspace " + keyspaceName);
246             if (MusicUtil.isKeyspaceActive()) {
247                 String consistency = MusicUtil.EVENTUAL;// for now this needs only
248                 String droperror = "Error Deleteing Keyspace " + keyspaceName;
249                 JsonKeySpace kspObject = new JsonKeySpace();
250                 kspObject.setKeyspaceName(keyspaceName);
251                 try{
252                     ResultType result = MusicCore.dropKeyspace(kspObject, consistency);
253                     if ( result.equals(ResultType.FAILURE) ) {
254                         return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError(droperror).toMap()).build();
255                     }
256                 } catch ( MusicQueryException ex) {
257                     logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.QUERYERROR 
258                     ,ErrorSeverity.WARN, ErrorTypes.QUERYERROR);
259                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(droperror + " " + ex.getMessage()).toMap()).build();
260                 } catch ( MusicServiceException ex) {
261                     logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR
262                         ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR, ex);
263                     return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(droperror + " " + ex.getMessage()).toMap()).build();
264                 }
265                 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("Keyspace " + keyspaceName + " Deleted").toMap()).build();
266             } else {
267                 String vError = "Keyspace deletion has been turned off. Contact DBA to delete the keyspace or set keyspace.active to true.";
268                 logger.info(EELFLoggerDelegate.applicationLogger,vError);
269                 logger.error(EELFLoggerDelegate.errorLogger,vError, AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
270                 return response.status(Response.Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(vError).toMap()).build();
271             }
272         } finally {
273             EELFLoggerDelegate.mdcRemove("keyspace");
274         }
275     }
276
277     /**
278      *
279      * @param tableObj
280      * @param version
281      * @param keyspace
282      * @param tablename
283      * @param headers
284      * @return
285      * @throws Exception -
286      */
287     @POST
288     @Path("/{keyspace: .*}/tables/{tablename: .*}")
289     @ApiOperation(value = "Create Table", response = String.class,
290         notes = "Create a table with the required json in the body.")
291     @Consumes(MediaType.APPLICATION_JSON)
292     @Produces(MediaType.APPLICATION_JSON)
293     @ApiResponses(value={
294         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
295             @ExampleProperty(mediaType="application/json",value = 
296                 "{\"message\" : \"Tablename <tablename> Created under keyspace <keyspace>\","
297                 + "\"status\" : \"SUCCESS\"}")
298         })),
299         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
300             @ExampleProperty(mediaType="application/json",value = 
301                 "{\"error\" : \"<errorMessage>\","
302                 + "\"status\" : \"FAILURE\"}") 
303         }))
304     })  
305     public Response createTable(
306         @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
307         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
308         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
309         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
310         @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
311         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
312         JsonTable tableObj,
313         @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
314         @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename) throws Exception {
315         try {
316             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
317             if ( null == tableObj ) {
318                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
319                         .setError(ResultType.BODYMISSING.getResult()).toMap()).build();
320             }
321             if(keyspace == null || keyspace.isEmpty() || tablename == null || tablename.isEmpty()){
322                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
323                         .setError("One or more path parameters are not set, please check and try again."
324                             + "Parameter values: keyspace='" + keyspace + "' tablename='" + tablename + "'")
325                             .toMap()).build();
326             }
327             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
328             String consistency = MusicUtil.EVENTUAL;
329             // for now this needs only eventual consistency
330             ResultType result = ResultType.FAILURE;
331             try {
332                 tableObj.setKeyspaceName(keyspace);
333                 tableObj.setTableName(tablename);
334                 result = MusicCore.createTable(tableObj, consistency);
335             } catch (MusicQueryException ex) {
336                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage()  ,ErrorSeverity
337                         .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
338                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
339             } catch (MusicServiceException ex) {
340                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity.CRITICAL, ErrorTypes.MUSICSERVICEERROR);
341                 response.status(Status.BAD_REQUEST);
342                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
343             }
344             if ( result.equals(ResultType.FAILURE) ) {
345                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Error Creating Table " + tablename).toMap()).build();
346             }
347             return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setMessage("TableName " + tablename.trim() + " Created under keyspace " + keyspace.trim()).toMap()).build();
348         } finally {
349             EELFLoggerDelegate.mdcRemove("keyspace");
350         }
351     }
352
353     /**
354      *
355      * @param keyspace
356      * @param tablename
357      * @param fieldName
358      * @param info
359      * @throws Exception
360      */
361     @POST
362     @Path("/{keyspace: .*}/tables/{tablename: .*}/index/{field: .*}")
363     @ApiOperation(value = "Create Index", response = String.class,
364         notes = "An index provides a means to access data using attributes "
365         + "other than the partition key. The benefit is fast, efficient lookup "
366         + "of data matching a given condition.")
367     @Produces(MediaType.APPLICATION_JSON)
368     @ApiResponses(value={
369         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
370             @ExampleProperty(mediaType="application/json",value = 
371                 "{\"message\" : \"Index Created on <keyspace>.<table>.<field>\","
372                 + "\"status\" : \"SUCCESS\"}")
373         })),
374         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
375             @ExampleProperty(mediaType="application/json",value = 
376                 "{\"error\" : \"<errorMessage>\","
377                 + "\"status\" : \"FAILURE\"}") 
378         })),
379         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
380             @ExampleProperty(mediaType="application/json",value = 
381                 "{\"error\" : \"Unknown Error in create index.\","
382                 + "\"status\" : \"FAILURE\"}") 
383         }))
384     })  
385     public Response createIndex(
386         @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
387         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
388         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
389         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
390         @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
391         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
392         @ApiParam(value = "Keyspace Name",required = true) @PathParam("keyspace") String keyspace,
393         @ApiParam(value = "Table Name",required = true) @PathParam("tablename") String tablename,
394         @ApiParam(value = "Field Name",required = true) @PathParam("field") String fieldName,
395         @Context UriInfo info) throws Exception {
396         try {
397             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
398             if ((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty()) || (fieldName == null || fieldName.isEmpty())){
399                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
400                     .setError("one or more path parameters are not set, please check and try again")
401                     .toMap()).build();
402             }
403             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
404             MultivaluedMap<String, String> rowParams = info.getQueryParameters();
405             String indexName = "";
406             if (rowParams.getFirst("index_name") != null)
407                 indexName = rowParams.getFirst("index_name");
408             
409             JsonIndex jsonIndexObject = new JsonIndex(indexName, keyspace, tablename, fieldName);
410             
411             ResultType result = ResultType.FAILURE;
412             try {
413                 result = MusicCore.createIndex(jsonIndexObject, MusicUtil.EVENTUAL);
414             } catch (MusicServiceException ex) {
415                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity
416                 .CRITICAL, ErrorTypes.GENERALSERVICEERROR, ex);
417                 response.status(Status.BAD_REQUEST);
418                 return response.entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
419             }
420             if ( result.equals(ResultType.SUCCESS) ) {
421                 return response.status(Status.OK).entity(new JsonResponse(result).setMessage("Index Created on " + keyspace+"."+tablename+"."+fieldName).toMap()).build();
422             } else {
423                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result).setError("Unknown Error in create index.").toMap()).build();
424             }
425         } finally {
426             EELFLoggerDelegate.mdcRemove("keyspace");
427         }
428     }
429
430     /**
431      *
432      * @param insObj
433      * @param keyspace
434      * @param tablename
435      * @return
436      * @throws Exception
437      */
438     @POST
439     @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
440     @ApiOperation(value = "Insert Into Table", response = String.class,
441         notes = "Insert into table with data in json body.")
442     @Consumes(MediaType.APPLICATION_JSON)
443     @Produces(MediaType.APPLICATION_JSON)
444     @ApiResponses(value={
445         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
446             @ExampleProperty(mediaType="application/json",value = 
447                 "{\"message\" : \"Insert Successful\","
448                 + "\"status\" : \"SUCCESS\"}")
449         })),
450         @ApiResponse(code=400, message = "Failure - Generic",examples = @Example( value =  {
451             @ExampleProperty(mediaType="application/json",value = 
452                 "{\"error\" : \"<errorMessage>\","
453                 + "\"status\" : \"FAILURE\"}") 
454         }))
455     })  
456     public Response insertIntoTable(
457         @ApiParam(value = "Major Version",required = true) @PathParam("version") String version,
458         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
459         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
460         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
461         @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam(NS) String ns,
462         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
463         JsonInsert insObj,
464         @ApiParam(value = "Keyspace Name",
465             required = true) @PathParam("keyspace") String keyspace,
466         @ApiParam(value = "Table Name",
467             required = true) @PathParam("tablename") String tablename) {
468         try {
469             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
470             if ( null == insObj ) {
471                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
472                         .setError(ResultType.BODYMISSING.getResult()).toMap()).build();
473             }
474             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
475             return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
476                 .setError("one or more path parameters are not set, please check and try again")
477                 .toMap()).build();
478             }
479             EELFLoggerDelegate.mdcPut("keyspace","(" + keyspace + ")");
480             ReturnType result = null;
481             String consistency = insObj.getConsistencyInfo().get("type");
482             try {
483                 insObj.setKeyspaceName(keyspace);
484                 insObj.setTableName(tablename);
485                 if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
486                     String lockId = insObj.getConsistencyInfo().get("lockId");
487                     if(lockId == null) {
488                         logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
489                                 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
490                         return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
491                                 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
492                     }
493                 }
494                 result = MusicCore.insertIntoTable(insObj);
495             }catch (MusicQueryException ex) {
496                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage()  ,ErrorSeverity
497                         .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
498                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
499             }catch (Exception ex) {
500                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity
501                     .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
502                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
503             }
504             if (result==null) {
505                 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.MUSICSERVICEERROR);
506                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
507             }else if(result.getResult() == ResultType.FAILURE) {
508                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(result.getResult()).setError(result.getMessage()).toMap()).build();
509             }
510             return response.status(Status.OK).entity(new JsonResponse(result.getResult()).setMessage("Insert Successful").toMap()).build();
511         } finally {
512             EELFLoggerDelegate.mdcRemove("keyspace");
513         }
514     }
515
516     /**
517      *
518      * @param insObj
519      * @param keyspace
520      * @param tablename
521      * @param info
522      * @return
523      * @throws MusicServiceException 
524      * @throws MusicQueryException 
525      * @throws Exception
526      */
527     @PUT
528     @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
529     @ApiOperation(value = "Update Table", response = String.class,
530         notes = "Update the table with the data in the JSON body.")
531     @Consumes(MediaType.APPLICATION_JSON)
532     @Produces(MediaType.APPLICATION_JSON)
533     public Response updateTable(
534         @ApiParam(value = "Major Version",
535             required = true) @PathParam("version") String version,
536         @ApiParam(value = "Minor Version",
537             required = false) @HeaderParam(XMINORVERSION) String minorVersion,
538         @ApiParam(value = "Patch Version",
539             required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
540         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
541         @ApiParam(value = "Application namespace",
542             required = false, hidden = true) @HeaderParam(NS) String ns,
543         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
544         JsonUpdate updateObj,
545         @ApiParam(value = "Keyspace Name",
546             required = true) @PathParam("keyspace") String keyspace,
547         @ApiParam(value = "Table Name",
548             required = true) @PathParam("tablename") String tablename,
549         @Context UriInfo info) throws MusicQueryException, MusicServiceException {
550         try {
551             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
552             if ( null == updateObj ) {
553                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
554                         .setError(ResultType.BODYMISSING.getResult()).toMap()).build();
555             }
556             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
557                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
558                     .setError("one or more path parameters are not set, please check and try again")
559                     .toMap()).build();
560             }
561             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
562             long startTime = System.currentTimeMillis();
563             String operationId = UUID.randomUUID().toString();  // just for infoging
564                                                                 // purposes.
565             String consistency = updateObj.getConsistencyInfo().get("type");
566             ReturnType operationResult = null;
567             logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency
568                 + " update-" + operationId + "-------------------------");
569             
570             updateObj.setKeyspaceName(keyspace);
571             updateObj.setTableName(tablename);
572             
573             try {
574                 if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
575                     String lockId = updateObj.getConsistencyInfo().get("lockId");
576                     if(lockId == null) {
577                         logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
578                                 + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
579                         return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
580                                 + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
581                     }
582                 }
583                 operationResult = MusicCore.updateTable(updateObj,info.getQueryParameters());
584             }catch (MusicLockingException e) {
585                  logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN,
586                             ErrorTypes.GENERALSERVICEERROR, e);
587                         return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
588             }catch (MusicQueryException ex) {
589                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage()  ,ErrorSeverity
590                         .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
591                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
592             }catch (Exception ex) {
593                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity
594                         .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
595                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
596             }
597             long actualUpdateCompletionTime = System.currentTimeMillis();
598
599             long endTime = System.currentTimeMillis();
600             long jsonParseCompletionTime = System.currentTimeMillis();
601             String timingString = "Time taken in ms for Music " + consistency + " update-" + operationId
602                 + ":" + "|total operation time:" + (endTime - startTime)
603                 + "|json parsing time:" + (jsonParseCompletionTime - startTime)
604                 + "|update time:" + (actualUpdateCompletionTime - jsonParseCompletionTime)
605                 + "|";
606
607             if (operationResult != null && operationResult.getTimingInfo() != null) {
608                 String lockManagementTime = operationResult.getTimingInfo();
609                 timingString = timingString + lockManagementTime;
610             }
611             logger.info(EELFLoggerDelegate.applicationLogger, timingString);
612
613             if (operationResult==null) {
614                 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
615                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
616             }
617             if ( operationResult.getResult() == ResultType.SUCCESS ) {
618                 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
619             } else {
620                 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
621                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(operationResult.getResult()).setError(operationResult.getMessage()).toMap()).build();
622             }
623         } finally {
624             EELFLoggerDelegate.mdcRemove("keyspace");
625         }
626     }
627
628     /**
629      *
630      * @param delObj
631      * @param keyspace
632      * @param tablename
633      * @param info
634      * @return
635      * @throws MusicServiceException 
636      * @throws MusicQueryException 
637      * @throws Exception
638      */
639     @DELETE
640     @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
641     @ApiOperation(value = "Delete From table", response = String.class,
642         notes = "Delete from a table, the row or parts of a row. Based on JSON body.")
643     @Consumes(MediaType.APPLICATION_JSON)
644     @Produces(MediaType.APPLICATION_JSON)
645     public Response deleteFromTable(
646         @ApiParam(value = "Major Version",
647             required = true) @PathParam("version") String version,
648         @ApiParam(value = "Minor Version",
649             required = false) @HeaderParam(XMINORVERSION) String minorVersion,
650         @ApiParam(value = "Patch Version",
651             required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
652         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
653         @ApiParam(value = "Application namespace",
654             required = false, hidden = true) @HeaderParam(NS) String ns,
655         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
656         JsonDelete delObj,
657         @ApiParam(value = "Keyspace Name",
658             required = true) @PathParam("keyspace") String keyspace,
659         @ApiParam(value = "Table Name",
660             required = true) @PathParam("tablename") String tablename,
661         @Context UriInfo info) throws MusicQueryException, MusicServiceException {
662         try {
663             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
664             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
665                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
666                     .setError("one or more path parameters are not set, please check and try again")
667                     .toMap()).build();
668             }
669             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
670             if(delObj == null) {
671                 logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult(), AppMessages.MISSINGDATA  ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
672                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult()).toMap()).build();
673             }
674             ReturnType operationResult = null;
675             String consistency = delObj.getConsistencyInfo().get("type");
676             delObj.setKeyspaceName(keyspace);
677             delObj.setTableName(tablename);
678             try {
679                 if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
680                     String lockId = delObj.getConsistencyInfo().get("lockId");
681                     if(lockId == null) {
682                         logger.error(EELFLoggerDelegate.errorLogger,"LockId cannot be null. Create lock reference or"
683                             + " use ATOMIC instead of CRITICAL", ErrorSeverity.FATAL, ErrorTypes.MUSICSERVICEERROR);
684                         return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("LockId cannot be null. Create lock "
685                             + "and acquire lock or use ATOMIC instead of CRITICAL").toMap()).build();
686                     }
687                 }
688                 
689                 operationResult = MusicCore.deleteFromTable(delObj,info.getQueryParameters());
690             } catch (MusicQueryException ex) {
691                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage()  ,ErrorSeverity
692                         .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
693                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
694                 
695             } catch (MusicLockingException e) {
696                 logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR, e);
697                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
698                         .setError("Unable to perform Delete operation. Exception from music").toMap()).build();
699             }
700             if (operationResult==null) {
701                 logger.error(EELFLoggerDelegate.errorLogger,"Null result - Please Contact admin", AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
702                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Null result - Please Contact admin").toMap()).build();
703             }
704             if (operationResult.getResult().equals(ResultType.SUCCESS)) {
705                 return response.status(Status.OK).entity(new JsonResponse(operationResult.getResult()).setMessage(operationResult.getMessage()).toMap()).build();
706             } else {
707                 logger.error(EELFLoggerDelegate.errorLogger,operationResult.getMessage(), AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR);
708                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(operationResult.getMessage()).toMap()).build();
709             }
710         } finally {
711             EELFLoggerDelegate.mdcRemove("keyspace");
712         }
713     }
714
715     /**
716      *
717      * @param tabObj
718      * @param keyspace
719      * @param tablename
720      * @throws Exception
721      */
722     @DELETE
723     @Path("/{keyspace: .*}/tables/{tablename: .*}")
724     @ApiOperation(value = "Drop Table", response = String.class)
725     @Produces(MediaType.APPLICATION_JSON)
726     @ApiResponses(value={
727         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
728             @ExampleProperty(mediaType="application/json",value = 
729                 "{\"status\" : \"SUCCESS\"}")
730         })),
731         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
732             @ExampleProperty(mediaType="application/json",value = 
733                 "{\"error\" : \"<errorMessage>\","
734                 + "\"status\" : \"FAILURE\"}") 
735         }))
736     })
737     public Response dropTable(
738         @ApiParam(value = "Major Version",
739             required = true) @PathParam("version") String version,
740         @ApiParam(value = "Minor Version",
741             required = false) @HeaderParam(XMINORVERSION) String minorVersion,
742         @ApiParam(value = "Patch Version",
743             required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
744         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
745         @ApiParam(value = "Application namespace",
746             required = false, hidden = true) @HeaderParam(NS) String ns,
747         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
748         @ApiParam(value = "Keyspace Name",
749             required = true) @PathParam("keyspace") String keyspace,
750         @ApiParam(value = "Table Name",
751             required = true) @PathParam("tablename") String tablename) throws Exception {
752         try {
753             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
754             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
755                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
756                     .setError("one or more path parameters are not set, please check and try again")
757                     .toMap()).build();
758             }
759             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspace+" ) ");
760             JsonTable jsonTable = new JsonTable();
761             jsonTable.setKeyspaceName(keyspace);
762             jsonTable.setTableName(tablename);
763             try {
764                 return response.status(Status.OK).entity(new JsonResponse(MusicCore.dropTable(jsonTable, MusicUtil.EVENTUAL)).toMap()).build();
765             } catch (MusicQueryException ex) {
766                 logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.QUERYERROR,ErrorSeverity.WARN
767                     , ErrorTypes.QUERYERROR);
768                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
769             } catch (MusicServiceException ex) {
770                 logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(), AppMessages.MISSINGINFO  ,ErrorSeverity.WARN
771                 , ErrorTypes.GENERALSERVICEERROR,ex);
772                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
773             }
774         } finally {
775             EELFLoggerDelegate.mdcRemove("keyspace");
776         }
777     }
778
779     /**
780      *
781      * @param selObj
782      * @param keyspace
783      * @param tablename
784      * @param info
785      * @return
786      */
787     @PUT
788     @Path("/{keyspace: .*}/tables/{tablename: .*}/rows/criticalget")
789     @ApiOperation(value = "** Depreciated ** - Select Critical", response = Map.class,
790         notes = "This API is depreciated in favor of the regular select api.\n"
791         + "Avaliable to use with the select api by providing a minorVersion of 1 "
792         + "and patchVersion of 0.\n"
793         + "Critical Get requires parameter rowId=value and consistency in order to work.\n"
794         + "It will fail if either are missing.")
795     @Consumes(MediaType.APPLICATION_JSON)
796     @Produces(MediaType.APPLICATION_JSON)
797     @ApiResponses(value={
798         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
799             @ExampleProperty(mediaType="application/json",value = 
800                 "{\"result\":{\"row 0\":{\"address\":"
801                 + "{\"city\":\"Someplace\",\"street\":\"1 Some way\"},"
802                 + "\"emp_salary\":50,\"emp_name\":\"tom\",\"emp_id\":"
803                 + "\"cfd66ccc-d857-4e90-b1e5-df98a3d40cd6\"}},\"status\":\"SUCCESS\"}")
804         })),
805         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
806             @ExampleProperty(mediaType="application/json",value = 
807                 "{\"error\" : \"<errorMessage>\","
808                 + "\"status\" : \"FAILURE\"}") 
809         }))
810     })
811     public Response selectCritical(
812         @ApiParam(value = "Major Version",
813     required = true) @PathParam("version") String version,
814         @ApiParam(value = "Minor Version",example = "0",
815             required = false) @HeaderParam(XMINORVERSION) String minorVersion,
816         @ApiParam(value = "Patch Version",example = "0",
817             required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
818         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
819         @ApiParam(value = "Application namespace",
820             required = false, hidden = true) @HeaderParam(NS) String ns,
821         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
822         JsonInsert selObj,
823         @ApiParam(value = "Keyspace Name",
824             required = true) @PathParam("keyspace") String keyspace,
825         @ApiParam(value = "Table Name",
826             required = true) @PathParam("tablename") String tablename,
827         @Context UriInfo info) throws Exception {
828         try {
829             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
830             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())) { 
831                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
832                     .setError("one or more path parameters are not set, please check and try again")
833                     .toMap()).build();
834             }
835             EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspace + " )");
836             if (info.getQueryParameters().isEmpty()) {
837                 logger.error(EELFLoggerDelegate.errorLogger,RestMusicDataAPI.PARAMETER_ERROR, AppMessages.UNKNOWNERROR  ,ErrorSeverity.WARN, ErrorTypes
838                 .GENERALSERVICEERROR);
839                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(RestMusicDataAPI.PARAMETER_ERROR).toMap()).build();
840             }
841             if (selObj == null || selObj.getConsistencyInfo().isEmpty()) {
842                 String error = " Missing Body or Consistency type.";
843                 logger.error(EELFLoggerDelegate.errorLogger,ResultType.BODYMISSING.getResult() + error, AppMessages.MISSINGDATA  ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
844                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ResultType.BODYMISSING.getResult() + error).toMap()).build();
845             }
846             ResultSet results = null;
847             String consistency = selObj.getConsistencyInfo().get("type");
848             String lockId = selObj.getConsistencyInfo().get("lockId");
849             selObj.setKeyspaceName(keyspace);
850             selObj.setTableName(tablename);
851             try {
852                 if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
853                     if(lockId == null) {
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();
858                     }
859                 }
860                 results = MusicCore.selectCritical(selObj, info.getQueryParameters());
861             }catch (MusicQueryException ex) {
862                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage()  ,ErrorSeverity
863                         .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
864                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
865                 
866             }catch(Exception ex) {
867                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
868             }
869
870             if(results!=null && results.getAvailableWithoutFetching() >0) {
871                 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
872             }
873             return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setError("No data found").toMap()).build();
874         } finally {
875             EELFLoggerDelegate.mdcRemove("keyspace");
876         }
877     }
878
879     /**
880      * This API will replace the original select and provide a single API fro select and critical. 
881      * The idea is to depreciate the older api of criticalGet and use a single API. 
882      * 
883      * @param selObj
884      * @param keyspace
885      * @param tablename
886      * @param info
887      * @return
888      */
889     @GET
890     @Path("/{keyspace: .*}/tables/{tablename: .*}/rows")
891     @ApiOperation(value = "Select", response = Map.class,
892         notes = "This has 2 versions: if minorVersion and patchVersion is null or 0, this will be a Eventual Select only.\n"
893         + "If minorVersion is 1 and patchVersion is 0, this will act like the Critical Select \n"
894         + "Critical Get requires parameter rowId=value and consistency in order to work.\n"
895         + "If parameters are missing or consistency information is missing. An eventual select will be preformed.")
896     @Consumes(MediaType.APPLICATION_JSON)
897     @Produces(MediaType.APPLICATION_JSON)
898     @ApiResponses(value={
899         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
900             @ExampleProperty(mediaType="application/json",value = 
901                 "{\"result\":{\"row 0\":{\"address\":"
902                 + "{\"city\":\"Someplace\",\"street\":\"1 Some way\"},"
903                 + "\"emp_salary\":50,\"emp_name\":\"tom\",\"emp_id\":"
904                 + "\"cfd66ccc-d857-4e90-b1e5-df98a3d40cd6\"}},\"status\":\"SUCCESS\"}")
905         })),
906         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
907             @ExampleProperty(mediaType="application/json",value = 
908                 "{\"error\" : \"<errorMessage>\","
909                 + "\"status\" : \"FAILURE\"}") 
910         }))
911     })
912     public Response selectWithCritical(
913         @ApiParam(value = "Major Version",example = "v2", 
914             required = true) @PathParam("version") String version,
915         @ApiParam(value = "Minor Version",example = "1",
916             required = false) @HeaderParam(XMINORVERSION) String minorVersion,
917         @ApiParam(value = "Patch Version",example = "0",
918             required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
919         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
920         @ApiParam(value = "Application namespace",
921             required = false,hidden = true) @HeaderParam(NS) String ns,
922         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
923         JsonInsert selObj,
924         @ApiParam(value = "Keyspace Name", required = true) @PathParam("keyspace") String keyspace,
925         @ApiParam(value = "Table Name", required = true) @PathParam("tablename") String tablename,
926         @Context UriInfo info) throws Exception {
927         if ((minorVersion != null && patchVersion != null) &&
928             (Integer.parseInt(minorVersion) == 1 && Integer.parseInt(patchVersion) == 0) &&
929             (!(null == selObj) && !selObj.getConsistencyInfo().isEmpty())) {
930             return selectCritical(version, minorVersion, patchVersion, aid, ns, authorization, selObj, keyspace, tablename, info);
931         } else {
932             return select(version, minorVersion, patchVersion, aid, ns, authorization, keyspace, tablename, info);
933         }
934     }
935
936     /**
937      *
938      * @param keyspace
939      * @param tablename
940      * @param info
941      * @return
942      * @throws Exception
943      */
944     private Response select(
945         String version,String minorVersion,String patchVersion,
946         String aid,String ns,String authorization,String keyspace,        
947         String tablename,UriInfo info) throws Exception {
948         try { 
949             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
950             if((keyspace == null || keyspace.isEmpty()) || (tablename == null || tablename.isEmpty())){
951                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
952                     .setError("one or more path parameters are not set, please check and try again")
953                     .toMap()).build();
954             }
955             EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspace + " ) ");
956             try {
957                 JsonSelect jsonSelect = new JsonSelect();
958                 jsonSelect.setKeyspaceName(keyspace);
959                 jsonSelect.setTableName(tablename);
960                 ResultSet results = MusicCore.select(jsonSelect, info.getQueryParameters());
961                 if(results.getAvailableWithoutFetching() >0) {
962                     return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).toMap()).build();
963                 }
964                 return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setDataResult(MusicDataStoreHandle.marshallResults(results)).setError("No data found").toMap()).build();
965             } catch (MusicQueryException ex) {
966                 logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage(), ex.getMessage()  ,ErrorSeverity
967                         .WARN, ErrorTypes.MUSICSERVICEERROR, ex);
968                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
969                 
970             } catch (MusicServiceException ex) {
971                 logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR  ,ErrorSeverity.ERROR,
972                     ErrorTypes.MUSICSERVICEERROR, ex);
973                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();
974             }
975         } finally {
976             EELFLoggerDelegate.mdcRemove("keyspace");
977         }
978     }
979
980     /**
981      *
982      * @param keyspace
983      * @param tablename
984      * @param info
985      * @param limit
986      * @return
987      * @throws MusicServiceException
988      */
989     public PreparedQueryObject selectSpecificQuery(String keyspace,
990         String tablename, UriInfo info, int limit)
991         throws MusicServiceException {
992         PreparedQueryObject queryObject = new PreparedQueryObject();
993         StringBuilder rowIdString = getRowIdentifier(keyspace, 
994             tablename,info.getQueryParameters(),queryObject).rowIdString;
995         queryObject.appendQueryString(
996             "SELECT *  FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
997         if (limit != -1) {
998             queryObject.appendQueryString(" LIMIT " + limit);
999         }
1000         queryObject.appendQueryString(";");
1001         return queryObject;
1002     }
1003
1004     /**
1005      *
1006      * @param keyspace
1007      * @param tablename
1008      * @param rowParams
1009      * @param queryObject
1010      * @return
1011      * @throws MusicServiceException
1012      */
1013     private RowIdentifier getRowIdentifier(String keyspace, String tablename,
1014         MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
1015         throws MusicServiceException {
1016         StringBuilder rowSpec = new StringBuilder();
1017         int counter = 0;
1018         TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
1019         if (tableInfo == null) {
1020             logger.error(EELFLoggerDelegate.errorLogger,
1021                 "Table information not found. Please check input for table name= "
1022                 + keyspace + "." + tablename);
1023             throw new MusicServiceException(
1024                 "Table information not found. Please check input for table name= "
1025                 + keyspace + "." + tablename);
1026         }
1027         StringBuilder primaryKey = new StringBuilder();
1028         for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
1029             String keyName = entry.getKey();
1030             List<String> valueList = entry.getValue();
1031             String indValue = valueList.get(0);
1032             DataType colType = null;
1033             Object formattedValue = null;
1034             try {
1035                 colType = tableInfo.getColumn(entry.getKey()).getType();
1036                 formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
1037             } catch (Exception e) {
1038                 logger.error(EELFLoggerDelegate.errorLogger,e);
1039             }
1040             if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) {
1041                 primaryKey.append(indValue);
1042             }
1043             rowSpec.append(keyName + "= ?");
1044             queryObject.addValue(formattedValue);
1045             if (counter != rowParams.size() - 1) {
1046                 rowSpec.append(" AND ");
1047             }
1048             counter = counter + 1;
1049         }
1050         return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);
1051     }
1052 }