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