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