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