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