06eeb805a3641898d819a34e4248d3eded527965
[music.git] / src / main / java / org / onap / music / main / MusicUtil.java
1 /*
2  * ============LICENSE_START==========================================
3  * org.onap.music
4  * ===================================================================
5  *  Copyright (c) 2017 AT&T Intellectual Property
6  * ===================================================================
7  *  Modifications Copyright (c) 2018 IBM.
8  *  Modifications Copyright (c) 2019 Samsung.
9  * ===================================================================
10  *  Licensed under the Apache License, Version 2.0 (the "License");
11  *  you may not use this file except in compliance with the License.
12  *  You may obtain a copy of the License at
13  *
14  *     http://www.apache.org/licenses/LICENSE-2.0
15  *
16  *  Unless required by applicable law or agreed to in writing, software
17  *  distributed under the License is distributed on an "AS IS" BASIS,
18  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  *  See the License for the specific language governing permissions and
20  *  limitations under the License.
21  *
22  * ============LICENSE_END=============================================
23  * ====================================================================
24  */
25
26 package org.onap.music.main;
27
28 import com.datastax.driver.core.ColumnDefinitions;
29 import com.datastax.driver.core.ColumnDefinitions.Definition;
30 import com.datastax.driver.core.ResultSet;
31 import com.datastax.driver.core.Row;
32 import java.io.File;
33 import java.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.math.BigInteger;
37 import java.nio.ByteBuffer;
38 import java.util.ArrayList;
39 import java.util.HashMap;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Properties;
43 import java.util.Scanner;
44 import java.util.StringTokenizer;
45 import java.util.UUID;
46 import java.util.concurrent.ConcurrentHashMap;
47 import java.util.concurrent.ConcurrentMap;
48
49 import javax.ws.rs.core.Response;
50 import javax.ws.rs.core.Response.ResponseBuilder;
51 import org.onap.music.datastore.MusicDataStoreHandle;
52 import org.onap.music.datastore.PreparedQueryObject;
53 import org.onap.music.eelf.logging.EELFLoggerDelegate;
54 import org.onap.music.eelf.logging.format.AppMessages;
55 import org.onap.music.eelf.logging.format.ErrorSeverity;
56 import org.onap.music.eelf.logging.format.ErrorTypes;
57 import org.onap.music.exceptions.MusicQueryException;
58 import org.onap.music.exceptions.MusicServiceException;
59 import org.onap.music.service.MusicCoreService;
60 import org.onap.music.service.impl.MusicCassaCore;
61 import org.onap.music.service.impl.MusicZKCore;
62
63 import com.datastax.driver.core.ConsistencyLevel;
64 import com.datastax.driver.core.DataType;
65 import com.sun.jersey.core.util.Base64;
66
67 /**
68  * @author nelson24
69  *
70  *         Properties This will take Properties and load them into MusicUtil.
71  *         This is a hack for now. Eventually it would bebest to do this in
72  *         another way.
73  *
74  */
75 public class MusicUtil {
76     private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicUtil.class);
77
78     public static final String ATOMIC = "atomic";
79     public static final String EVENTUAL = "eventual";
80     public static final String CRITICAL = "critical";
81     public static final String EVENTUAL_NB = "eventual_nb";
82     public static final String ALL = "all";
83     public static final String QUORUM = "quorum";
84     public static final String ONE = "one";
85     public static final String ATOMICDELETELOCK = "atomic_delete_lock";
86     public static final String DEFAULTKEYSPACENAME = "TBD";
87     private static final String XLATESTVERSION = "X-latestVersion";
88     private static final String XMINORVERSION = "X-minorVersion";
89     private static final String XPATCHVERSION = "X-patchVersion";
90     public static final String SELECT = "select";
91     public static final String INSERT = "insert";
92     public static final String UPDATE = "update";
93     public static final String UPSERT = "upsert";
94     public static final String USERID = "userId";
95     public static final String PASSWORD = "password";
96     public static final String CASSANDRA = "cassandra";
97     public static final String ZOOKEEPER = "zookeeper";
98
99     public static final String AUTHORIZATION = "Authorization";
100
101     private static final String LOCALHOST = "localhost";
102     private static final String PROPERTIES_FILE = "/opt/app/music/etc/music.properties";
103
104     private static int myId = 0;
105     private static ArrayList<String> allIds = new ArrayList<>();
106     private static String publicIp = "";
107     private static ArrayList<String> allPublicIps = new ArrayList<>();
108     private static String myZkHost = LOCALHOST;
109     private static String myCassaHost = LOCALHOST;
110     private static String defaultMusicIp = LOCALHOST;
111     private static int cassandraPort = 9042;
112     private static int notifytimeout = 30000;
113     private static int notifyinterval = 5000;
114     private static int cacheObjectMaxLife = -1;
115     private static String lockUsing = MusicUtil.CASSANDRA;
116     private static boolean isCadi = false;
117     
118     private static boolean debug = true;
119     private static String version = "2.3.0";
120     private static String musicRestIp = LOCALHOST;
121     private static String musicPropertiesFilePath = PROPERTIES_FILE;
122     private static long defaultLockLeasePeriod = 6000;
123     private static final String[] propKeys = new String[] { "zookeeper.host", "cassandra.host", "music.ip", "debug",
124             "version", "music.rest.ip", "music.properties", "lock.lease.period", "id", "all.ids", "public.ip",
125             "all.pubic.ips", "cassandra.user", "cassandra.password", "aaf.endpoint.url","admin.username","admin.password","aaf.admin.url",
126             "music.namespace","admin.aaf.role","cassandra.port","lock.using"};
127     private static final String[] cosistencyLevel = new String[] {
128             "ALL","EACH_QUORUM","QUORUM","LOCAL_QUORUM","ONE","TWO","THREE","LOCAL_ONE","ANY","SERIAL","LOCAL_SERIAL"};
129     private static final Map<String,ConsistencyLevel> consistencyName = new HashMap<>();
130     static {
131         consistencyName.put("ONE",ConsistencyLevel.ONE);
132         consistencyName.put("TWO",ConsistencyLevel.TWO);
133         consistencyName.put("THREE",ConsistencyLevel.THREE);
134         consistencyName.put("SERIAL",ConsistencyLevel.SERIAL);
135         consistencyName.put("ALL",ConsistencyLevel.ALL);
136         consistencyName.put("EACH_QUORUM",ConsistencyLevel.EACH_QUORUM);
137         consistencyName.put("QUORUM",ConsistencyLevel.QUORUM);
138         consistencyName.put("LOCAL_QUORUM",ConsistencyLevel.LOCAL_QUORUM);
139         consistencyName.put("LOCAL_ONE",ConsistencyLevel.LOCAL_ONE);
140         consistencyName.put("LOCAL_SERIAL",ConsistencyLevel.LOCAL_SERIAL);
141     }
142
143     private static String cassName = "cassandra";
144     private static String cassPwd;
145     private static String aafEndpointUrl = null;
146     public static ConcurrentMap<String, Long> zkNodeMap = new ConcurrentHashMap<>();
147     private static String adminId = "username";
148     private static String adminPass= "password";
149     private static String aafAdminUrl= null;
150     private static String musicNamespace= "com.att.music.api";
151     private static String adminAafRole= "com.att.music.api.admin_api";
152     
153     public static final long MusicEternityEpochMillis = 1533081600000L; // Wednesday, August 1, 2018 12:00:00 AM
154
155     public static final long MaxLockReferenceTimePart = 1000000000000L; // millis after eternity (eq sometime in 2050)
156     
157     public static final long MaxCriticalSectionDurationMillis = 1L * 24 * 60 * 60 * 1000; // 1 day
158
159
160     public static String getLockUsing() {
161         return lockUsing;
162     }
163
164
165     public static void setLockUsing(String lockUsing) {
166         MusicUtil.lockUsing = lockUsing;
167     }
168     
169     public static String getAafAdminUrl() {
170         return aafAdminUrl;
171     }
172
173
174     public static void setAafAdminUrl(String aafAdminUrl) {
175         MusicUtil.aafAdminUrl = aafAdminUrl;
176     }
177
178
179     public static String getMusicNamespace() {
180         return musicNamespace;
181     }
182
183
184     public static void setMusicNamespace(String musicNamespace) {
185         MusicUtil.musicNamespace = musicNamespace;
186     }
187
188
189     public static String getAdminAafRole() {
190         return adminAafRole;
191     }
192
193
194     public static void setAdminAafRole(String adminAafRole) {
195         MusicUtil.adminAafRole = adminAafRole;
196     }
197
198
199
200     public static String getAdminId() {
201         return adminId;
202     }
203
204
205     public static void setAdminId(String adminId) {
206         MusicUtil.adminId = adminId;
207     }
208
209
210     public static String getAdminPass() {
211         return adminPass;
212     }
213
214     public static void setAdminPass(String adminPass) {
215         MusicUtil.adminPass = adminPass;
216     }
217
218
219     private MusicUtil() {
220         throw new IllegalStateException("Utility Class");
221     }
222     /**
223      *
224      * @return cassandra port
225      */
226     public static int getCassandraPort() {
227         return cassandraPort;
228     }
229
230     /**
231      * set cassandra port
232      * @param cassandraPort
233      */
234     public static void setCassandraPort(int cassandraPort) {
235         MusicUtil.cassandraPort = cassandraPort;
236     }
237     /**
238      * @return the cassName
239      */
240     public static String getCassName() {
241         return cassName;
242     }
243
244     /**
245      * @return the cassPwd
246      */
247     public static String getCassPwd() {
248         return cassPwd;
249     }
250
251     /**
252      * @return the aafEndpointUrl
253      */
254     public static String getAafEndpointUrl() {
255         return aafEndpointUrl;
256     }
257
258     /**
259      *
260      * @param aafEndpointUrl
261      */
262     public static void setAafEndpointUrl(String aafEndpointUrl) {
263         MusicUtil.aafEndpointUrl = aafEndpointUrl;
264     }
265
266     /**
267      *
268      * @return
269      */
270     public static int getMyId() {
271         return myId;
272     }
273
274     /**
275      *
276      * @param myId
277      */
278     public static void setMyId(int myId) {
279         MusicUtil.myId = myId;
280     }
281
282     /**
283      *
284      * @return
285      */
286     public static List<String> getAllIds() {
287         return allIds;
288     }
289
290     /**
291      *
292      * @param allIds
293      */
294     public static void setAllIds(List<String> allIds) {
295         MusicUtil.allIds = (ArrayList<String>) allIds;
296     }
297
298     /**
299      *
300      * @return
301      */
302     public static String getPublicIp() {
303         return publicIp;
304     }
305
306     /**
307      *
308      * @param publicIp
309      */
310     public static void setPublicIp(String publicIp) {
311         MusicUtil.publicIp = publicIp;
312     }
313
314     /**
315      *
316      * @return
317      */
318     public static List<String> getAllPublicIps() {
319         return allPublicIps;
320     }
321
322     /**
323      *
324      * @param allPublicIps
325      */
326     public static void setAllPublicIps(List<String> allPublicIps) {
327         MusicUtil.allPublicIps = (ArrayList<String>) allPublicIps;
328     }
329
330     /**
331      * Returns An array of property names that should be in the Properties
332      * files.
333      *
334      * @return
335      */
336     public static String[] getPropkeys() {
337         return propKeys;
338     }
339
340     /**
341      * Get MusicRestIp - default = localhost property file value - music.rest.ip
342      *
343      * @return
344      */
345     public static String getMusicRestIp() {
346         return musicRestIp;
347     }
348
349     /**
350      * Set MusicRestIp
351      *
352      * @param musicRestIp
353      */
354     public static void setMusicRestIp(String musicRestIp) {
355         MusicUtil.musicRestIp = musicRestIp;
356     }
357
358     /**
359      * Get MusicPropertiesFilePath - Default = /opt/music/music.properties
360      * property file value - music.properties
361      *
362      * @return
363      */
364     public static String getMusicPropertiesFilePath() {
365         return musicPropertiesFilePath;
366     }
367
368     /**
369      * Set MusicPropertiesFilePath
370      *
371      * @param musicPropertiesFilePath
372      */
373     public static void setMusicPropertiesFilePath(String musicPropertiesFilePath) {
374         MusicUtil.musicPropertiesFilePath = musicPropertiesFilePath;
375     }
376
377     /**
378      * Get DefaultLockLeasePeriod - Default = 6000 property file value -
379      * lock.lease.period
380      *
381      * @return
382      */
383     public static long getDefaultLockLeasePeriod() {
384         return defaultLockLeasePeriod;
385     }
386
387     /**
388      * Set DefaultLockLeasePeriod
389      *
390      * @param defaultLockLeasePeriod
391      */
392     public static void setDefaultLockLeasePeriod(long defaultLockLeasePeriod) {
393         MusicUtil.defaultLockLeasePeriod = defaultLockLeasePeriod;
394     }
395
396     /**
397      * Set Debug
398      *
399      * @param debug
400      */
401     public static void setDebug(boolean debug) {
402         MusicUtil.debug = debug;
403     }
404
405     /**
406      * Is Debug - Default = true property file value - debug
407      *
408      * @return
409      */
410     public static boolean isDebug() {
411         return debug;
412     }
413
414     /**
415      * Set Version
416      *
417      * @param version
418      */
419     public static void setVersion(String version) {
420         MusicUtil.version = version;
421     }
422
423     /**
424      * Return the version property file value - version
425      *
426      * @return
427      */
428     public static String getVersion() {
429         return version;
430     }
431
432     /**
433      * Get MyZkHost - Zookeeper Hostname - Default = localhost property file
434      * value - zookeeper.host
435      *
436      * @return
437      */
438     public static String getMyZkHost() {
439         return myZkHost;
440     }
441
442     /**
443      * Set MyZkHost - Zookeeper Hostname
444      *
445      * @param myZkHost
446      */
447     public static void setMyZkHost(String myZkHost) {
448         MusicUtil.myZkHost = myZkHost;
449     }
450
451     /**
452      * Get MyCassHost - Cassandra Hostname - Default = localhost property file
453      * value - cassandra.host
454      *
455      * @return
456      */
457     public static String getMyCassaHost() {
458         return myCassaHost;
459     }
460
461     /**
462      * Set MyCassHost - Cassandra Hostname
463      *
464      * @param myCassaHost
465      */
466     public static void setMyCassaHost(String myCassaHost) {
467         MusicUtil.myCassaHost = myCassaHost;
468     }
469
470     /**
471      * Get DefaultMusicIp - Default = localhost property file value - music.ip
472      *
473      * @return
474      */
475     public static String getDefaultMusicIp() {
476         return defaultMusicIp;
477     }
478
479     /**
480      * Set DefaultMusicIp
481      *
482      * @param defaultMusicIp
483      */
484     public static void setDefaultMusicIp(String defaultMusicIp) {
485         MusicUtil.defaultMusicIp = defaultMusicIp;
486     }
487
488     /**
489      *
490      * @return
491      */
492     public static String getTestType() {
493         String testType = "";
494         try {
495             Scanner fileScanner = new Scanner(new File(""));
496             testType = fileScanner.next();// ignore the my id line
497             @SuppressWarnings("unused")
498             String batchSize = fileScanner.next();// ignore the my public ip
499                                                     // line
500             fileScanner.close();
501         } catch (FileNotFoundException e) {
502             logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
503         }
504         return testType;
505
506     }
507
508     /**
509      *
510      * @param time
511      */
512     public static void sleep(long time) {
513         try {
514             Thread.sleep(time);
515         } catch (InterruptedException e) {
516             logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
517             Thread.currentThread().interrupt();
518         }
519     }
520
521     /**
522      * Utility function to check if the query object is valid.
523      *
524      * @param withparams
525      * @param queryObject
526      * @return
527      */
528     public static boolean isValidQueryObject(boolean withparams, PreparedQueryObject queryObject) {
529         if (withparams) {
530             int noOfValues = queryObject.getValues().size();
531             int noOfParams = 0;
532             char[] temp = queryObject.getQuery().toCharArray();
533             for (int i = 0; i < temp.length; i++) {
534                 if (temp[i] == '?')
535                     noOfParams++;
536             }
537             return (noOfValues == noOfParams);
538         } else {
539             return !queryObject.getQuery().isEmpty();
540         }
541
542     }
543
544     public static void setCassName(String cassName) {
545         MusicUtil.cassName = cassName;
546     }
547
548     public static void setCassPwd(String cassPwd) {
549         MusicUtil.cassPwd = cassPwd;
550     }
551
552     @SuppressWarnings("unchecked")
553     public static String convertToCQLDataType(DataType type, Object valueObj) throws Exception {
554
555         String value = "";
556         switch (type.getName()) {
557         case UUID:
558             value = valueObj + "";
559             break;
560         case TEXT:
561         case VARCHAR:
562             String valueString = valueObj + "";
563             valueString = valueString.replace("'", "''");
564             value = "'" + valueString + "'";
565             break;
566         case MAP: {
567             Map<String, Object> otMap = (Map<String, Object>) valueObj;
568             value = "{" + jsonMaptoSqlString(otMap, ",") + "}";
569             break;
570         }
571         default:
572             value = valueObj + "";
573             break;
574         }
575         return value;
576     }
577
578     /**
579      *
580      * @param colType
581      * @param valueObj
582      * @return
583      * @throws MusicTypeConversionException
584      * @throws Exception
585      */
586     @SuppressWarnings("unchecked")
587     public static Object convertToActualDataType(DataType colType, Object valueObj) throws Exception {
588         String valueObjString = valueObj + "";
589         switch (colType.getName()) {
590             case UUID:
591                 return UUID.fromString(valueObjString);
592             case VARINT:
593                 return BigInteger.valueOf(Long.parseLong(valueObjString));
594             case BIGINT:
595                 return Long.parseLong(valueObjString);
596             case INT:
597                 return Integer.parseInt(valueObjString);
598             case FLOAT:
599                 return Float.parseFloat(valueObjString);
600             case DOUBLE:
601                 return Double.parseDouble(valueObjString);
602             case BOOLEAN:
603                 return Boolean.parseBoolean(valueObjString);
604             case MAP:
605                 return (Map<String, Object>) valueObj;
606             case LIST:
607                 return (List<Object>)valueObj;
608             case BLOB:
609
610             default:
611                 return valueObjString;
612         }
613     }
614
615     public static ByteBuffer convertToActualDataType(DataType colType, byte[] valueObj) {
616          ByteBuffer buffer = ByteBuffer.wrap(valueObj);
617          return buffer;
618     }
619
620     /**
621      *
622      * Utility function to parse json map into sql like string
623      *
624      * @param jMap
625      * @param lineDelimiter
626      * @return
627      */
628
629     public static String jsonMaptoSqlString(Map<String, Object> jMap, String lineDelimiter) throws Exception{
630         StringBuilder sqlString = new StringBuilder();
631         int counter = 0;
632         for (Map.Entry<String, Object> entry : jMap.entrySet()) {
633             Object ot = entry.getValue();
634             String value = ot + "";
635             if (ot instanceof String) {
636                 value = "'" + value.replace("'", "''") + "'";
637             }
638             sqlString.append("'" + entry.getKey() + "':" + value);
639             if (counter != jMap.size() - 1)
640                 sqlString.append(lineDelimiter);
641             counter = counter + 1;
642         }
643         return sqlString.toString();
644     }
645
646     @SuppressWarnings("unused")
647     public static String buildVersion(String major, String minor, String patch) {
648         if (minor != null) {
649             major += "." + minor;
650             if (patch != null) {
651                 major += "." + patch;
652             }
653         }
654         return major;
655     }
656
657     /**
658      * Currently this will build a header with X-latestVersion, X-minorVersion and X-pathcVersion
659      * X-latestVerstion will be equal to the latest full version.
660      * X-minorVersion - will be equal to the latest minor version.
661      * X-pathVersion - will be equal to the latest patch version.
662      * Future plans will change this.
663      * @param response
664      * @param major
665      * @param minor
666      * @param patch
667      * @return
668      */
669     public static ResponseBuilder buildVersionResponse(String major, String minor, String patch) {
670         ResponseBuilder response = Response.noContent();
671         String versionIn = buildVersion(major,minor,patch);
672         String version = MusicUtil.getVersion();
673         String[] verArray = version.split("\\.",3);
674         if ( minor != null ) {
675             response.header(XMINORVERSION,minor);
676         } else {
677             response.header(XMINORVERSION,verArray[1]);
678         }
679         if ( patch != null ) {
680             response.header(XPATCHVERSION,patch);
681         } else {
682             response.header(XPATCHVERSION,verArray[2]);
683         }
684         response.header(XLATESTVERSION,version);
685         logger.info(EELFLoggerDelegate.applicationLogger,"Version In:" + versionIn);
686         return response;
687     }
688
689
690     public static Map<String,String> extractBasicAuthentication(String authorization){
691         Map<String,String> authValues = new HashMap<>();
692         if(authorization == null) {
693             authValues.put("ERROR", "Authorization cannot be null");
694             return authValues;
695         }
696         authorization = authorization.replaceFirst("Basic", "");
697         String decoded = Base64.base64Decode(authorization);
698         StringTokenizer token = new StringTokenizer(decoded, ":");
699         authValues.put(MusicUtil.USERID, token.nextToken());
700         authValues.put(MusicUtil.PASSWORD,token.nextToken());
701         return authValues;
702
703     }
704
705     public static boolean isValidConsistency(String consistency) {
706         for (String string : cosistencyLevel) {
707             if (string.equalsIgnoreCase(consistency))
708                 return true;
709         }
710         return false;
711
712     }
713
714     public static ConsistencyLevel getConsistencyLevel(String consistency) {
715         return consistencyName.get(consistency.toUpperCase());
716         }
717
718         public static void loadProperties() throws Exception {
719         Properties prop = new Properties();
720         InputStream input = null;
721         try {
722             // load the properties file
723             input = MusicUtil.class.getClassLoader().getResourceAsStream("music.properties");
724             prop.load(input);
725         } catch (Exception ex) {
726             logger.error(EELFLoggerDelegate.errorLogger, "Unable to find properties file.");
727             throw new Exception();
728         } finally {
729             if (input != null) {
730                 try {
731                     input.close();
732                 } catch (IOException e) {
733                     e.printStackTrace();
734                 }
735             }
736         }
737         // get the property value and return it
738         MusicUtil.setMyCassaHost(prop.getProperty("cassandra.host"));
739         String zkHosts = prop.getProperty("zookeeper.host");
740         MusicUtil.setMyZkHost(zkHosts);
741         MusicUtil.setCassName(prop.getProperty("cassandra.user"));
742         MusicUtil.setCassPwd(prop.getProperty("cassandra.password"));
743         MusicUtil.setCassandraPort(Integer.parseInt(prop.getProperty("cassandra.port")));
744         MusicUtil.setNotifyTimeOut(Integer.parseInt(prop.getProperty("notify.timeout")));
745         MusicUtil.setNotifyInterval(Integer.parseInt(prop.getProperty("notify.interval")));
746         MusicUtil.setCacheObjectMaxLife(Integer.parseInt(prop.getProperty("cacheobject.maxlife")));
747     }
748
749     public static void setNotifyInterval(int notifyinterval) {
750         MusicUtil.notifyinterval = notifyinterval;
751     }
752     public static void setNotifyTimeOut(int notifytimeout) {
753         MusicUtil.notifytimeout = notifytimeout;
754     }
755
756     public static int getNotifyInterval() {
757         return MusicUtil.notifyinterval;
758     }
759
760     public static int getNotifyTimeout() {
761         return MusicUtil.notifytimeout;
762     }
763
764     public static int getCacheObjectMaxLife() {
765         return MusicUtil.cacheObjectMaxLife;
766     }
767
768     public static void setCacheObjectMaxLife(int cacheObjectMaxLife) {
769         MusicUtil.cacheObjectMaxLife = cacheObjectMaxLife;
770     }
771     
772     /**
773      * Given the time of write for an update in a critical section, this method provides a transformed timestamp
774      * that ensures that a previous lock holder who is still alive can never corrupt a later critical section.
775      * The main idea is to us the lock reference to clearly demarcate the timestamps across critical sections.
776      * @param the UUID lock reference associated with the write.
777      * @param the long timeOfWrite which is the actual time at which the write took place
778      * @throws MusicServiceException
779      * @throws MusicQueryException
780      */
781     public static long v2sTimeStampInMicroseconds(long ordinal, long timeOfWrite) throws MusicServiceException, MusicQueryException {
782         // TODO: use acquire time instead of music eternity epoch
783         long ts = ordinal * MaxLockReferenceTimePart + (timeOfWrite - MusicEternityEpochMillis);
784
785         return ts;
786     }
787     
788     public static MusicCoreService  getMusicCoreService() {
789         if(getLockUsing().equals(MusicUtil.CASSANDRA))
790             return MusicCassaCore.getInstance();
791         else if (getLockUsing().equals(MusicUtil.ZOOKEEPER))
792             return MusicZKCore.getInstance();
793         else
794             return MusicCassaCore.getInstance();
795     }
796     
797     /**
798      * @param lockName
799      * @return
800      */
801     public static Map<String, Object> validateLock(String lockName) {
802         Map<String, Object> resultMap = new HashMap<>();
803         String[] locks = lockName.split("\\.");
804         if(locks.length < 3) {
805             resultMap.put("Error", "Invalid lock. Please make sure lock is of the type keyspaceName.tableName.primaryKey");
806             return resultMap;
807         }
808         String keyspace= locks[0];
809         if(keyspace.startsWith("$"))
810             keyspace = keyspace.substring(1);
811         resultMap.put("keyspace",keyspace);
812         return resultMap;
813     }
814
815
816     public static void setIsCadi(boolean isCadi) {
817         MusicUtil.isCadi = isCadi;
818     }
819
820     public static void writeBackToQuorum(PreparedQueryObject selectQuery, String primaryKeyName,
821         PreparedQueryObject updateQuery, String keyspace, String table,
822         Object cqlFormattedPrimaryKeyValue)
823         throws Exception {
824         try {
825             ResultSet results = MusicDataStoreHandle.getDSHandle().executeQuorumConsistencyGet(selectQuery);
826             // write it back to a quorum
827             Row row = results.one();
828             ColumnDefinitions colInfo = row.getColumnDefinitions();
829             int totalColumns = colInfo.size();
830             int counter = 1;
831             StringBuilder fieldValueString = new StringBuilder("");
832             for (Definition definition : colInfo) {
833                 String colName = definition.getName();
834                 if (colName.equals(primaryKeyName))
835                     continue;
836                 DataType colType = definition.getType();
837                 Object valueObj = MusicDataStoreHandle.getDSHandle().getColValue(row, colName, colType);
838                 Object valueString = MusicUtil.convertToActualDataType(colType, valueObj);
839                 fieldValueString.append(colName + " = ?");
840                 updateQuery.addValue(valueString);
841                 if (counter != (totalColumns - 1))
842                     fieldValueString.append(",");
843                 counter = counter + 1;
844             }
845             updateQuery.appendQueryString("UPDATE " + keyspace + "." + table + " SET "
846                 + fieldValueString + " WHERE " + primaryKeyName + "= ? " + ";");
847             updateQuery.addValue(cqlFormattedPrimaryKeyValue);
848
849             MusicDataStoreHandle.getDSHandle().executePut(updateQuery, "critical");
850         } catch (MusicServiceException | MusicQueryException e) {
851             logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.QUERYERROR +""+updateQuery ,
852                 ErrorSeverity.MAJOR, ErrorTypes.QUERYERROR);
853         }
854     }
855     
856     public static boolean getIsCadi() {
857         return MusicUtil.isCadi;
858     }
859
860
861     /**
862      * @return a random uuid
863      */
864     public static String generateUUID() {
865         String uuid = UUID.randomUUID().toString();
866         logger.info(EELFLoggerDelegate.applicationLogger,"New AID generated: "+uuid);
867         return uuid;
868     }
869
870 }
871