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