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