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