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