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