Applying bug fixes
[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 com.att.eelf.configuration.EELFLogger;
40 import com.att.eelf.configuration.EELFManager;
41 import org.onap.music.datastore.PreparedQueryObject;
42 import org.onap.music.datastore.jsonobjects.JsonDelete;
43 import org.onap.music.datastore.jsonobjects.JsonInsert;
44 import org.onap.music.datastore.jsonobjects.JsonKeySpace;
45 import org.onap.music.datastore.jsonobjects.JsonTable;
46 import org.onap.music.datastore.jsonobjects.JsonUpdate;
47 import org.onap.music.eelf.logging.EELFLoggerDelegate;
48 import org.onap.music.exceptions.MusicServiceException;
49 import org.onap.music.main.CachingUtil;
50 import org.onap.music.main.MusicCore;
51 import org.onap.music.main.MusicCore.Condition;
52 import org.onap.music.main.MusicUtil;
53 import org.onap.music.main.ResultType;
54 import org.onap.music.main.ReturnType;
55 import org.onap.music.response.jsonobjects.JsonResponse;
56 import com.datastax.driver.core.DataType;
57 import com.datastax.driver.core.ResultSet;
58 import com.datastax.driver.core.Row;
59 import com.datastax.driver.core.TableMetadata;
60 import io.swagger.annotations.Api;
61 import io.swagger.annotations.ApiOperation;
62 import io.swagger.annotations.ApiParam;
63
64 @Path("/v{version: [0-9]+}/keyspaces")
65 @Api(value = "Data Api")
66 public class RestMusicDataAPI {
67     /*
68      * Header values for Versioning X-minorVersion *** - Used to request or communicate a MINOR
69      * version back from the client to the server, and from the server back to the client - This
70      * will be the MINOR version requested by the client, or the MINOR version of the last MAJOR
71      * version (if not specified by the client on the request) - Contains a single position value
72      * (e.g. if the full version is 1.24.5, X-minorVersion = "24") - Is optional for the client on
73      * request; however, this header should be provided if the client needs to take advantage of
74      * MINOR incremented version functionality - Is mandatory for the server on response
75      * 
76      *** X-patchVersion *** - Used only to communicate a PATCH version in a response for
77      * troubleshooting purposes only, and will not be provided by the client on request - This will
78      * be the latest PATCH version of the MINOR requested by the client, or the latest PATCH version
79      * of the MAJOR (if not specified by the client on the request) - Contains a single position
80      * value (e.g. if the full version is 1.24.5, X-patchVersion = "5") - Is mandatory for the
81      * server on response
82      *
83      *** X-latestVersion *** - Used only to communicate an API's latest version - Is mandatory for the
84      * server on response, and shall include the entire version of the API (e.g. if the full version
85      * is 1.24.5, X-latestVersion = "1.24.5") - Used in the response to inform clients that they are
86      * not using the latest version of the API
87      *
88      */
89
90     private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMusicDataAPI.class);
91     private static String xLatestVersion = "X-latestVersion";
92
93     private class RowIdentifier {
94         public String primarKeyValue;
95         public StringBuilder rowIdString;
96         public PreparedQueryObject queryObject;// the string with all the row
97                                                // identifiers separated by AND
98
99         public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
100                         PreparedQueryObject queryObject) {
101             this.primarKeyValue = primaryKeyValue;
102             this.rowIdString = rowIdString;
103             this.queryObject = queryObject;
104         }
105     }
106
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
191         }
192         logger.debug("result = " + result);
193         if (!result) {
194             resultMap.put("Status", String.valueOf(result));
195             resultMap.put("Exception", "Keyspace already exists. Please contact admin.");
196             if (resultMap.get("uuid").equals("new")) {
197                 queryObject = new PreparedQueryObject();
198                 queryObject.appendQueryString(
199                                 "DELETE FROM admin.keyspace_master where uuid = " + newAid);
200                 queryObject.appendQueryString(";");
201                 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
202                 resultMap.remove("aid");
203                 resultMap.remove("uuid");
204                 return resultMap;
205
206             } else {
207                 queryObject = new PreparedQueryObject();
208                 queryObject.appendQueryString(
209                                 "UPDATE admin.keyspace_master SET keyspace_name=?,password=?,is_api=null where uuid = ?;");
210                 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(),
211                                 MusicUtil.DEFAULTKEYSPACENAME));
212                 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), null));
213                 queryObject.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), newAid));
214                 result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
215                 resultMap.remove("aid");
216                 resultMap.remove("uuid");
217                 return resultMap;
218             }
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             result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
226             if (result) {
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             } else {
233                 resultMap.remove("uuid");
234                 resultMap.put("Exception", "Exception while creating user.");
235                 return resultMap;
236             }
237         } catch (Exception e) {
238             logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
239         }
240         resultMap.remove("uuid");
241         if (CachingUtil.isAAFApplication(ns))
242             resultMap.remove("aid");
243         resultMap.put("Status", String.valueOf(result));
244         return resultMap;
245
246     }
247
248     /**
249      * 
250      * @param kspObject
251      * @param keyspaceName
252      * @return
253      * @throws Exception
254      */
255     @DELETE
256     @Path("/{name}")
257     @ApiOperation(value = "Delete Keyspace", response = String.class)
258     @Consumes(MediaType.APPLICATION_JSON)
259     @Produces(MediaType.APPLICATION_JSON)
260     public Map<String, Object> dropKeySpace(
261                     @ApiParam(value = "Major Version",
262                                     required = true) @PathParam("version") String version,
263                     @ApiParam(value = "Minor Version",
264                                     required = false) @HeaderParam("X-minorVersion") String minorVersion,
265                     @ApiParam(value = "Patch Version",
266                                     required = false) @HeaderParam("X-patchVersion") String patchVersion,
267                     @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
268                     @ApiParam(value = "Application namespace",
269                                     required = true) @HeaderParam("ns") String ns,
270                     @ApiParam(value = "userId",
271                                     required = true) @HeaderParam("userId") String userId,
272                     @ApiParam(value = "Password",
273                                     required = true) @HeaderParam("password") String password,
274                     JsonKeySpace kspObject,
275                     @ApiParam(value = "Keyspace Name",
276                                     required = true) @PathParam("name") String keyspaceName,
277                     @Context HttpServletResponse response) throws Exception {
278         Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password,
279                         keyspaceName, aid, "dropKeySpace");
280         response.addHeader(xLatestVersion, MusicUtil.getVersion());
281         if (resultMap.containsKey("aid"))
282             resultMap.remove("aid");
283         if (!resultMap.isEmpty()) {
284             return resultMap;
285         }
286
287         String consistency = MusicUtil.EVENTUAL;// for now this needs only
288                                                 // eventual
289         // consistency
290         String appName = CachingUtil.getAppName(keyspaceName);
291         String uuid = CachingUtil.getUuidFromMusicCache(keyspaceName);
292         PreparedQueryObject pQuery = new PreparedQueryObject();
293         pQuery.appendQueryString(
294                         "select  count(*) as count from admin.keyspace_master where application_name=? allow filtering;");
295         pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), appName));
296         Row row = MusicCore.get(pQuery).one();
297         long count = row.getLong(0);
298
299         if (count == 0) {
300             resultMap.put("Exception", "Keyspace not found. Please make sure keyspace exists.");
301             return resultMap;
302         } else if (count == 1) {
303             pQuery = new PreparedQueryObject();
304             pQuery.appendQueryString(
305                     "UPDATE admin.keyspace_master SET keyspace_name=? where uuid = ?;");
306             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(),
307                     MusicUtil.DEFAULTKEYSPACENAME));
308             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
309             MusicCore.nonKeyRelatedPut(pQuery, consistency);
310         } else {
311             pQuery = new PreparedQueryObject();
312             pQuery.appendQueryString("delete from admin.keyspace_master where uuid = ?");
313             pQuery.addValue(MusicUtil.convertToActualDataType(DataType.uuid(), uuid));
314             MusicCore.nonKeyRelatedPut(pQuery, consistency);
315         }
316
317         PreparedQueryObject queryObject = new PreparedQueryObject();
318         queryObject.appendQueryString("DROP KEYSPACE " + keyspaceName + ";");
319         return new JsonResponse(MusicCore.nonKeyRelatedPut(queryObject, consistency), "", "")
320                         .toMap();
321     }
322
323     /**
324      * 
325      * @param tableObj
326      * @param keyspace
327      * @param tablename
328      * @return
329      * @throws Exception
330      */
331     @POST
332     @Path("/{keyspace}/tables/{tablename}")
333     @ApiOperation(value = "Create Table", response = String.class)
334     @Consumes(MediaType.APPLICATION_JSON)
335     @Produces(MediaType.APPLICATION_JSON)
336     public Map<String, Object> createTable(
337                     @ApiParam(value = "Major Version",
338                                     required = true) @PathParam("version") String version,
339                     @ApiParam(value = "Minor Version",
340                                     required = false) @HeaderParam("X-minorVersion") String minorVersion,
341                     @ApiParam(value = "Patch Version",
342                                     required = false) @HeaderParam("X-patchVersion") String patchVersion,
343                     @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
344                     @ApiParam(value = "Application namespace",
345                                     required = true) @HeaderParam("ns") String ns,
346                     @ApiParam(value = "userId",
347                                     required = true) @HeaderParam("userId") String userId,
348                     @ApiParam(value = "Password",
349                                     required = true) @HeaderParam("password") String password,
350                     JsonTable tableObj,
351                     @ApiParam(value = "Keyspace Name",
352                                     required = true) @PathParam("keyspace") String keyspace,
353                     @ApiParam(value = "Table Name",
354                                     required = true) @PathParam("tablename") String tablename,
355                     @Context HttpServletResponse response) throws Exception {
356         Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
357                         aid, "createTable");
358         response.addHeader(xLatestVersion, MusicUtil.getVersion());
359         if (resultMap.containsKey("aid"))
360             resultMap.remove("aid");
361         if (!resultMap.isEmpty()) {
362             return resultMap;
363         }
364         String consistency = MusicUtil.EVENTUAL;
365         // for now this needs only eventual consistency
366         PreparedQueryObject queryObject = new PreparedQueryObject();
367         boolean result = false;
368         // first read the information about the table fields
369         Map<String, String> fields = tableObj.getFields();
370         StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
371         int counter = 0;
372         String primaryKey;
373         for (Map.Entry<String, String> entry : fields.entrySet()) {
374             fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
375             if (entry.getKey().equals("PRIMARY KEY")) {
376                 primaryKey = entry.getValue().substring(entry.getValue().indexOf('(') + 1);
377                 primaryKey = primaryKey.substring(0, primaryKey.indexOf(')'));
378             }
379             if (counter == fields.size() - 1)
380                 fieldsString.append(")");
381             else
382                 fieldsString.append(",");
383             counter = counter + 1;
384         }
385         // information about the name-value style properties
386         Map<String, Object> propertiesMap = tableObj.getProperties();
387         StringBuilder propertiesString = new StringBuilder();
388         if (propertiesMap != null) {
389             counter = 0;
390             for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
391                 Object ot = entry.getValue();
392                 String value = ot + "";
393                 if (ot instanceof String) {
394                     value = "'" + value + "'";
395                 } else if (ot instanceof Map) {
396                     Map<String, Object> otMap = (Map<String, Object>) ot;
397                     value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
398                 }
399
400                 propertiesString.append(entry.getKey() + "=" + value + "");
401                 if (counter != propertiesMap.size() - 1)
402                     propertiesString.append(" AND ");
403
404                 counter = counter + 1;
405             }
406         }
407
408         queryObject.appendQueryString(
409                         "CREATE TABLE " + keyspace + "." + tablename + " " + fieldsString);
410
411         if (propertiesMap != null)
412             queryObject.appendQueryString(" WITH " + propertiesString);
413
414         queryObject.appendQueryString(";");
415         try {
416             result = MusicCore.nonKeyRelatedPut(queryObject, consistency);
417         } catch (MusicServiceException ex) {
418             return new JsonResponse(false, ex.getMessage(), "").toMap();
419         }
420
421         return new JsonResponse(result, "", "").toMap();
422     }
423
424     /**
425      * 
426      * @param keyspace
427      * @param tablename
428      * @param fieldName
429      * @param info
430      * @throws Exception
431      */
432     @POST
433     @Path("/{keyspace}/tables/{tablename}/index/{field}")
434     @ApiOperation(value = "Create Index", response = String.class)
435     @Produces(MediaType.APPLICATION_JSON)
436     public Map<String, Object> createIndex(
437                     @ApiParam(value = "Major Version",
438                                     required = true) @PathParam("version") String version,
439                     @ApiParam(value = "Minor Version",
440                                     required = false) @HeaderParam("X-minorVersion") String minorVersion,
441                     @ApiParam(value = "Patch Version",
442                                     required = false) @HeaderParam("X-patchVersion") String patchVersion,
443                     @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
444                     @ApiParam(value = "Application namespace",
445                                     required = true) @HeaderParam("ns") String ns,
446                     @ApiParam(value = "userId",
447                                     required = true) @HeaderParam("userId") String userId,
448                     @ApiParam(value = "Password",
449                                     required = true) @HeaderParam("password") String password,
450                     @ApiParam(value = "Keyspace Name",
451                                     required = true) @PathParam("keyspace") String keyspace,
452                     @ApiParam(value = "Table Name",
453                                     required = true) @PathParam("tablename") String tablename,
454                     @ApiParam(value = "Field Name",
455                                     required = true) @PathParam("field") String fieldName,
456                     @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
457         Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
458                         aid, "createIndex");
459         response.addHeader(xLatestVersion, MusicUtil.getVersion());
460         if (resultMap.containsKey("aid"))
461             resultMap.remove("aid");
462         if (!resultMap.isEmpty())
463             return resultMap;
464         MultivaluedMap<String, String> rowParams = info.getQueryParameters();
465         String indexName = "";
466         if (rowParams.getFirst("index_name") != null)
467             indexName = rowParams.getFirst("index_name");
468         PreparedQueryObject query = new PreparedQueryObject();
469         query.appendQueryString("Create index " + indexName + " if not exists on " + keyspace + "."
470                         + tablename + " (" + fieldName + ");");
471         return new JsonResponse(MusicCore.nonKeyRelatedPut(query, "eventual"), "", "").toMap();
472
473     }
474
475     /**
476      * 
477      * @param insObj
478      * @param keyspace
479      * @param tablename
480      * @return
481      * @throws Exception
482      */
483     @POST
484     @Path("/{keyspace}/tables/{tablename}/rows")
485     @ApiOperation(value = "Insert Into Table", response = String.class)
486     @Consumes(MediaType.APPLICATION_JSON)
487     @Produces(MediaType.APPLICATION_JSON)
488     public Map<String, Object> insertIntoTable(
489                     @ApiParam(value = "Major Version",
490                                     required = true) @PathParam("version") String version,
491                     @ApiParam(value = "Minor Version",
492                                     required = false) @HeaderParam("X-minorVersion") String minorVersion,
493                     @ApiParam(value = "Patch Version",
494                                     required = false) @HeaderParam("X-patchVersion") String patchVersion,
495                     @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
496                     @ApiParam(value = "Application namespace",
497                                     required = true) @HeaderParam("ns") String ns,
498                     @ApiParam(value = "userId",
499                                     required = true) @HeaderParam("userId") String userId,
500                     @ApiParam(value = "Password",
501                                     required = true) @HeaderParam("password") String password,
502                     JsonInsert insObj,
503                     @ApiParam(value = "Keyspace Name",
504                                     required = true) @PathParam("keyspace") String keyspace,
505                     @ApiParam(value = "Table Name",
506                                     required = true) @PathParam("tablename") String tablename,
507                     @Context HttpServletResponse response) throws Exception {
508         Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
509                         aid, "insertIntoTable");
510         response.addHeader(xLatestVersion, MusicUtil.getVersion());
511         if (resultMap.containsKey("aid"))
512             resultMap.remove("aid");
513         if (!resultMap.isEmpty()) {
514             return resultMap;
515         }
516         ReturnType result = null;
517         Map<String, Object> valuesMap = insObj.getValues();
518         PreparedQueryObject queryObject = new PreparedQueryObject();
519         TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename);
520         String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();
521         StringBuilder fieldsString = new StringBuilder("(vector_ts,");
522         String vectorTs =
523                         String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
524         StringBuilder valueString = new StringBuilder("(" + "?" + ",");
525         queryObject.addValue(vectorTs);
526         int counter = 0;
527         String primaryKey = "";
528
529         for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
530             fieldsString.append("" + entry.getKey());
531             Object valueObj = entry.getValue();
532             if (primaryKeyName.equals(entry.getKey())) {
533                 primaryKey = entry.getValue() + "";
534                 primaryKey = primaryKey.replace("'", "''");
535             }
536
537             DataType colType = tableInfo.getColumn(entry.getKey()).getType();
538
539             Object formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
540             valueString.append("?");
541             queryObject.addValue(formattedValue);
542
543             if (counter == valuesMap.size() - 1) {
544                 fieldsString.append(")");
545                 valueString.append(")");
546             } else {
547                 fieldsString.append(",");
548                 valueString.append(",");
549             }
550             counter = counter + 1;
551         }
552
553         queryObject.appendQueryString("INSERT INTO " + keyspace + "." + tablename + " "
554                         + fieldsString + " VALUES " + valueString);
555
556         String ttl = insObj.getTtl();
557         String timestamp = insObj.getTimestamp();
558
559         if ((ttl != null) && (timestamp != null)) {
560             logger.info(EELFLoggerDelegate.applicationLogger, "both there");
561             queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
562             queryObject.addValue(Integer.parseInt(ttl));
563             queryObject.addValue(Long.parseLong(timestamp));
564         }
565
566         if ((ttl != null) && (timestamp == null)) {
567             logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there");
568             queryObject.appendQueryString(" USING TTL ?");
569             queryObject.addValue(Integer.parseInt(ttl));
570         }
571
572         if ((ttl == null) && (timestamp != null)) {
573             logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there");
574             queryObject.appendQueryString(" USING TIMESTAMP ?");
575             queryObject.addValue(Long.parseLong(timestamp));
576         }
577
578         queryObject.appendQueryString(";");
579
580         String consistency = insObj.getConsistencyInfo().get("type");
581         try {
582             if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
583                 result = MusicCore.eventualPut(queryObject);
584             } else if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
585                 String lockId = insObj.getConsistencyInfo().get("lockId");
586                 result = MusicCore.criticalPut(keyspace, tablename, primaryKey, queryObject, lockId,
587                                 null);
588             } else if (consistency.equalsIgnoreCase(MusicUtil.ATOMIC)) {
589                 result = MusicCore.atomicPut(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         try {
866             return operationResult.toMap();
867         } catch (NullPointerException e) {
868             return new ReturnType(ResultType.FAILURE, e.getMessage()).toMap();
869         }
870     }
871
872     /**
873      * 
874      * @param tabObj
875      * @param keyspace
876      * @param tablename
877      * @throws Exception
878      */
879     @DELETE
880     @Path("/{keyspace}/tables/{tablename}")
881     @ApiOperation(value = "Drop Table", response = String.class)
882     @Consumes(MediaType.APPLICATION_JSON)
883     @Produces(MediaType.APPLICATION_JSON)
884     public Map<String, Object> dropTable(
885                     @ApiParam(value = "Major Version",
886                                     required = true) @PathParam("version") String version,
887                     @ApiParam(value = "Minor Version",
888                                     required = false) @HeaderParam("X-minorVersion") String minorVersion,
889                     @ApiParam(value = "Patch Version",
890                                     required = false) @HeaderParam("X-patchVersion") String patchVersion,
891                     @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
892                     @ApiParam(value = "Application namespace",
893                                     required = true) @HeaderParam("ns") String ns,
894                     @ApiParam(value = "userId",
895                                     required = true) @HeaderParam("userId") String userId,
896                     @ApiParam(value = "Password",
897                                     required = true) @HeaderParam("password") String password,
898                     JsonTable tabObj,
899                     @ApiParam(value = "Keyspace Name",
900                                     required = true) @PathParam("keyspace") String keyspace,
901                     @ApiParam(value = "Table Name",
902                                     required = true) @PathParam("tablename") String tablename,
903                     @Context HttpServletResponse response) throws Exception {
904         Map<String, Object> resultMap =
905                         MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "dropTable");
906         response.addHeader(xLatestVersion, MusicUtil.getVersion());
907         if (resultMap.containsKey("aid"))
908             resultMap.remove("aid");
909         if (!resultMap.isEmpty()) {
910             return resultMap;
911         }
912         String consistency = "eventual";// for now this needs only eventual
913                                         // consistency
914         PreparedQueryObject query = new PreparedQueryObject();
915         query.appendQueryString("DROP TABLE  " + keyspace + "." + tablename + ";");
916         try {
917             return new JsonResponse(MusicCore.nonKeyRelatedPut(query, consistency), "", "").toMap();
918         } catch (MusicServiceException ex) {
919             return new JsonResponse(false, ex.getMessage(), "").toMap();
920         }
921
922     }
923
924     /**
925      * 
926      * @param selObj
927      * @param keyspace
928      * @param tablename
929      * @param info
930      * @return
931      */
932     @PUT
933     @Path("/{keyspace}/tables/{tablename}/rows/criticalget")
934     @ApiOperation(value = "Select Critical", response = Map.class)
935     @Consumes(MediaType.APPLICATION_JSON)
936     @Produces(MediaType.APPLICATION_JSON)
937     public Map<String, HashMap<String, Object>> selectCritical(
938                     @ApiParam(value = "Major Version",
939                                     required = true) @PathParam("version") String version,
940                     @ApiParam(value = "Minor Version",
941                                     required = false) @HeaderParam("X-minorVersion") String minorVersion,
942                     @ApiParam(value = "Patch Version",
943                                     required = false) @HeaderParam("X-patchVersion") String patchVersion,
944                     @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
945                     @ApiParam(value = "Application namespace",
946                                     required = true) @HeaderParam("ns") String ns,
947                     @ApiParam(value = "userId",
948                                     required = true) @HeaderParam("userId") String userId,
949                     @ApiParam(value = "Password",
950                                     required = true) @HeaderParam("password") String password,
951                     JsonInsert selObj,
952                     @ApiParam(value = "Keyspace Name",
953                                     required = true) @PathParam("keyspace") String keyspace,
954                     @ApiParam(value = "Table Name",
955                                     required = true) @PathParam("tablename") String tablename,
956                     @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
957         Map<String, Object> resultMap = MusicCore.autheticateUser(ns, userId, password, keyspace,
958                         aid, "selectCritical");
959         response.addHeader(xLatestVersion, MusicUtil.getVersion());
960         if (resultMap.containsKey("aid"))
961             resultMap.remove("aid");
962         if (!resultMap.isEmpty()) {
963             logger.error("Error while authentication... ");
964             HashMap<String, Object> tempMap = new HashMap<>();
965             tempMap.putAll(resultMap);
966             Map<String, HashMap<String, Object>> results = new HashMap<>();
967             results.put("Result", tempMap);
968             return results;
969         }
970         String lockId = selObj.getConsistencyInfo().get("lockId");
971
972         PreparedQueryObject queryObject = new PreparedQueryObject();
973         StringBuilder rowSpec = new StringBuilder();
974
975         RowIdentifier rowId = null;
976         try {
977             rowId = getRowIdentifier(keyspace, tablename, info.getQueryParameters(), queryObject);
978         } catch (MusicServiceException ex) {
979             return MusicUtil.setErrorResponse(ex);
980         }
981         queryObject.appendQueryString(
982                         "SELECT *  FROM " + keyspace + "." + tablename + " WHERE " + rowSpec + ";");
983
984         ResultSet results = null;
985
986         String consistency = selObj.getConsistencyInfo().get("type");
987
988         if (consistency.equalsIgnoreCase("critical")) {
989             results = MusicCore.criticalGet(keyspace, tablename, rowId.primarKeyValue, queryObject,
990                             lockId);
991         } else if (consistency.equalsIgnoreCase("atomic")) {
992             results = MusicCore.atomicGet(keyspace, tablename, rowId.primarKeyValue, queryObject);
993         }
994
995         return MusicCore.marshallResults(results);
996     }
997
998     /**
999      * 
1000      * @param keyspace
1001      * @param tablename
1002      * @param info
1003      * @return
1004      * @throws Exception
1005      */
1006     @GET
1007     @Path("/{keyspace}/tables/{tablename}/rows")
1008     @ApiOperation(value = "Select All or Select Specivic", response = Map.class)
1009     @Produces(MediaType.APPLICATION_JSON)
1010     public Map<String, HashMap<String, Object>> select(
1011                     @ApiParam(value = "Major Version",
1012                                     required = true) @PathParam("version") String version,
1013                     @ApiParam(value = "Minor Version",
1014                                     required = false) @HeaderParam("X-minorVersion") String minorVersion,
1015                     @ApiParam(value = "Patch Version",
1016                                     required = false) @HeaderParam("X-patchVersion") String patchVersion,
1017                     @ApiParam(value = "AID", required = true) @HeaderParam("aid") String aid,
1018                     @ApiParam(value = "Application namespace",
1019                                     required = true) @HeaderParam("ns") String ns,
1020                     @ApiParam(value = "userId",
1021                                     required = true) @HeaderParam("userId") String userId,
1022                     @ApiParam(value = "Password",
1023                                     required = true) @HeaderParam("password") String password,
1024                     @ApiParam(value = "Keyspace Name",
1025                                     required = true) @PathParam("keyspace") String keyspace,
1026                     @ApiParam(value = "Table Name",
1027                                     required = true) @PathParam("tablename") String tablename,
1028                     @Context UriInfo info, @Context HttpServletResponse response) throws Exception {
1029         Map<String, Object> resultMap =
1030                         MusicCore.autheticateUser(ns, userId, password, keyspace, aid, "select");
1031         response.addHeader(xLatestVersion, MusicUtil.getVersion());
1032         if (resultMap.containsKey("aid"))
1033             resultMap.remove("aid");
1034         if (!resultMap.isEmpty()) {
1035             logger.error("Error while authentication... ");
1036             HashMap<String, Object> tempMap = new HashMap<>();
1037             tempMap.putAll(resultMap);
1038             Map<String, HashMap<String, Object>> results = new HashMap<>();
1039             results.put("Result", tempMap);
1040             return results;
1041         }
1042         PreparedQueryObject queryObject = new PreparedQueryObject();
1043
1044         if (info.getQueryParameters().isEmpty())// select all
1045             queryObject.appendQueryString("SELECT *  FROM " + keyspace + "." + tablename + ";");
1046         else {
1047             int limit = -1; // do not limit the number of results
1048             try {
1049                 queryObject = selectSpecificQuery(version, minorVersion, patchVersion, aid, ns,
1050                                 userId, password, keyspace, tablename, info, limit);
1051             } catch (MusicServiceException ex) {
1052                 return MusicUtil.setErrorResponse(ex);
1053             }
1054         }
1055
1056         try {
1057             ResultSet results = MusicCore.get(queryObject);
1058             return MusicCore.marshallResults(results);
1059         } catch (MusicServiceException ex) {
1060             return MusicUtil.setErrorResponse(ex);
1061         }
1062
1063     }
1064
1065     /**
1066      * 
1067      * @param keyspace
1068      * @param tablename
1069      * @param info
1070      * @param limit
1071      * @return
1072      * @throws MusicServiceException
1073      * @throws Exception
1074      */
1075     public PreparedQueryObject selectSpecificQuery(String version, String minorVersion,
1076                     String patchVersion, String aid, String ns, String userId, String password,
1077                     String keyspace, String tablename, UriInfo info, int limit)
1078                     throws MusicServiceException {
1079
1080         PreparedQueryObject queryObject = new PreparedQueryObject();
1081         StringBuilder rowIdString = getRowIdentifier(keyspace, tablename, info.getQueryParameters(),
1082                         queryObject).rowIdString;
1083
1084         queryObject.appendQueryString(
1085                         "SELECT *  FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
1086
1087         if (limit != -1) {
1088             queryObject.appendQueryString(" LIMIT " + limit);
1089         }
1090
1091         queryObject.appendQueryString(";");
1092         return queryObject;
1093
1094     }
1095
1096     /**
1097      * 
1098      * @param keyspace
1099      * @param tablename
1100      * @param rowParams
1101      * @param queryObject
1102      * @return
1103      * @throws MusicServiceException
1104      * @throws Exception
1105      */
1106     private RowIdentifier getRowIdentifier(String keyspace, String tablename,
1107                     MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
1108                     throws MusicServiceException {
1109         StringBuilder rowSpec = new StringBuilder();
1110         int counter = 0;
1111         TableMetadata tableInfo = MusicCore.returnColumnMetadata(keyspace, tablename);
1112         if (tableInfo == null) {
1113             logger.error(EELFLoggerDelegate.errorLogger,
1114                             "Table information not found. Please check input for table name= "
1115                                             + keyspace + "." + tablename);
1116             throw new MusicServiceException(
1117                             "Table information not found. Please check input for table name= "
1118                                             + keyspace + "." + tablename);
1119         }
1120         StringBuilder primaryKey = new StringBuilder();
1121         for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
1122             String keyName = entry.getKey();
1123             List<String> valueList = entry.getValue();
1124             String indValue = valueList.get(0);
1125             DataType colType = tableInfo.getColumn(entry.getKey()).getType();
1126             Object formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
1127             primaryKey.append(indValue);
1128             rowSpec.append(keyName + "= ?");
1129             queryObject.addValue(formattedValue);
1130             if (counter != rowParams.size() - 1)
1131                 rowSpec.append(" AND ");
1132             counter = counter + 1;
1133         }
1134         return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);
1135     }
1136 }