aboutsummaryrefslogtreecommitdiffstats
path: root/music-core/src/main/java/org/onap/music/datastore
diff options
context:
space:
mode:
Diffstat (limited to 'music-core/src/main/java/org/onap/music/datastore')
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/Condition.java63
-rwxr-xr-xmusic-core/src/main/java/org/onap/music/datastore/MusicDataStore.java540
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java127
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/PreparedQueryObject.java176
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/jsonobjects/JSONObject.java37
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java313
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonIndex.java120
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java415
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java163
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java44
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java49
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java208
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java363
-rw-r--r--music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java436
14 files changed, 3054 insertions, 0 deletions
diff --git a/music-core/src/main/java/org/onap/music/datastore/Condition.java b/music-core/src/main/java/org/onap/music/datastore/Condition.java
new file mode 100644
index 00000000..c17d9c07
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/Condition.java
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore;
+
+import java.util.Map;
+import org.onap.music.exceptions.MusicServiceException;
+import org.onap.music.main.MusicCore;
+
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
+
+public class Condition {
+ private Map<String, Object> conditions;
+ private PreparedQueryObject selectQueryForTheRow;
+
+ public Condition(Map<String, Object> conditions, PreparedQueryObject selectQueryForTheRow) {
+ this.conditions = conditions;
+ this.selectQueryForTheRow = selectQueryForTheRow;
+ }
+
+ public boolean testCondition() throws Exception {
+ // first generate the row
+ ResultSet results = quorumGet(selectQueryForTheRow);
+ Row row = null;
+ if(results != null) {
+ row = results.one();
+ }
+ if(row == null) {
+ throw new Exception(" No data found to update");
+ }
+ return getDSHandle().doesRowSatisfyCondition(row, conditions);
+ }
+
+ /* For JUnit testing only */
+ public ResultSet quorumGet(PreparedQueryObject selectQueryForTheRow) {
+ return MusicCore.quorumGet(selectQueryForTheRow);
+ }
+
+ /* For JUnit testing only */
+ public MusicDataStore getDSHandle() throws MusicServiceException {
+ return MusicDataStoreHandle.getDSHandle();
+ }
+ } \ No newline at end of file
diff --git a/music-core/src/main/java/org/onap/music/datastore/MusicDataStore.java b/music-core/src/main/java/org/onap/music/datastore/MusicDataStore.java
new file mode 100755
index 00000000..9ce73cc8
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/MusicDataStore.java
@@ -0,0 +1,540 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * ===================================================================
+ * Modifications Copyright (c) 2018-2019 IBM
+ * Modifications Copyright (c) 2019 Samsung
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.eelf.logging.format.AppMessages;
+import org.onap.music.eelf.logging.format.ErrorSeverity;
+import org.onap.music.eelf.logging.format.ErrorTypes;
+import org.onap.music.exceptions.MusicQueryException;
+import org.onap.music.exceptions.MusicServiceException;
+import org.onap.music.lockingservice.cassandra.LockType;
+import org.onap.music.main.CipherUtil;
+import org.onap.music.main.MusicUtil;
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.ColumnDefinitions;
+import com.datastax.driver.core.ColumnDefinitions.Definition;
+import com.datastax.driver.core.ConsistencyLevel;
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.HostDistance;
+import com.datastax.driver.core.KeyspaceMetadata;
+import com.datastax.driver.core.Metadata;
+import com.datastax.driver.core.PoolingOptions;
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.SimpleStatement;
+import com.datastax.driver.core.SocketOptions;
+import com.datastax.driver.core.TableMetadata;
+import com.datastax.driver.core.exceptions.AlreadyExistsException;
+import com.datastax.driver.core.exceptions.InvalidQueryException;
+import com.datastax.driver.extras.codecs.enums.EnumNameCodec;
+
+/**
+ * @author nelson24
+ *
+ */
+public class MusicDataStore {
+
+ public static final String CONSISTENCY_LEVEL_ONE = "ONE";
+ public static final String CONSISTENCY_LEVEL_QUORUM = "QUORUM";
+ public static final String CONSISTENCY_LEVEL_LOCAL_QUORUM = "LOCAL_QUORUM";
+ private Session session;
+ private Cluster cluster;
+
+
+ /**
+ * Connect to default Cassandra address
+ */
+ public MusicDataStore() {
+ try {
+ connectToCassaCluster(MusicUtil.getMyCassaHost());
+ } catch (MusicServiceException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e);
+ }
+ }
+
+
+ /**
+ * @param cluster
+ * @param session
+ */
+ public MusicDataStore(Cluster cluster, Session session) {
+ this.session = session;
+ setCluster(cluster);
+ }
+
+
+ /**
+ * @param session
+ */
+ public void setSession(Session session) {
+ this.session = session;
+ }
+
+ /**
+ * @param session
+ */
+ public Session getSession() {
+ return session;
+ }
+
+ /**
+ * @param cluster
+ */
+ public void setCluster(Cluster cluster) {
+ EnumNameCodec<LockType> lockTypeCodec = new EnumNameCodec<LockType>(LockType.class);
+ cluster.getConfiguration().getCodecRegistry().register(lockTypeCodec);
+
+ this.cluster = cluster;
+ }
+
+ public Cluster getCluster() {
+ return this.cluster;
+ }
+
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicDataStore.class);
+
+
+ /**
+ *
+ * @param remoteIp
+ * @throws MusicServiceException
+ */
+ public MusicDataStore(String remoteIp) {
+ try {
+ connectToCassaCluster(remoteIp);
+ } catch (MusicServiceException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e);
+ }
+ }
+
+ /**
+ *
+ */
+ public void close() {
+ session.close();
+ }
+
+ /**
+ * This method connects to cassandra cluster on specific address.
+ *
+ * @param address
+ */
+ private void connectToCassaCluster(String address) throws MusicServiceException {
+ String[] addresses = null;
+ addresses = address.split(",");
+ PoolingOptions poolingOptions = new PoolingOptions();
+ poolingOptions
+ .setConnectionsPerHost(HostDistance.LOCAL, 4, 10)
+ .setConnectionsPerHost(HostDistance.REMOTE, 2, 4);
+
+ Cluster cluster;
+ if(MusicUtil.getCassName() != null && MusicUtil.getCassPwd() != null) {
+ String cassPwd;
+ if (MusicUtil.getCipherEncKey() != null && !("").equals(MusicUtil.getCipherEncKey())) {
+ cassPwd = CipherUtil.decryptPKC(MusicUtil.getCassPwd());
+ } else {
+ cassPwd = MusicUtil.getCassPwd();
+ }
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "Building with credentials "+MusicUtil.getCassName()+" & "+ MusicUtil.getCassPwd());
+ cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort())
+ .withCredentials(MusicUtil.getCassName(), cassPwd)
+ //.withLoadBalancingPolicy(new RoundRobinPolicy())
+ .withoutJMXReporting()
+ .withPoolingOptions(poolingOptions)
+ .withSocketOptions(
+ new SocketOptions().setConnectTimeoutMillis(MusicUtil.getCassandraConnectTimeOutMS())
+ .setReadTimeoutMillis(MusicUtil.getCassandraReadTimeOutMS()))
+ .addContactPoints(addresses).build();
+ } else {
+ cluster = Cluster.builder().withPort(MusicUtil.getCassandraPort())
+ .withoutJMXReporting()
+ .withPoolingOptions(poolingOptions)
+ .withSocketOptions(new SocketOptions()
+ .setConnectTimeoutMillis(MusicUtil.getCassandraConnectTimeOutMS())
+ .setReadTimeoutMillis(MusicUtil.getCassandraReadTimeOutMS()))
+ .addContactPoints(addresses)
+ .build();
+ }
+
+ this.setCluster(cluster);
+ Metadata metadata = this.cluster.getMetadata();
+ logger.info(EELFLoggerDelegate.applicationLogger, "Connected to cassa cluster "
+ + metadata.getClusterName() + " at " + address);
+
+ try {
+ session = this.cluster.connect();
+ } catch (Exception ex) {
+ logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.CASSANDRACONNECTIVITY,
+ ErrorSeverity.ERROR, ErrorTypes.SERVICEUNAVAILABLE, ex);
+ throw new MusicServiceException(
+ "Error while connecting to Cassandra cluster.. " + ex.getMessage());
+ }
+ }
+
+ /**
+ *
+ * @param keyspace
+ * @param tableName
+ * @param columnName
+ * @return DataType
+ */
+ public DataType returnColumnDataType(String keyspace, String tableName, String columnName) {
+ KeyspaceMetadata ks = cluster.getMetadata().getKeyspace(keyspace);
+ TableMetadata table = ks.getTable(tableName);
+ return table.getColumn(columnName).getType();
+
+ }
+
+ /**
+ *
+ * @param keyspace
+ * @param tableName
+ * @return TableMetadata
+ */
+ public TableMetadata returnColumnMetadata(String keyspace, String tableName) {
+ KeyspaceMetadata ks = cluster.getMetadata().getKeyspace(keyspace);
+ return ks.getTable(tableName);
+ }
+
+ /**
+ *
+ * @param keyspace
+ * @param tableName
+ * @return TableMetadata
+ */
+ public KeyspaceMetadata returnKeyspaceMetadata(String keyspace) {
+ return cluster.getMetadata().getKeyspace(keyspace);
+ }
+
+
+ /**
+ * Utility function to return the Java specific object type.
+ *
+ * @param row
+ * @param colName
+ * @param colType
+ * @return
+ */
+ public Object getColValue(Row row, String colName, DataType colType) {
+
+ switch (colType.getName()) {
+ case VARCHAR:
+ return row.getString(colName);
+ case UUID:
+ return row.getUUID(colName);
+ case VARINT:
+ return row.getVarint(colName);
+ case BIGINT:
+ return row.getLong(colName);
+ case INT:
+ return row.getInt(colName);
+ case FLOAT:
+ return row.getFloat(colName);
+ case DOUBLE:
+ return row.getDouble(colName);
+ case BOOLEAN:
+ return row.getBool(colName);
+ case MAP:
+ return row.getMap(colName, String.class, String.class);
+ case LIST:
+ return row.getList(colName, String.class);
+ default:
+ return null;
+ }
+ }
+
+ public byte[] getBlobValue(Row row, String colName, DataType colType) {
+ ByteBuffer bb = row.getBytes(colName);
+ return bb.array();
+ }
+
+ public boolean doesRowSatisfyCondition(Row row, Map<String, Object> condition) throws Exception {
+ ColumnDefinitions colInfo = row.getColumnDefinitions();
+
+ for (Map.Entry<String, Object> entry : condition.entrySet()) {
+ String colName = entry.getKey();
+ DataType colType = colInfo.getType(colName);
+ Object columnValue = getColValue(row, colName, colType);
+ Object conditionValue = MusicUtil.convertToActualDataType(colType, entry.getValue());
+ if (columnValue.equals(conditionValue) == false)
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Utility function to store ResultSet values in to a MAP for output.
+ *
+ * @param results
+ * @return MAP
+ */
+ public Map<String, HashMap<String, Object>> marshalData(ResultSet results) {
+ Map<String, HashMap<String, Object>> resultMap =
+ new HashMap<>();
+ int counter = 0;
+ for (Row row : results) {
+ ColumnDefinitions colInfo = row.getColumnDefinitions();
+ HashMap<String, Object> resultOutput = new HashMap<>();
+ for (Definition definition : colInfo) {
+ if (!(("vector_ts").equals(definition.getName()))) {
+ if(definition.getType().toString().toLowerCase().contains("blob")) {
+ resultOutput.put(definition.getName(),
+ getBlobValue(row, definition.getName(), definition.getType()));
+ } else {
+ resultOutput.put(definition.getName(),
+ getColValue(row, definition.getName(), definition.getType()));
+ }
+ }
+ }
+ resultMap.put("row " + counter, resultOutput);
+ counter++;
+ }
+ return resultMap;
+ }
+
+
+ // Prepared Statements 1802 additions
+
+ public boolean executePut(PreparedQueryObject queryObject, String consistency)
+ throws MusicServiceException, MusicQueryException {
+ return executePut(queryObject, consistency, 0);
+ }
+ /**
+ * This Method performs DDL and DML operations on Cassandra using specified consistency level
+ *
+ * @param queryObject Object containing cassandra prepared query and values.
+ * @param consistency Specify consistency level for data synchronization across cassandra
+ * replicas
+ * @return Boolean Indicates operation success or failure
+ * @throws MusicServiceException
+ * @throws MusicQueryException
+ */
+ public boolean executePut(PreparedQueryObject queryObject, String consistency,long timeSlot)
+ throws MusicServiceException, MusicQueryException {
+
+ boolean result = false;
+ long timeOfWrite = System.currentTimeMillis();
+ if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) {
+ logger.error(EELFLoggerDelegate.errorLogger, queryObject.getQuery(),AppMessages.QUERYERROR, ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
+ throw new MusicQueryException("Ill formed queryObject for the request = " + "["
+ + queryObject.getQuery() + "]");
+ }
+ logger.debug(EELFLoggerDelegate.applicationLogger,
+ "In preprared Execute Put: the actual insert query:"
+ + queryObject.getQuery() + "; the values"
+ + queryObject.getValues());
+ SimpleStatement preparedInsert = null;
+
+ try {
+ preparedInsert = new SimpleStatement(queryObject.getQuery(), queryObject.getValues().toArray());
+ if (consistency.equalsIgnoreCase(MusicUtil.CRITICAL)) {
+ logger.info(EELFLoggerDelegate.applicationLogger, "Executing critical put query");
+ preparedInsert.setConsistencyLevel(ConsistencyLevel.QUORUM);
+ } else if (consistency.equalsIgnoreCase(MusicUtil.EVENTUAL)) {
+ logger.info(EELFLoggerDelegate.applicationLogger, "Executing simple put query");
+ if(queryObject.getConsistency() == null)
+ preparedInsert.setConsistencyLevel(ConsistencyLevel.ONE);
+ else
+ preparedInsert.setConsistencyLevel(MusicUtil.getConsistencyLevel(queryObject.getConsistency()));
+ } else if (consistency.equalsIgnoreCase(MusicUtil.ONE)) {
+ preparedInsert.setConsistencyLevel(ConsistencyLevel.ONE);
+ } else if (consistency.equalsIgnoreCase(MusicUtil.QUORUM)) {
+ preparedInsert.setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM);
+ } else if (consistency.equalsIgnoreCase(MusicUtil.ALL)) {
+ preparedInsert.setConsistencyLevel(ConsistencyLevel.ALL);
+ }
+ long timestamp = MusicUtil.v2sTimeStampInMicroseconds(timeSlot, timeOfWrite);
+ preparedInsert.setDefaultTimestamp(timestamp);
+
+ ResultSet rs = session.execute(preparedInsert);
+ result = rs.wasApplied();
+ } catch (AlreadyExistsException ae) {
+ throw new MusicServiceException("Already Exists Exception: " + ae.getMessage());
+ } catch (InvalidQueryException e) {
+ if (e.getMessage().contains("unconfigured table")) {
+ throw new MusicServiceException("Invalid Query Exception: " + e.getMessage());
+ } else {
+ logger.info(EELFLoggerDelegate.applicationLogger, "Query Exception: " + e.getMessage(),
+ AppMessages.SESSIONFAILED + " [" + queryObject.getQuery() + "]", ErrorSeverity.INFO,
+ ErrorTypes.QUERYERROR, e);
+ throw new MusicServiceException("Query Exception: " + e.getMessage());
+ }
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),
+ AppMessages.SESSIONFAILED + " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR,
+ ErrorTypes.QUERYERROR, e);
+ throw new MusicServiceException("Executing Session Failure for Request = " + "[" + queryObject.getQuery()
+ + "]" + " Reason = " + e.getMessage());
+ }
+
+ return result;
+ }
+
+ /* *//**
+ * This method performs DDL operations on Cassandra using consistency level ONE.
+ *
+ * @param queryObject Object containing cassandra prepared query and values.
+ * @return ResultSet
+ * @throws MusicServiceException
+ * @throws MusicQueryException
+ *//*
+ public ResultSet executeEventualGet(PreparedQueryObject queryObject)
+ throws MusicServiceException, MusicQueryException {
+ CacheAccess<String, PreparedStatement> queryBank = CachingUtil.getStatementBank();
+ PreparedStatement preparedEventualGet = null;
+ if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) {
+ logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
+ throw new MusicQueryException("Ill formed queryObject for the request = " + "["
+ + queryObject.getQuery() + "]");
+ }
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "Executing Eventual get query:" + queryObject.getQuery());
+
+ ResultSet results = null;
+ try {
+ if(queryBank.get(queryObject.getQuery()) != null )
+ preparedEventualGet=queryBank.get(queryObject.getQuery());
+ else {
+ preparedEventualGet = session.prepare(queryObject.getQuery());
+ CachingUtil.updateStatementBank(queryObject.getQuery(), preparedEventualGet);
+ }
+ if(queryObject.getConsistency() == null) {
+ preparedEventualGet.setConsistencyLevel(ConsistencyLevel.ONE);
+ } else {
+ preparedEventualGet.setConsistencyLevel(MusicUtil.getConsistencyLevel(queryObject.getConsistency()));
+ }
+ results = session.execute(preparedEventualGet.bind(queryObject.getValues().toArray()));
+
+ } catch (Exception ex) {
+ logger.error("Exception", ex);
+ logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
+ throw new MusicServiceException(ex.getMessage());
+ }
+ return results;
+ }
+
+ *//**
+ *
+ * This method performs DDL operation on Cassandra using consistency level QUORUM.
+ *
+ * @param queryObject Object containing cassandra prepared query and values.
+ * @return ResultSet
+ * @throws MusicServiceException
+ * @throws MusicQueryException
+ *//*
+ public ResultSet executeCriticalGet(PreparedQueryObject queryObject)
+ throws MusicServiceException, MusicQueryException {
+ if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) {
+ logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
+ throw new MusicQueryException("Error processing Prepared Query Object for the request = " + "["
+ + queryObject.getQuery() + "]");
+ }
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "Executing Critical get query:" + queryObject.getQuery());
+ PreparedStatement preparedEventualGet = session.prepare(queryObject.getQuery());
+ preparedEventualGet.setConsistencyLevel(ConsistencyLevel.QUORUM);
+ ResultSet results = null;
+ try {
+ results = session.execute(preparedEventualGet.bind(queryObject.getValues().toArray()));
+ } catch (Exception ex) {
+ logger.error("Exception", ex);
+ logger.error(EELFLoggerDelegate.errorLogger, ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
+ throw new MusicServiceException(ex.getMessage());
+ }
+ return results;
+
+ }
+ */
+ public ResultSet executeGet(PreparedQueryObject queryObject,String consistencyLevel) throws MusicQueryException, MusicServiceException {
+ if (!MusicUtil.isValidQueryObject(!queryObject.getValues().isEmpty(), queryObject)) {
+ logger.error(EELFLoggerDelegate.errorLogger, "",AppMessages.QUERYERROR+ " [" + queryObject.getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR);
+ throw new MusicQueryException("Error processing Prepared Query Object for the request = " + "["
+ + queryObject.getQuery() + "]");
+ }
+ ResultSet results = null;
+ try {
+ SimpleStatement statement = new SimpleStatement(queryObject.getQuery(), queryObject.getValues().toArray());
+ if (consistencyLevel.equalsIgnoreCase(CONSISTENCY_LEVEL_ONE)) {
+ statement.setConsistencyLevel(ConsistencyLevel.ONE);
+ } else if (consistencyLevel.equalsIgnoreCase(CONSISTENCY_LEVEL_QUORUM)) {
+ statement.setConsistencyLevel(ConsistencyLevel.QUORUM);
+ } else if (consistencyLevel.equalsIgnoreCase(CONSISTENCY_LEVEL_LOCAL_QUORUM)) {
+ statement.setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM);
+ }
+
+ results = session.execute(statement);
+
+ } catch (Exception ex) {
+ logger.error(EELFLoggerDelegate.errorLogger, "Execute Get Error" + ex.getMessage(),AppMessages.UNKNOWNERROR+ "[" + queryObject
+ .getQuery() + "]", ErrorSeverity.ERROR, ErrorTypes.QUERYERROR, ex);
+ throw new MusicServiceException("Execute Get Error" + ex.getMessage());
+ }
+
+ return results;
+
+ }
+
+ /**
+ * This method performs DDL operations on Cassandra using consistency level ONE.
+ *
+ * @param queryObject Object containing cassandra prepared query and values.
+ */
+ public ResultSet executeOneConsistencyGet(PreparedQueryObject queryObject)
+ throws MusicServiceException, MusicQueryException {
+ return executeGet(queryObject, CONSISTENCY_LEVEL_ONE);
+ }
+
+ /**
+ *
+ * This method performs DDL operation on Cassandra using consistency level LOCAL_QUORUM.
+ *
+ * @param queryObject Object containing cassandra prepared query and values.
+ */
+ public ResultSet executeLocalQuorumConsistencyGet(PreparedQueryObject queryObject)
+ throws MusicServiceException, MusicQueryException {
+ return executeGet(queryObject, CONSISTENCY_LEVEL_LOCAL_QUORUM);
+ }
+
+ /**
+ *
+ * This method performs DDL operation on Cassandra using consistency level QUORUM.
+ *
+ * @param queryObject Object containing cassandra prepared query and values.
+ */
+ public ResultSet executeQuorumConsistencyGet(PreparedQueryObject queryObject)
+ throws MusicServiceException, MusicQueryException {
+ return executeGet(queryObject, CONSISTENCY_LEVEL_QUORUM);
+ }
+
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java b/music-core/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java
new file mode 100644
index 00000000..09fe0d35
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/MusicDataStoreHandle.java
@@ -0,0 +1,127 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * Modifications Copyright (C) 2019 IBM.
+ * ===================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.exceptions.MusicServiceException;
+import org.onap.music.main.MusicUtil;
+
+import com.datastax.driver.core.KeyspaceMetadata;
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.TableMetadata;
+
+public class MusicDataStoreHandle {
+
+ private static MusicDataStore mDstoreHandle = null;
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicDataStoreHandle.class);
+
+ private MusicDataStoreHandle(){
+ throw new IllegalStateException("Utility class");
+ }
+
+ /**
+ *
+ * @param remoteIp
+ * @return
+ */
+ public static MusicDataStore getDSHandle(String remoteIp) {
+ logger.info(EELFLoggerDelegate.metricsLogger,"Acquiring data store handle");
+ long start = System.currentTimeMillis();
+ if (mDstoreHandle == null) {
+ mDstoreHandle = new MusicDataStore(remoteIp);
+ }
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.metricsLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
+ return mDstoreHandle;
+ }
+
+ /**
+ *
+ * @return
+ * @throws MusicServiceException
+ */
+ public static MusicDataStore getDSHandle() throws MusicServiceException {
+ logger.info(EELFLoggerDelegate.metricsLogger,"Acquiring data store handle");
+ long start = System.currentTimeMillis();
+ if (mDstoreHandle == null) {
+ // Quick Fix - Best to put this into every call to getDSHandle?
+ if (!"localhost".equals(MusicUtil.getMyCassaHost())) {
+ mDstoreHandle = new MusicDataStore(MusicUtil.getMyCassaHost());
+ } else {
+ mDstoreHandle = new MusicDataStore();
+ }
+ }
+ if(mDstoreHandle.getSession() == null) {
+ String message = "Connection to Cassandra has not been enstablished."
+ + " Please check connection properites and reboot.";
+ logger.info(EELFLoggerDelegate.applicationLogger, message);
+ throw new MusicServiceException(message);
+ }
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.metricsLogger,"Time taken to acquire data store handle:" + (end - start) + " ms");
+ return mDstoreHandle;
+ }
+
+ public static void setMDstoreHandle(MusicDataStore dsHandle) {
+ mDstoreHandle = dsHandle;
+ }
+
+ /**
+ *
+ * @param keyspace
+ * @param tablename
+ * @return
+ * @throws MusicServiceException
+ */
+ public static TableMetadata returnColumnMetadata(String keyspace, String tablename) throws MusicServiceException {
+ return getDSHandle().returnColumnMetadata(keyspace, tablename);
+ }
+
+ /**
+ *
+ * @param keyspace
+ * @param tablename
+ * @return
+ * @throws MusicServiceException
+ */
+ public static KeyspaceMetadata returnkeyspaceMetadata(String keyspace) throws MusicServiceException {
+ return getDSHandle().returnKeyspaceMetadata(keyspace);
+ }
+
+ /**
+ *
+ * @param results
+ * @return
+ * @throws MusicServiceException
+ */
+ public static Map<String, HashMap<String, Object>> marshallResults(ResultSet results) throws MusicServiceException {
+ return getDSHandle().marshalData(results);
+ }
+
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/PreparedQueryObject.java b/music-core/src/main/java/org/onap/music/datastore/PreparedQueryObject.java
new file mode 100644
index 00000000..fdac50be
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/PreparedQueryObject.java
@@ -0,0 +1,176 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017-2019 AT&T Intellectual Property
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author srupane
+ *
+ */
+public class PreparedQueryObject {
+
+
+ private List<Object> values;
+ private StringBuilder query;
+ private String consistency;
+ private String keyspaceName;
+ private String tableName;
+ private String operation;
+ private String primaryKeyValue;
+
+
+ /**
+ * Create PreparedQueryObject
+ */
+ public PreparedQueryObject() {
+ this.values = new ArrayList<>();
+ this.query = new StringBuilder();
+ }
+
+ /**
+ * Create PreparedQueryObject
+ * @param query query portion of the prepared query
+ */
+ public PreparedQueryObject(String query) {
+ this.values = new ArrayList<>();
+ this.query = new StringBuilder(query);
+ }
+
+ /**
+ * Create PreparedQueryObject
+ * @param query query portion of the prepared query
+ * @param values to be added to the query string as prepared query
+ */
+ public PreparedQueryObject(String query, Object...values) {
+ this.query = new StringBuilder(query);
+ this.values = new ArrayList<>();
+ for (Object value: values) {
+ this.values.add(value);
+ }
+ }
+
+ public String getKeyspaceName() {
+ return keyspaceName;
+ }
+
+ public void setKeyspaceName(String keyspaceName) {
+ this.keyspaceName = keyspaceName;
+ }
+
+ public String getTableName() {
+ return tableName;
+ }
+
+ public void setTableName(String tableName) {
+ this.tableName = tableName;
+ }
+
+ public String getOperation() {
+ if (operation!=null) return operation;
+ if (query.length()==0) return null;
+ String queryStr = query.toString().toLowerCase();
+ String firstOp = null;
+ int firstOpChar = query.length();
+ if (queryStr.indexOf("insert")>-1 && queryStr.indexOf("insert")<firstOpChar) {
+ firstOp = "insert";
+ firstOpChar = queryStr.indexOf("insert");
+ }
+ if (queryStr.indexOf("update")>-1 && queryStr.indexOf("update")<firstOpChar) {
+ firstOp = "update";
+ firstOpChar = queryStr.indexOf("update");
+ }
+ if (queryStr.indexOf("delete")>-1 && queryStr.indexOf("delete")<firstOpChar) {
+ firstOp = "delete";
+ firstOpChar = queryStr.indexOf("delete");
+ }
+ if (queryStr.indexOf("select")>-1 && queryStr.indexOf("select")<firstOpChar) {
+ firstOp = "select";
+ firstOpChar = queryStr.indexOf("select");
+ }
+ return firstOp;
+ }
+
+ public void setOperation(String operation) {
+ this.operation = operation;
+ }
+
+ public String getPrimaryKeyValue() {
+ return primaryKeyValue;
+ }
+
+ public void setPrimaryKeyValue(String primaryKeyValue) {
+ this.primaryKeyValue = primaryKeyValue;
+ }
+
+ public String getConsistency() {
+ return consistency;
+ }
+
+ public void setConsistency(String consistency) {
+ this.consistency = consistency;
+ }
+
+ /**
+ * @return values to be set as part of the prepared query
+ */
+ public List<Object> getValues() {
+ return values;
+ }
+
+ /**
+ * @param o object to be added as a value to the prepared query, in order
+ */
+ public void addValue(Object o) {
+ this.values.add(o);
+ }
+
+ /**
+ * Add values to the preparedQuery
+ * @param objs ordered list of objects to be added as values to the prepared query
+ */
+ public void addValues(Object... objs) {
+ for (Object obj: objs) {
+ this.values.add(obj);
+ }
+ }
+
+ /**
+ * @param s
+ */
+ public void appendQueryString(String s) {
+ this.query.append(s);
+ }
+ public void replaceQueryString(String s) {
+ this.query.replace(0, query.length(), s);
+ }
+
+ /**
+ * @return the query
+ */
+ public String getQuery() {
+ return this.query.toString();
+ }
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JSONObject.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JSONObject.java
new file mode 100644
index 00000000..a1524cc6
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JSONObject.java
@@ -0,0 +1,37 @@
+package org.onap.music.datastore.jsonobjects;
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+
+public class JSONObject {
+
+ private String data;
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java
new file mode 100644
index 00000000..988ba3a8
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonDelete.java
@@ -0,0 +1,313 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * ===================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ===================================================================
+ * Modifications Copyright (C) 2019 IBM
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore.jsonobjects;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.music.datastore.Condition;
+import org.onap.music.datastore.MusicDataStoreHandle;
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.eelf.logging.format.AppMessages;
+import org.onap.music.eelf.logging.format.ErrorSeverity;
+import org.onap.music.eelf.logging.format.ErrorTypes;
+import org.onap.music.exceptions.MusicQueryException;
+import org.onap.music.exceptions.MusicServiceException;
+import org.onap.music.main.MusicUtil;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.TableMetadata;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel(value = "JsonTable", description = "Json model for delete")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class JsonDelete {
+
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonDelete.class);
+
+ private List<String> columns = null;
+ private Map<String, String> consistencyInfo;
+ private Map<String, Object> conditions;
+ private String ttl;
+ private String timestamp;
+ private String keyspaceName;
+ private String tableName;
+ private StringBuilder rowIdString;
+ private String primarKeyValue;
+
+
+ @ApiModelProperty(value = "Conditions")
+ public Map<String, Object> getConditions() {
+ return conditions;
+ }
+
+ public void setConditions(Map<String, Object> conditions) {
+ this.conditions = conditions;
+ }
+
+ @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic")
+ public Map<String, String> getConsistencyInfo() {
+ return consistencyInfo;
+ }
+
+ public void setConsistencyInfo(Map<String, String> consistencyInfo) {
+ this.consistencyInfo = consistencyInfo;
+ }
+
+ @ApiModelProperty(value = "Column values")
+ public List<String> getColumns() {
+ return columns;
+ }
+
+ public void setColumns(List<String> columns) {
+ this.columns = columns;
+ }
+
+
+ @ApiModelProperty(value = "Time to live information")
+ public String getTtl() {
+ return ttl;
+ }
+
+ public void setTtl(String ttl) {
+ this.ttl = ttl;
+ }
+
+ @ApiModelProperty(value = "Time stamp")
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(String timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public String getKeyspaceName() {
+ return keyspaceName;
+ }
+
+ public void setKeyspaceName(String keyspaceName) {
+ this.keyspaceName = keyspaceName;
+ }
+
+ public String getTableName() {
+ return tableName;
+ }
+
+ public void setTableName(String tableName) {
+ this.tableName = tableName;
+ }
+
+ public StringBuilder getRowIdString() {
+ return rowIdString;
+ }
+
+ public void setRowIdString(StringBuilder rowIdString) {
+ this.rowIdString = rowIdString;
+ }
+
+ public String getPrimarKeyValue() {
+ return primarKeyValue;
+ }
+
+ public void setPrimarKeyValue(String primarKeyValue) {
+ this.primarKeyValue = primarKeyValue;
+ }
+
+
+ public PreparedQueryObject genDeletePreparedQueryObj(MultivaluedMap<String, String> rowParams) throws MusicQueryException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Coming inside genUpdatePreparedQueryObj method " + this.getKeyspaceName());
+ logger.debug("Coming inside genUpdatePreparedQueryObj method " + this.getTableName());
+ }
+
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+
+ if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty())
+ || (this.getTableName() == null || this.getTableName().isEmpty())){
+
+
+ throw new MusicQueryException("one or more path parameters are not set, please check and try again",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+
+ EELFLoggerDelegate.mdcPut("keyspace", "( "+this.getKeyspaceName()+" ) ");
+
+ if(this == null) {
+ logger.error(EELFLoggerDelegate.errorLogger,"Required HTTP Request body is missing.", AppMessages.MISSINGDATA ,ErrorSeverity.WARN, ErrorTypes.DATAERROR);
+
+ throw new MusicQueryException("Required HTTP Request body is missing.",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+ StringBuilder columnString = new StringBuilder();
+
+ int counter = 0;
+ List<String> columnList = this.getColumns();
+ if (columnList != null) {
+ for (String column : columnList) {
+ columnString.append(column);
+ if (counter != columnList.size() - 1)
+ columnString.append(",");
+ counter = counter + 1;
+ }
+ }
+
+ // get the row specifier
+ RowIdentifier rowId = null;
+ try {
+ rowId = getRowIdentifier(this.getKeyspaceName(), this.getTableName(), rowParams, queryObject);
+ this.setRowIdString(rowId.rowIdString);
+ this.setPrimarKeyValue(rowId.primarKeyValue);
+ if(rowId == null || rowId.primarKeyValue.isEmpty()) {
+
+ throw new MusicQueryException("Mandatory WHERE clause is missing. Please check the input request.",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+ } catch (MusicServiceException ex) {
+ logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes
+ .GENERALSERVICEERROR, ex);
+ /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();*/
+ throw new MusicQueryException(AppMessages.UNKNOWNERROR.toString(), Status.BAD_REQUEST.getStatusCode());
+ }
+ String rowSpec = rowId.rowIdString.toString();
+
+ if ((columnList != null) && (!rowSpec.isEmpty())) {
+ queryObject.appendQueryString("DELETE " + columnString + " FROM " + this.getKeyspaceName() + "."
+ + this.getTableName() + " WHERE " + rowSpec + ";");
+ }
+
+ if ((columnList == null) && (!rowSpec.isEmpty())) {
+ queryObject.appendQueryString("DELETE FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE "
+ + rowSpec + ";");
+ }
+
+ if ((columnList != null) && (rowSpec.isEmpty())) {
+ queryObject.appendQueryString(
+ "DELETE " + columnString + " FROM " + this.getKeyspaceName() + "." + rowSpec + ";");
+ }
+ // get the conditional, if any
+ Condition conditionInfo;
+ if (this.getConditions() == null) {
+ conditionInfo = null;
+ } else {
+ // to avoid parsing repeatedly, just send the select query to
+ // obtain row
+ PreparedQueryObject selectQuery = new PreparedQueryObject();
+ selectQuery.appendQueryString("SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE "
+ + rowId.rowIdString + ";");
+ selectQuery.addValue(rowId.primarKeyValue);
+ conditionInfo = new Condition(this.getConditions(), selectQuery);
+ }
+
+ String consistency = this.getConsistencyInfo().get("type");
+
+
+ if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency")!=null) {
+ if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) {
+ queryObject.setConsistency(this.getConsistencyInfo().get("consistency"));
+ } else {
+ throw new MusicQueryException("Invalid Consistency type", Status.BAD_REQUEST.getStatusCode());
+ }
+ }
+
+ queryObject.setOperation("delete");
+
+ return queryObject;
+ }
+
+
+ /**
+ *
+ * @param keyspace
+ * @param tablename
+ * @param rowParams
+ * @param queryObject
+ * @return
+ * @throws MusicServiceException
+ */
+ private RowIdentifier getRowIdentifier(String keyspace, String tablename,
+ MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
+ throws MusicServiceException {
+ StringBuilder rowSpec = new StringBuilder();
+ int counter = 0;
+ TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
+ if (tableInfo == null) {
+ logger.error(EELFLoggerDelegate.errorLogger,
+ "Table information not found. Please check input for table name= "
+ + keyspace + "." + tablename);
+ throw new MusicServiceException(
+ "Table information not found. Please check input for table name= "
+ + keyspace + "." + tablename);
+ }
+ StringBuilder primaryKey = new StringBuilder();
+ for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
+ String keyName = entry.getKey();
+ List<String> valueList = entry.getValue();
+ String indValue = valueList.get(0);
+ DataType colType = null;
+ Object formattedValue = null;
+ try {
+ colType = tableInfo.getColumn(entry.getKey()).getType();
+ formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e);
+ }
+ if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) {
+ primaryKey.append(indValue);
+ }
+ rowSpec.append(keyName + "= ?");
+ queryObject.addValue(formattedValue);
+ if (counter != rowParams.size() - 1) {
+ rowSpec.append(" AND ");
+ }
+ counter = counter + 1;
+ }
+ return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);
+ }
+
+ private class RowIdentifier {
+ private String primarKeyValue;
+ private StringBuilder rowIdString;
+ @SuppressWarnings("unused")
+ public PreparedQueryObject queryObject; // the string with all the row
+ // identifiers separated by AND
+
+ public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
+ PreparedQueryObject queryObject) {
+ this.primarKeyValue = primaryKeyValue;
+ this.rowIdString = rowIdString;
+ this.queryObject = queryObject;
+ }
+ }
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonIndex.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonIndex.java
new file mode 100644
index 00000000..a06e8ea9
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonIndex.java
@@ -0,0 +1,120 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * ===================================================================
+ * Modifications Copyright (c) 2019 IBM
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+package org.onap.music.datastore.jsonobjects;
+
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@ApiModel(value = "JsonIndex", description = "Index Object")
+public class JsonIndex {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonIndex.class);
+
+ private String indexName;
+ private String keyspaceName;
+ private String tableName;
+ private String fieldName;
+
+ public JsonIndex(String indexName,String keyspaceName,String tableName,String fieldName) {
+ this.indexName = indexName;
+ this.keyspaceName= keyspaceName;
+ this.tableName = tableName;
+ this.fieldName = fieldName;
+ }
+
+ @ApiModelProperty(value = "Index Name")
+ public String getIndexName() {
+ return indexName;
+ }
+
+ public JsonIndex setIndexName(String indexName) {
+ this.indexName = indexName;
+ return this;
+ }
+
+ @ApiModelProperty(value = "Keyspace name")
+ public String getKeyspaceName() {
+ return keyspaceName;
+ }
+
+ public JsonIndex setKeyspaceName(String keyspaceName) {
+ this.keyspaceName = keyspaceName;
+ return this;
+ }
+
+ public JsonIndex setTableName(String tableName) {
+ this.tableName = tableName;
+ return this;
+ }
+
+ @ApiModelProperty(value = "Table name")
+ public String getTableName() {
+ return tableName;
+ }
+
+ public JsonIndex setFieldName(String fieldName) {
+ this.fieldName = fieldName;
+ return this;
+ }
+
+ @ApiModelProperty(value = "Field name")
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ public PreparedQueryObject genCreateIndexQuery() {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Came inside genCreateIndexQuery method");
+ }
+
+ logger.info("genCreateIndexQuery indexName ::" + indexName);
+ logger.info("genCreateIndexQuery keyspaceName ::" + keyspaceName);
+ logger.info("genCreateIndexQuery tableName ::" + tableName);
+ logger.info("genCreateIndexQuery fieldName ::" + fieldName);
+
+ long start = System.currentTimeMillis();
+
+ PreparedQueryObject query = new PreparedQueryObject();
+ query.appendQueryString("Create index if not exists " + this.getIndexName() + " on " + this.getKeyspaceName() + "."
+ + this.getTableName() + " (" + this.getFieldName() + ");");
+
+ long end = System.currentTimeMillis();
+
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "Time taken for setting up query in create index:" + (end - start));
+
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ " create index query :" + query.getQuery());
+
+ return query;
+ }
+
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java
new file mode 100644
index 00000000..2f685cfe
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonInsert.java
@@ -0,0 +1,415 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * Modifications Copyright (C) 2019 IBM
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore.jsonobjects;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.music.datastore.MusicDataStoreHandle;
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.eelf.logging.format.AppMessages;
+import org.onap.music.eelf.logging.format.ErrorSeverity;
+import org.onap.music.eelf.logging.format.ErrorTypes;
+import org.onap.music.exceptions.MusicQueryException;
+import org.onap.music.exceptions.MusicServiceException;
+import org.onap.music.main.MusicUtil;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.TableMetadata;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel(value = "InsertTable", description = "Json model for table vlaues insert")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class JsonInsert implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private String keyspaceName;
+ private String tableName;
+ private transient Map<String, Object> values;
+ private String ttl;
+ private String timestamp;
+ private transient Map<String, Object> rowSpecification;
+ private Map<String, String> consistencyInfo;
+ private Map<String, byte[]> objectMap;
+ private String primaryKeyVal;
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonInsert.class);
+
+ @ApiModelProperty(value = "objectMap",hidden = true)
+ public Map<String, byte[]> getObjectMap() {
+ return objectMap;
+ }
+
+ public void setObjectMap(Map<String, byte[]> objectMap) {
+ this.objectMap = objectMap;
+ }
+
+ @ApiModelProperty(value = "keyspace")
+ public String getKeyspaceName() {
+ return keyspaceName;
+ }
+
+ public void setKeyspaceName(String keyspaceName) {
+ this.keyspaceName = keyspaceName;
+ }
+
+ @ApiModelProperty(value = "Table name")
+ public String getTableName() {
+ return tableName;
+ }
+
+ public void setTableName(String tableName) {
+ this.tableName = tableName;
+ }
+
+ @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic")
+ public Map<String, String> getConsistencyInfo() {
+ return consistencyInfo;
+ }
+
+ public void setConsistencyInfo(Map<String, String> consistencyInfo) {
+ this.consistencyInfo = consistencyInfo;
+ }
+
+ @ApiModelProperty(value = "Columns and tables support an optional "
+ + "expiration period called TTL (time-to-live) in seconds.",
+ notes="TTL precision is one second, which is calculated by the coordinator "
+ + "node. When using TTL, ensure that all nodes in the cluster have synchronized clocks.",allowEmptyValue = true)
+ public String getTtl() {
+ return ttl;
+ }
+
+ public void setTtl(String ttl) {
+ this.ttl = ttl;
+ }
+
+ @ApiModelProperty(value = "Time stamp (epoch_in_microseconds)",
+ notes = "Marks inserted data (write time) with TIMESTAMP. "
+ + "Enter the time since epoch (January 1, 1970) in microseconds."
+ + "By default, the actual time of write is used.", allowEmptyValue = true)
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(String timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ @ApiModelProperty(value = "Json Object of key/values", notes="Where key is the column name and value is the data value for that column.",
+ example = "{'emp_id': 'df98a3d40cd6','emp_name': 'john',"
+ + "'emp_salary': 50,'address':{'street' : '1 Some way','city' : 'New York'}}")
+ public Map<String, Object> getValues() {
+ return values;
+ }
+
+ public void setValues(Map<String, Object> values) {
+ this.values = values;
+ }
+
+ @ApiModelProperty(value = "Information for selecting specific rows for insert",hidden = true)
+ public Map<String, Object> getRowSpecification() {
+ return rowSpecification;
+ }
+
+ public void setRowSpecification(Map<String, Object> rowSpecification) {
+ this.rowSpecification = rowSpecification;
+ }
+
+ public String getPrimaryKeyVal() {
+ return primaryKeyVal;
+ }
+
+ public void setPrimaryKeyVal(String primaryKeyVal) {
+ this.primaryKeyVal = primaryKeyVal;
+ }
+
+ public byte[] serialize() {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutput out = null;
+ try {
+ out = new ObjectOutputStream(bos);
+ out.writeObject(this);
+ } catch (IOException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.DATAERROR);
+ }
+ return bos.toByteArray();
+ }
+
+ /**
+ * Generate TableInsertQuery
+ * @return
+ * @throws MusicQueryException
+ */
+ public PreparedQueryObject genInsertPreparedQueryObj() throws MusicQueryException {
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+ TableMetadata tableInfo = null;
+ try {
+ tableInfo = MusicDataStoreHandle.returnColumnMetadata(this.getKeyspaceName(), this.getTableName());
+ if(tableInfo == null) {
+ throw new MusicQueryException("Table name doesn't exists. Please check the table name.",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+ } catch (MusicServiceException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
+ throw new MusicQueryException(e.getMessage(),Status.BAD_REQUEST.getStatusCode());
+
+ }
+ String primaryKeyName = tableInfo.getPrimaryKey().get(0).getName();
+ StringBuilder fieldsString = new StringBuilder("(vector_ts,");
+ String vectorTs =
+ String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
+ StringBuilder valueString = new StringBuilder("(" + "?" + ",");
+ queryObject.addValue(vectorTs);
+
+ Map<String, Object> valuesMap = this.getValues();
+ if (valuesMap==null) {
+ throw new MusicQueryException("Nothing to insert. No values provided in request.",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+ int counter = 0;
+ String primaryKey = "";
+ for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
+ fieldsString.append("" + entry.getKey());
+ Object valueObj = entry.getValue();
+ if (primaryKeyName.equals(entry.getKey())) {
+ primaryKey = entry.getValue() + "";
+ primaryKey = primaryKey.replace("'", "''");
+ }
+ DataType colType = null;
+ try {
+ colType = tableInfo.getColumn(entry.getKey()).getType();
+ } catch(NullPointerException ex) {
+ logger.error(EELFLoggerDelegate.errorLogger,ex.getMessage() +" Invalid column name : "+entry.getKey
+ (), AppMessages.INCORRECTDATA ,ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR, ex);
+ throw new MusicQueryException("Invalid column name : " + entry.getKey(),
+ Status.BAD_REQUEST.getStatusCode());
+ }
+
+ Object formattedValue = null;
+ try {
+ formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e);
+ }
+ valueString.append("?");
+
+ queryObject.addValue(formattedValue);
+
+ if (counter == valuesMap.size() - 1) {
+ fieldsString.append(")");
+ valueString.append(")");
+ } else {
+ fieldsString.append(",");
+ valueString.append(",");
+ }
+ counter = counter + 1;
+ }
+
+ //blobs..
+ Map<String, byte[]> objectMap = this.getObjectMap();
+ if(objectMap != null) {
+ for (Map.Entry<String, byte[]> entry : objectMap.entrySet()) {
+ if(counter > 0) {
+ fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ",");
+ valueString.replace(valueString.length()-1, valueString.length(), ",");
+ }
+ fieldsString.append("" + entry.getKey());
+ byte[] valueObj = entry.getValue();
+ if (primaryKeyName.equals(entry.getKey())) {
+ primaryKey = entry.getValue() + "";
+ primaryKey = primaryKey.replace("'", "''");
+ }
+ DataType colType = tableInfo.getColumn(entry.getKey()).getType();
+ ByteBuffer formattedValue = null;
+ if(colType.toString().toLowerCase().contains("blob")) {
+ formattedValue = MusicUtil.convertToActualDataType(colType, valueObj);
+ }
+ valueString.append("?");
+ queryObject.addValue(formattedValue);
+ counter = counter + 1;
+ fieldsString.append(",");
+ valueString.append(",");
+ }
+ }
+ this.setPrimaryKeyVal(primaryKey);
+ if(primaryKey == null || primaryKey.length() <= 0) {
+ logger.error(EELFLoggerDelegate.errorLogger, "Some required partition key parts are missing: "+primaryKeyName );
+ throw new MusicQueryException("Some required partition key parts are missing: " + primaryKeyName,
+ Status.BAD_REQUEST.getStatusCode());
+ }
+
+ fieldsString.replace(fieldsString.length()-1, fieldsString.length(), ")");
+ valueString.replace(valueString.length()-1, valueString.length(), ")");
+
+ queryObject.appendQueryString("INSERT INTO " + this.getKeyspaceName() + "." + this.getTableName() + " "
+ + fieldsString + " VALUES " + valueString);
+
+ String ttl = this.getTtl();
+ String timestamp = this.getTimestamp();
+
+ if ((ttl != null) && (timestamp != null)) {
+ logger.info(EELFLoggerDelegate.applicationLogger, "both there");
+ queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
+ queryObject.addValue(Integer.parseInt(ttl));
+ queryObject.addValue(Long.parseLong(timestamp));
+ }
+
+ if ((ttl != null) && (timestamp == null)) {
+ logger.info(EELFLoggerDelegate.applicationLogger, "ONLY TTL there");
+ queryObject.appendQueryString(" USING TTL ?");
+ queryObject.addValue(Integer.parseInt(ttl));
+ }
+
+ if ((ttl == null) && (timestamp != null)) {
+ logger.info(EELFLoggerDelegate.applicationLogger, "ONLY timestamp there");
+ queryObject.appendQueryString(" USING TIMESTAMP ?");
+ queryObject.addValue(Long.parseLong(timestamp));
+ }
+
+ queryObject.appendQueryString(";");
+
+ String consistency = this.getConsistencyInfo().get("type");
+ if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency") != null) {
+ if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) {
+ queryObject.setConsistency(this.getConsistencyInfo().get("consistency"));
+ } else {
+ throw new MusicQueryException("Invalid Consistency type", Status.BAD_REQUEST.getStatusCode());
+ }
+ }
+ queryObject.setOperation("insert");
+
+ logger.info("Data insert Query ::::: " + queryObject.getQuery());
+
+ return queryObject;
+ }
+
+ /**
+ *
+ * @param rowParams
+ * @return
+ * @throws MusicQueryException
+ */
+ public PreparedQueryObject genSelectCriticalPreparedQueryObj(MultivaluedMap<String, String> rowParams) throws MusicQueryException {
+
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+
+ if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty())
+ || (this.getTableName() == null || this.getTableName().isEmpty())){
+ throw new MusicQueryException("one or more path parameters are not set, please check and try again",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+ EELFLoggerDelegate.mdcPut("keyspace", "( "+this.getKeyspaceName()+" ) ");
+ RowIdentifier rowId = null;
+ try {
+ rowId = getRowIdentifier(this.getKeyspaceName(), this.getTableName(), rowParams, queryObject);
+ this.setPrimaryKeyVal(rowId.primarKeyValue);
+ } catch (MusicServiceException ex) {
+ logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes
+ .GENERALSERVICEERROR, ex);
+ throw new MusicQueryException(ex.getMessage(), Status.BAD_REQUEST.getStatusCode());
+ }
+
+ queryObject.appendQueryString(
+ "SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE " + rowId.rowIdString + ";");
+
+ return queryObject;
+ }
+
+ private class RowIdentifier {
+ public String primarKeyValue;
+ public StringBuilder rowIdString;
+ @SuppressWarnings("unused")
+ public PreparedQueryObject queryObject; // the string with all the row
+ // identifiers separated by AND
+
+ public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
+ PreparedQueryObject queryObject) {
+ this.primarKeyValue = primaryKeyValue;
+ this.rowIdString = rowIdString;
+ this.queryObject = queryObject;
+ }
+ }
+
+ /**
+ *
+ * @param keyspace
+ * @param tablename
+ * @param rowParams
+ * @param queryObject
+ * @return
+ * @throws MusicServiceException
+ */
+ private RowIdentifier getRowIdentifier(String keyspace, String tablename,
+ MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
+ throws MusicServiceException {
+ StringBuilder rowSpec = new StringBuilder();
+ int counter = 0;
+ TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
+ if (tableInfo == null) {
+ logger.error(EELFLoggerDelegate.errorLogger,
+ "Table information not found. Please check input for table name= "
+ + keyspace + "." + tablename);
+ throw new MusicServiceException(
+ "Table information not found. Please check input for table name= "
+ + keyspace + "." + tablename);
+ }
+ StringBuilder primaryKey = new StringBuilder();
+ for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
+ String keyName = entry.getKey();
+ List<String> valueList = entry.getValue();
+ String indValue = valueList.get(0);
+ DataType colType = null;
+ Object formattedValue = null;
+ try {
+ colType = tableInfo.getColumn(entry.getKey()).getType();
+ formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e);
+ }
+ if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) {
+ primaryKey.append(indValue);
+ }
+ rowSpec.append(keyName + "= ?");
+ queryObject.addValue(formattedValue);
+ if (counter != rowParams.size() - 1) {
+ rowSpec.append(" AND ");
+ }
+ counter = counter + 1;
+ }
+ return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);
+ }
+
+
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java
new file mode 100644
index 00000000..cada1c00
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonKeySpace.java
@@ -0,0 +1,163 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * ===================================================================
+ * Modifications Copyright (C) 2019 IBM
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore.jsonobjects;
+
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.eelf.logging.format.AppMessages;
+import org.onap.music.eelf.logging.format.ErrorSeverity;
+import org.onap.music.eelf.logging.format.ErrorTypes;
+import org.onap.music.exceptions.MusicQueryException;
+import org.onap.music.main.MusicUtil;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel(value = "JsonTable", description = "Json model creating new keyspace")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class JsonKeySpace {
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonKeySpace.class);
+ private String keyspaceName;
+ private Map<String, Object> replicationInfo;
+ private String durabilityOfWrites;
+ private Map<String, String> consistencyInfo;
+
+ @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic")
+ public Map<String, String> getConsistencyInfo() {
+ return consistencyInfo;
+ }
+
+ public void setConsistencyInfo(Map<String, String> consistencyInfo) {
+ this.consistencyInfo = consistencyInfo;
+ }
+
+ @ApiModelProperty(value = "Replication information")
+ public Map<String, Object> getReplicationInfo() {
+ return replicationInfo;
+ }
+
+ public void setReplicationInfo(Map<String, Object> replicationInfo) {
+ this.replicationInfo = replicationInfo;
+ }
+
+ @ApiModelProperty(value = "Durability", allowableValues = "true,false")
+ public String getDurabilityOfWrites() {
+ return durabilityOfWrites;
+ }
+
+ public void setDurabilityOfWrites(String durabilityOfWrites) {
+ this.durabilityOfWrites = durabilityOfWrites;
+ }
+
+ @ApiModelProperty(value = "Keyspace name")
+ public String getKeyspaceName() {
+ return keyspaceName;
+ }
+
+ public void setKeyspaceName(String keyspaceName) {
+ this.keyspaceName = keyspaceName;
+ }
+
+ /**
+ * Will generate query to create Keyspacce.
+ *
+ * @throws MusicQueryException
+ */
+ @SuppressWarnings("deprecation")
+ public PreparedQueryObject genCreateKeyspaceQuery() throws MusicQueryException {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Came inside createKeyspace method");
+ }
+
+ String keyspaceName = this.getKeyspaceName();
+ String durabilityOfWrites = this.getDurabilityOfWrites();
+ String consistency = MusicUtil.EVENTUAL;
+
+ logger.info("genCreateKeyspaceQuery keyspaceName ::" + keyspaceName);
+ logger.info("genCreateKeyspaceQuery class :: " + this.getReplicationInfo().get("class"));
+ logger.info("genCreateKeyspaceQuery replication_factor :: " + this.getReplicationInfo().get("replication_factor"));
+ logger.info("genCreateKeyspaceQuery durabilityOfWrites :: " + durabilityOfWrites);
+
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+
+ if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency") != null) {
+ if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) {
+ queryObject.setConsistency(this.getConsistencyInfo().get("consistency"));
+ }else {
+ throw new MusicQueryException("Invalid Consistency type",Status.BAD_REQUEST.getStatusCode());
+ }
+ }
+
+ long start = System.currentTimeMillis();
+ Map<String, Object> replicationInfo = this.getReplicationInfo();
+ String repString = null;
+ try {
+ repString = "{" + MusicUtil.jsonMaptoSqlString(replicationInfo, ",") + "}";
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.MISSINGDATA,
+ ErrorSeverity.CRITICAL, ErrorTypes.DATAERROR);
+ }
+ queryObject.appendQueryString("CREATE KEYSPACE " + keyspaceName + " WITH replication = " + repString);
+ if (this.getDurabilityOfWrites() != null) {
+ queryObject.appendQueryString(" AND durable_writes = " + this.getDurabilityOfWrites());
+ }
+ queryObject.appendQueryString(";");
+ long end = System.currentTimeMillis();
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "Time taken for setting up query in create keyspace:" + (end - start));
+
+ return queryObject;
+ }
+
+ /**
+ * Will generate Query to drop a keyspace.
+ *
+ * @return
+ */
+ public PreparedQueryObject genDropKeyspaceQuery() {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Coming inside genDropKeyspaceQuery method "+this.getKeyspaceName());
+ }
+
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+ queryObject.appendQueryString("DROP KEYSPACE " + this.getKeyspaceName() + ";");
+
+ return queryObject;
+ }
+
+ @Override
+ public String toString() {
+ return "CassaKeyspaceObject [keyspaceName=" + keyspaceName + ", replicationInfo=" + replicationInfo
+ + "durabilityOfWrites=" + durabilityOfWrites + "]";
+ }
+
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java
new file mode 100644
index 00000000..86bbe3dc
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLeasedLock.java
@@ -0,0 +1,44 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore.jsonobjects;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel(value = "Json Leasesd Lock", description = "model for leased lock")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class JsonLeasedLock {
+ private long leasePeriod;
+
+ @ApiModelProperty(value = "Lease period")
+ public long getLeasePeriod() {
+ return leasePeriod;
+ }
+
+ public void setLeasePeriod(long leasePeriod) {
+ this.leasePeriod = leasePeriod;
+ }
+
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java
new file mode 100644
index 00000000..f353c018
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonLock.java
@@ -0,0 +1,49 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore.jsonobjects;
+
+import org.onap.music.lockingservice.cassandra.LockType;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel(value = "Json Lock Type", description = "Model for Lock Type")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class JsonLock {
+ private LockType locktype;
+
+ @ApiModelProperty(
+ value = "Type of music lock",
+ name = "lockType",
+ allowEmptyValue = false,
+ allowableValues = "READ|WRITE")
+ public LockType getLocktype() {
+ return this.locktype;
+ }
+
+ public void setLockType(LockType locktype) {
+ this.locktype = locktype;
+ }
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java
new file mode 100644
index 00000000..e354b4b0
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonSelect.java
@@ -0,0 +1,208 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * Modifications Copyright (C) 2019 IBM
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore.jsonobjects;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.music.datastore.MusicDataStoreHandle;
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.eelf.logging.format.AppMessages;
+import org.onap.music.eelf.logging.format.ErrorSeverity;
+import org.onap.music.eelf.logging.format.ErrorTypes;
+import org.onap.music.exceptions.MusicQueryException;
+import org.onap.music.exceptions.MusicServiceException;
+import org.onap.music.main.MusicUtil;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.TableMetadata;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class JsonSelect implements Serializable {
+ private Map<String, String> consistencyInfo;
+ private String keyspaceName;
+ private String tableName;
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonSelect.class);
+
+
+
+ public Map<String, String> getConsistencyInfo() {
+ return consistencyInfo;
+ }
+
+ public void setConsistencyInfo(Map<String, String> consistencyInfo) {
+ this.consistencyInfo = consistencyInfo;
+ }
+
+ public String getKeyspaceName() {
+ return keyspaceName;
+ }
+
+ public void setKeyspaceName(String keyspaceName) {
+ this.keyspaceName = keyspaceName;
+ }
+
+ public String getTableName() {
+ return tableName;
+ }
+
+ public void setTableName(String tableName) {
+ this.tableName = tableName;
+ }
+
+ public byte[] serialize() {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutput out = null;
+ try {
+ out = new ObjectOutputStream(bos);
+ out.writeObject(this);
+ } catch (IOException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), e);
+ }
+ return bos.toByteArray();
+ }
+
+ /**
+ * genSelectQuery
+ *
+ * @return
+ * @throws MusicQueryException
+ */
+ public PreparedQueryObject genSelectQuery(MultivaluedMap<String, String> rowParams) throws MusicQueryException {
+
+ if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty())
+ || (this.getTableName() == null || this.getTableName().isEmpty())){
+ throw new MusicQueryException("one or more path parameters are not set, please check and try again",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+ EELFLoggerDelegate.mdcPut("keyspace", "( " + this.getKeyspaceName() + " ) ");
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+
+ if (rowParams.isEmpty()) { // select all
+ queryObject.appendQueryString("SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + ";");
+ } else {
+ int limit = -1; // do not limit the number of results
+ try {
+ queryObject = selectSpecificQuery(this.getKeyspaceName(), this.getTableName(), rowParams, limit);
+ } catch (MusicServiceException ex) {
+ logger.error(EELFLoggerDelegate.errorLogger, ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN,
+ ErrorTypes.GENERALSERVICEERROR, ex);
+
+ throw new MusicQueryException(ex.getMessage(), Status.BAD_REQUEST.getStatusCode());
+ }
+ }
+
+ return queryObject;
+ }
+
+ public PreparedQueryObject selectSpecificQuery(String keyspace,
+ String tablename, MultivaluedMap<String, String> rowParams, int limit)
+ throws MusicServiceException {
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+ StringBuilder rowIdString = getRowIdentifier(keyspace,
+ tablename,rowParams,queryObject).rowIdString;
+ queryObject.appendQueryString(
+ "SELECT * FROM " + keyspace + "." + tablename + " WHERE " + rowIdString);
+ if (limit != -1) {
+ queryObject.appendQueryString(" LIMIT " + limit);
+ }
+ queryObject.appendQueryString(";");
+ return queryObject;
+ }
+
+ private class RowIdentifier {
+ public String primarKeyValue;
+ public StringBuilder rowIdString;
+ @SuppressWarnings("unused")
+ public PreparedQueryObject queryObject; // the string with all the row
+ // identifiers separated by AND
+
+ public RowIdentifier(String primaryKeyValue, StringBuilder rowIdString,
+ PreparedQueryObject queryObject) {
+ this.primarKeyValue = primaryKeyValue;
+ this.rowIdString = rowIdString;
+ this.queryObject = queryObject;
+ }
+ }
+
+ /**
+ *
+ * @param keyspace
+ * @param tablename
+ * @param rowParams
+ * @param queryObject
+ * @return
+ * @throws MusicServiceException
+ */
+ private RowIdentifier getRowIdentifier(String keyspace, String tablename,
+ MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
+ throws MusicServiceException {
+ StringBuilder rowSpec = new StringBuilder();
+ int counter = 0;
+ TableMetadata tableInfo = MusicDataStoreHandle.returnColumnMetadata(keyspace, tablename);
+ if (tableInfo == null) {
+ logger.error(EELFLoggerDelegate.errorLogger,
+ "Table information not found. Please check input for table name= "
+ + keyspace + "." + tablename);
+ throw new MusicServiceException(
+ "Table information not found. Please check input for table name= "
+ + keyspace + "." + tablename);
+ }
+ StringBuilder primaryKey = new StringBuilder();
+ for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
+ String keyName = entry.getKey();
+ List<String> valueList = entry.getValue();
+ String indValue = valueList.get(0);
+ DataType colType = null;
+ Object formattedValue = null;
+ try {
+ colType = tableInfo.getColumn(entry.getKey()).getType();
+ formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e);
+ }
+ if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) {
+ primaryKey.append(indValue);
+ }
+ rowSpec.append(keyName + "= ?");
+ queryObject.addValue(formattedValue);
+ if (counter != rowParams.size() - 1) {
+ rowSpec.append(" AND ");
+ }
+ counter = counter + 1;
+ }
+ return new RowIdentifier(primaryKey.toString(), rowSpec, queryObject);
+ }
+
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java
new file mode 100644
index 00000000..0ba1a7ef
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonTable.java
@@ -0,0 +1,363 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * ===================================================================
+ * Modifications Copyright (C) 2019 IBM
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore.jsonobjects;
+
+import java.util.Map;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.exceptions.MusicQueryException;
+import org.onap.music.main.MusicUtil;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel(value = "JsonTable", description = "Defines the Json for Creating a new Table.")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class JsonTable {
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonTable.class);
+
+ private String keyspaceName;
+ private String tableName;
+
+ private Map<String, String> fields;
+ private Map<String, Object> properties;
+ private String primaryKey;
+ private String partitionKey;
+ private String clusteringKey;
+ private String filteringKey;
+ private String clusteringOrder;
+ private Map<String, String> consistencyInfo;
+
+ @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic")
+ public Map<String, String> getConsistencyInfo() {
+ return consistencyInfo;
+ }
+
+ public void setConsistencyInfo(Map<String, String> consistencyInfo) {
+ this.consistencyInfo = consistencyInfo;
+ }
+
+ @ApiModelProperty(value = "Properties")
+ public Map<String, Object> getProperties() {
+ return properties;
+ }
+
+ public void setProperties(Map<String, Object> properties) {
+ this.properties = properties;
+ }
+
+ @ApiModelProperty(value = "Fields")
+ public Map<String, String> getFields() {
+ return fields;
+ }
+
+ public void setFields(Map<String, String> fields) {
+ this.fields = fields;
+ }
+
+ @ApiModelProperty(value = "KeySpace Name")
+ public String getKeyspaceName() {
+ return keyspaceName;
+ }
+
+ public void setKeyspaceName(String keyspaceName) {
+ this.keyspaceName = keyspaceName;
+ }
+
+ @ApiModelProperty(value = "Table Name")
+ public String getTableName() {
+ return tableName;
+ }
+
+ public void setTableName(String tableName) {
+ this.tableName = tableName;
+ }
+
+ @ApiModelProperty(value = "Clustering Order", notes = "")
+ public String getClusteringOrder() {
+ return clusteringOrder;
+ }
+
+ public void setClusteringOrder(String clusteringOrder) {
+ this.clusteringOrder = clusteringOrder;
+ }
+
+ @ApiModelProperty(value = "Primary Key")
+ public String getPrimaryKey() {
+ return primaryKey;
+ }
+
+ public void setPrimaryKey(String primaryKey) {
+ this.primaryKey = primaryKey;
+ }
+
+ public String getClusteringKey() {
+ return clusteringKey;
+ }
+
+ public void setClusteringKey(String clusteringKey) {
+ this.clusteringKey = clusteringKey;
+ }
+
+ public String getFilteringKey() {
+ return filteringKey;
+ }
+
+ public void setFilteringKey(String filteringKey) {
+ this.filteringKey = filteringKey;
+ }
+
+ public String getPartitionKey() {
+ return partitionKey;
+ }
+
+ public void setPartitionKey(String partitionKey) {
+ this.partitionKey = partitionKey;
+ }
+
+ public PreparedQueryObject genCreateTableQuery() throws MusicQueryException {
+ String primaryKey = null;
+ String partitionKey = this.getPartitionKey();
+ String clusterKey = this.getClusteringKey();
+ String filteringKey = this.getFilteringKey();
+ if (filteringKey != null) {
+ clusterKey = clusterKey + "," + filteringKey;
+ }
+ primaryKey = this.getPrimaryKey(); // get primaryKey if available
+
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+ // first read the information about the table fields
+ Map<String, String> fields = this.getFields();
+ if (fields == null) {
+ throw new MusicQueryException(
+ "Create Table Error: No fields in request", Status.BAD_REQUEST.getStatusCode());
+ }
+ StringBuilder fieldsString = new StringBuilder("(vector_ts text,");
+ int counter = 0;
+ for (Map.Entry<String, String> entry : fields.entrySet()) {
+ if (entry.getKey().equals("PRIMARY KEY")) {
+ primaryKey = entry.getValue(); // replaces primaryKey
+ primaryKey = primaryKey.trim();
+ }
+ else {
+ if (counter == 0 )
+ fieldsString.append("" + entry.getKey() + " " + entry.getValue() + "");
+ else fieldsString.append("," + entry.getKey() + " " + entry.getValue() + "");
+ }
+
+ if (counter != (fields.size() - 1) ) {
+ counter = counter + 1;
+ } else {
+
+ if((primaryKey != null) && (partitionKey == null)) {
+ primaryKey = primaryKey.trim();
+ int count1 = StringUtils.countMatches(primaryKey, ')');
+ int count2 = StringUtils.countMatches(primaryKey, '(');
+ if (count1 != count2) {
+ throw new MusicQueryException(
+ "Create Table Error: primary key '(' and ')' do not match, primary key=" + primaryKey,
+ Status.BAD_REQUEST.getStatusCode());
+ }
+
+ if ( primaryKey.indexOf('(') == -1 || ( count2 == 1 && (primaryKey.lastIndexOf(')') +1) == primaryKey.length() ) ) {
+ if (primaryKey.contains(",") ) {
+ partitionKey= primaryKey.substring(0,primaryKey.indexOf(','));
+ partitionKey=partitionKey.replaceAll("[\\(]+","");
+ clusterKey=primaryKey.substring(primaryKey.indexOf(',')+1); // make sure index
+ clusterKey=clusterKey.replaceAll("[)]+", "");
+ } else {
+ partitionKey=primaryKey;
+ partitionKey=partitionKey.replaceAll("[\\)]+","");
+ partitionKey=partitionKey.replaceAll("[\\(]+","");
+ clusterKey="";
+ }
+ } else { // not null and has ) before the last char
+ partitionKey= primaryKey.substring(0,primaryKey.indexOf(')'));
+ partitionKey=partitionKey.replaceAll("[\\(]+","");
+ partitionKey = partitionKey.trim();
+ clusterKey= primaryKey.substring(primaryKey.indexOf(')'));
+ clusterKey=clusterKey.replaceAll("[\\(]+","");
+ clusterKey=clusterKey.replaceAll("[\\)]+","");
+ clusterKey = clusterKey.trim();
+ if (clusterKey.indexOf(',') == 0) {
+ clusterKey=clusterKey.substring(1);
+ }
+ clusterKey = clusterKey.trim();
+ if (clusterKey.equals(",") )
+ clusterKey=""; // print error if needed ( ... ),)
+ }
+
+ if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
+ && (partitionKey.equalsIgnoreCase(clusterKey) ||
+ clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
+ logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey + " and primary key=" + primaryKey );
+ /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
+ "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ") of"
+ + " primary key=" + primaryKey)
+ .toMap()).build();*/
+ throw new MusicQueryException("Create Table primary key error: clusterKey(" + clusterKey
+ + ") equals/contains/overlaps partitionKey(" + partitionKey + ") of" + " primary key="
+ + primaryKey, Status.BAD_REQUEST.getStatusCode());
+
+ }
+
+ if (partitionKey.isEmpty() )
+ primaryKey="";
+ else if (clusterKey.isEmpty() )
+ primaryKey=" (" + partitionKey + ")";
+ else
+ primaryKey=" (" + partitionKey + ")," + clusterKey;
+
+
+ if (primaryKey != null)
+ fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
+
+ } else { // end of length > 0
+
+ if (!(partitionKey.isEmpty() || clusterKey.isEmpty())
+ && (partitionKey.equalsIgnoreCase(clusterKey) ||
+ clusterKey.contains(partitionKey) || partitionKey.contains(clusterKey)) ) {
+ logger.error("DataAPI createTable partition/cluster key ERROR: partitionKey="+partitionKey+", clusterKey=" + clusterKey);
+ /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(
+ "Create Table primary key error: clusterKey(" + clusterKey + ") equals/contains/overlaps partitionKey(" +partitionKey+ ")")
+ .toMap()).build();*/
+ throw new MusicQueryException(
+ "Create Table primary key error: clusterKey(" + clusterKey
+ + ") equals/contains/overlaps partitionKey(" + partitionKey + ")",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+
+ if (partitionKey.isEmpty() )
+ primaryKey="";
+ else if (clusterKey.isEmpty() )
+ primaryKey=" (" + partitionKey + ")";
+ else
+ primaryKey=" (" + partitionKey + ")," + clusterKey;
+
+ if (primaryKey != null)
+ fieldsString.append(", PRIMARY KEY (" + primaryKey + " )");
+ }
+ fieldsString.append(")");
+
+ } // end of last field check
+
+ } // end of for each
+ // information about the name-value style properties
+ Map<String, Object> propertiesMap = this.getProperties();
+ StringBuilder propertiesString = new StringBuilder();
+ if (propertiesMap != null) {
+ counter = 0;
+ for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {
+ Object ot = entry.getValue();
+ String value = ot + "";
+ if (ot instanceof String) {
+ value = "'" + value + "'";
+ } else if (ot instanceof Map) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> otMap = (Map<String, Object>) ot;
+ try {
+ value = "{" + MusicUtil.jsonMaptoSqlString(otMap, ",") + "}";
+ } catch (Exception e) {
+ throw new MusicQueryException(e.getMessage(),
+ Status.BAD_REQUEST.getStatusCode());
+ }
+ }
+
+ propertiesString.append(entry.getKey() + "=" + value + "");
+ if (counter != propertiesMap.size() - 1)
+ propertiesString.append(" AND ");
+
+ counter = counter + 1;
+ }
+ }
+
+ String clusteringOrder = this.getClusteringOrder();
+
+ if (clusteringOrder != null && !(clusteringOrder.isEmpty())) {
+ String[] arrayClusterOrder = clusteringOrder.split("[,]+");
+
+ for (int i = 0; i < arrayClusterOrder.length; i++) {
+ String[] clusterS = arrayClusterOrder[i].trim().split("[ ]+");
+ if ( (clusterS.length ==2) && (clusterS[1].equalsIgnoreCase("ASC") || clusterS[1].equalsIgnoreCase("DESC"))) {
+ continue;
+ } else {
+ /*return response.status(Status.BAD_REQUEST)
+ .entity(new JsonResponse(ResultType.FAILURE)
+ .setError("createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"+ clusteringOrder+".")
+ .toMap()).build();*/
+
+ throw new MusicQueryException(
+ "createTable/Clustering Order vlaue ERROR: valid clustering order is ASC or DESC or expecting colname order; please correct clusteringOrder:"
+ + clusteringOrder + ".",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+ // add validation for column names in cluster key
+ }
+
+ if (!(clusterKey.isEmpty())) {
+ clusteringOrder = "CLUSTERING ORDER BY (" +clusteringOrder +")";
+ //cjc check if propertiesString.length() >0 instead propertiesMap
+ if (propertiesMap != null) {
+ propertiesString.append(" AND "+ clusteringOrder);
+ } else {
+ propertiesString.append(clusteringOrder);
+ }
+ } else {
+ logger.warn("Skipping clustering order=("+clusteringOrder+ ") since clustering key is empty ");
+ }
+ } //if non empty
+
+ queryObject.appendQueryString(
+ "CREATE TABLE " + this.getKeyspaceName() + "." + this.getTableName() + " " + fieldsString);
+
+
+ if (propertiesString != null && propertiesString.length()>0 )
+ queryObject.appendQueryString(" WITH " + propertiesString);
+ queryObject.appendQueryString(";");
+
+ return queryObject;
+ }
+
+ /**
+ * genDropTableQuery
+ *
+ * @return PreparedQueryObject
+ */
+ public PreparedQueryObject genDropTableQuery() {
+ PreparedQueryObject query = new PreparedQueryObject();
+ query.appendQueryString("DROP TABLE " + this.getKeyspaceName() + "." + this.getTableName() + ";");
+ logger.info("Delete Query ::::: " + query.getQuery());
+
+ return query;
+ }
+
+
+}
diff --git a/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java
new file mode 100644
index 00000000..29fdb1d4
--- /dev/null
+++ b/music-core/src/main/java/org/onap/music/datastore/jsonobjects/JsonUpdate.java
@@ -0,0 +1,436 @@
+/*
+ * ============LICENSE_START==========================================
+ * org.onap.music
+ * ===================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property
+ * Modifications Copyright (C) 2019 IBM
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END=============================================
+ * ====================================================================
+ */
+
+package org.onap.music.datastore.jsonobjects;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.music.datastore.Condition;
+import org.onap.music.datastore.MusicDataStoreHandle;
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.eelf.logging.EELFLoggerDelegate;
+import org.onap.music.eelf.logging.format.AppMessages;
+import org.onap.music.eelf.logging.format.ErrorSeverity;
+import org.onap.music.eelf.logging.format.ErrorTypes;
+import org.onap.music.exceptions.MusicQueryException;
+import org.onap.music.exceptions.MusicServiceException;
+import org.onap.music.main.MusicUtil;
+import org.onap.music.main.ReturnType;
+
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.TableMetadata;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel(value = "JsonTable", description = "Json model for table update")
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class JsonUpdate implements Serializable {
+ private String keyspaceName;
+ private String tableName;
+ private transient Map<String, Object> values;
+ private String ttl;
+ private String timestamp;
+ private Map<String, String> consistencyInfo;
+ private transient Map<String, Object> conditions;
+ private transient Map<String, Object> rowSpecification;
+ private String rowIdString;
+ private String primarKeyValue;
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(JsonUpdate.class);
+
+ @ApiModelProperty(value = "Conditions")
+ public Map<String, Object> getConditions() {
+ return conditions;
+ }
+
+ public void setConditions(Map<String, Object> conditions) {
+ this.conditions = conditions;
+ }
+
+ @ApiModelProperty(value = "Information for selecting sepcific rows")
+ public Map<String, Object> getRow_specification() {
+ return rowSpecification;
+ }
+
+ public void setRow_specification(Map<String, Object> rowSpecification) {
+ this.rowSpecification = rowSpecification;
+ }
+
+
+ @ApiModelProperty(value = "Keyspace name")
+ public String getKeyspaceName() {
+ return keyspaceName;
+ }
+
+ public void setKeyspaceName(String keyspaceName) {
+ this.keyspaceName = keyspaceName;
+ }
+
+ @ApiModelProperty(value = "Table name")
+ public String getTableName() {
+ return tableName;
+ }
+
+ public void setTableName(String tableName) {
+ this.tableName = tableName;
+ }
+
+ @ApiModelProperty(value = "Consistency level", allowableValues = "eventual,critical,atomic")
+ public Map<String, String> getConsistencyInfo() {
+ return consistencyInfo;
+ }
+
+ public void setConsistencyInfo(Map<String, String> consistencyInfo) {
+ this.consistencyInfo = consistencyInfo;
+ }
+
+ @ApiModelProperty(value = "Time to live value")
+ public String getTtl() {
+ return ttl;
+ }
+
+ public void setTtl(String ttl) {
+ this.ttl = ttl;
+ }
+
+ @ApiModelProperty(value = "Time stamp")
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(String timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ @ApiModelProperty(value = "Column values")
+ public Map<String, Object> getValues() {
+ return values;
+ }
+
+ public void setValues(Map<String, Object> values) {
+ this.values = values;
+ }
+
+ public String getRowIdString() {
+ return rowIdString;
+ }
+
+ public void setRowIdString(String rowIdString) {
+ this.rowIdString = rowIdString;
+ }
+
+ public String getPrimarKeyValue() {
+ return primarKeyValue;
+ }
+
+ public void setPrimarKeyValue(String primarKeyValue) {
+ this.primarKeyValue = primarKeyValue;
+ }
+
+ public byte[] serialize() {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutput out = null;
+ try {
+ out = new ObjectOutputStream(bos);
+ out.writeObject(this);
+ } catch (IOException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e,AppMessages.IOERROR, ErrorSeverity.ERROR, ErrorTypes.DATAERROR);
+ }
+ return bos.toByteArray();
+ }
+
+ /**
+ * Generate TableInsertQuery
+ * @return
+ * @throws MusicQueryException
+ */
+ public PreparedQueryObject genUpdatePreparedQueryObj(MultivaluedMap<String, String> rowParams) throws MusicQueryException {
+ PreparedQueryObject queryObject = new PreparedQueryObject();
+
+ if((this.getKeyspaceName() == null || this.getKeyspaceName().isEmpty()) ||
+ (this.getTableName() == null || this.getTableName().isEmpty())){
+
+ /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
+ .setError("one or more path parameters are not set, please check and try again")
+ .toMap()).build();*/
+
+ throw new MusicQueryException("one or more path parameters are not set, please check and try again",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+
+ EELFLoggerDelegate.mdcPut("keyspace", "( "+this.getKeyspaceName()+" ) ");
+ String operationId = UUID.randomUUID().toString(); // just for infoging purposes.
+ String consistency = this.getConsistencyInfo().get("type");
+
+ logger.info(EELFLoggerDelegate.applicationLogger, "--------------Music " + consistency
+ + " update-" + operationId + "-------------------------");
+ // obtain the field value pairs of the update
+
+ Map<String, Object> valuesMap = this.getValues();
+
+ TableMetadata tableInfo = getColumnMetadata(this.getKeyspaceName(), this.getTableName());
+
+ if (tableInfo == null) {
+ logger.error(EELFLoggerDelegate.errorLogger,"Table information not found. Please check input for table name= "+this.getTableName(), AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR);
+
+ /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
+ .setError("Table information not found. Please check input for table name= "
+ + this.getKeyspaceName() + "." + this.getTableName()).toMap()).build();*/
+
+ throw new MusicQueryException("Table information not found. Please check input for table name= "
+ + this.getKeyspaceName() + "." + this.getTableName(), Status.BAD_REQUEST.getStatusCode());
+ }
+
+ String vectorTs = String.valueOf(Thread.currentThread().getId() + System.currentTimeMillis());
+ StringBuilder fieldValueString = new StringBuilder("vector_ts=?,");
+ queryObject.addValue(vectorTs);
+ int counter = 0;
+ for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
+ Object valueObj = entry.getValue();
+ DataType colType = null;
+ try {
+ colType = tableInfo.getColumn(entry.getKey()).getType();
+ } catch(NullPointerException ex) {
+ logger.error(EELFLoggerDelegate.errorLogger, ex, "Invalid column name : "+entry.getKey(), ex);
+ /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).
+ * setError("Invalid column name : "+entry.getKey()).toMap()).build();*/
+
+ throw new MusicQueryException("Invalid column name : " + entry.getKey(),Status.BAD_REQUEST.getStatusCode());
+ }
+ Object valueString = null;
+ try {
+ valueString = MusicUtil.convertToActualDataType(colType, valueObj);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e);
+ }
+ fieldValueString.append(entry.getKey() + "= ?");
+ queryObject.addValue(valueString);
+ if (counter != valuesMap.size() - 1) {
+ fieldValueString.append(",");
+ }
+ counter = counter + 1;
+ }
+ String ttl = this.getTtl();
+ String timestamp = this.getTimestamp();
+
+ queryObject.appendQueryString("UPDATE " + this.getKeyspaceName() + "." + this.getTableName() + " ");
+ if ((ttl != null) && (timestamp != null)) {
+ logger.info("both there");
+ queryObject.appendQueryString(" USING TTL ? AND TIMESTAMP ?");
+ queryObject.addValue(Integer.parseInt(ttl));
+ queryObject.addValue(Long.parseLong(timestamp));
+ }
+
+ if ((ttl != null) && (timestamp == null)) {
+ logger.info("ONLY TTL there");
+ queryObject.appendQueryString(" USING TTL ?");
+ queryObject.addValue(Integer.parseInt(ttl));
+ }
+
+ if ((ttl == null) && (timestamp != null)) {
+ logger.info("ONLY timestamp there");
+ queryObject.appendQueryString(" USING TIMESTAMP ?");
+ queryObject.addValue(Long.parseLong(timestamp));
+ }
+
+ // get the row specifier
+ RowIdentifier rowId = null;
+ try {
+ rowId = getRowIdentifier(this.getKeyspaceName(), this.getTableName(), rowParams, queryObject);
+ this.setRowIdString(rowId.rowIdString);
+ this.setPrimarKeyValue(rowId.primarKeyValue);
+ if(rowId == null || rowId.getPrimaryKeyValue().isEmpty()) {
+ /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE)
+ .setError("Mandatory WHERE clause is missing. Please check the input request.").toMap()).build();*/
+
+ throw new MusicQueryException("Mandatory WHERE clause is missing. Please check the input request.",
+ Status.BAD_REQUEST.getStatusCode());
+ }
+ } catch (MusicQueryException ex) {
+ throw new MusicQueryException("Mandatory WHERE clause is missing. Please check the input request.",
+ Status.BAD_REQUEST.getStatusCode());
+
+ }catch (MusicServiceException ex) {
+ logger.error(EELFLoggerDelegate.errorLogger,ex, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes
+ .GENERALSERVICEERROR, ex);
+ /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(ex.getMessage()).toMap()).build();*/
+
+ throw new MusicQueryException(ex.getMessage(), Status.BAD_REQUEST.getStatusCode());
+
+ }
+
+
+
+ queryObject.appendQueryString(
+ " SET " + fieldValueString + " WHERE " + rowId.getRowIdString() + ";");
+
+
+
+ // get the conditional, if any
+ Condition conditionInfo;
+ if (this.getConditions() == null) {
+ conditionInfo = null;
+ } else {
+ // to avoid parsing repeatedly, just send the select query to obtain row
+ PreparedQueryObject selectQuery = new PreparedQueryObject();
+ selectQuery.appendQueryString("SELECT * FROM " + this.getKeyspaceName() + "." + this.getTableName() + " WHERE "
+ + rowId.getRowIdString() + ";");
+ selectQuery.addValue(rowId.primarKeyValue);
+ conditionInfo = new Condition(this.getConditions(), selectQuery);
+ }
+
+ if(consistency.equalsIgnoreCase(MusicUtil.EVENTUAL) && this.getConsistencyInfo().get("consistency") != null) {
+ if(MusicUtil.isValidConsistency(this.getConsistencyInfo().get("consistency"))) {
+ queryObject.setConsistency(this.getConsistencyInfo().get("consistency"));
+ } else {
+ /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.SYNTAXERROR)
+ .setError("Invalid Consistency type").toMap()).build();*/
+
+ logger.error("Invalid Consistency type");
+ throw new MusicQueryException("Invalid Consistency type", Status.BAD_REQUEST.getStatusCode());
+ }
+ }
+
+ queryObject.setOperation("update");
+
+ return queryObject;
+ }
+
+ TableMetadata getColumnMetadata(String keyspaceName, String tableName) throws MusicQueryException {
+ TableMetadata tableInfo;
+ try {
+ tableInfo = returnColumnMetadata(keyspaceName, tableName);
+ } catch (MusicServiceException e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e, AppMessages.UNKNOWNERROR ,ErrorSeverity.WARN, ErrorTypes
+ .GENERALSERVICEERROR, e);
+ /*return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();*/
+ throw new MusicQueryException(e.getMessage(), Status.BAD_REQUEST.getStatusCode());
+ }catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e, AppMessages.UNKNOWNERROR, ErrorSeverity.CRITICAL,
+ ErrorTypes.GENERALSERVICEERROR);
+ throw new MusicQueryException(e.getMessage(), Status.BAD_REQUEST.getStatusCode());
+ }
+ return tableInfo;
+ }
+
+ /** wrapper around static method for testing */
+ TableMetadata returnColumnMetadata(String keyspace, String tableName) throws MusicServiceException {
+ return MusicDataStoreHandle.returnColumnMetadata(keyspace, tableName);
+ }
+
+ class RowIdentifier {
+ private String primarKeyValue;
+ private String rowIdString;
+ @SuppressWarnings("unused")
+ public PreparedQueryObject queryObject; // the string with all the row
+ // identifiers separated by AND
+
+ public RowIdentifier(String primaryKeyValue, String rowIdString,
+ PreparedQueryObject queryObject) {
+ this.primarKeyValue = primaryKeyValue;
+ this.rowIdString = rowIdString;
+ this.queryObject = queryObject;
+ }
+
+ public String getPrimaryKeyValue() {
+ return this.primarKeyValue;
+ }
+
+ public void setPrimaryKeyValue(String primaryKeyValue) {
+ this.primarKeyValue = primaryKeyValue;
+ }
+
+ public String getRowIdString() {
+ return this.rowIdString;
+ }
+
+ public void setRowIdString(String rowIdString) {
+ this.rowIdString = rowIdString;
+ }
+
+ public PreparedQueryObject getQueryObject() {
+ return this.queryObject;
+ }
+ }
+
+ /**
+ *
+ * @param keyspace
+ * @param tablename
+ * @param rowParams
+ * @param queryObject
+ * @return
+ * @throws MusicServiceException
+ */
+ RowIdentifier getRowIdentifier(String keyspace, String tablename,
+ MultivaluedMap<String, String> rowParams, PreparedQueryObject queryObject)
+ throws MusicServiceException {
+ StringBuilder rowSpec = new StringBuilder();
+ int counter = 0;
+ TableMetadata tableInfo = returnColumnMetadata(keyspace, tablename);
+ if (tableInfo == null) {
+ logger.error(EELFLoggerDelegate.errorLogger,
+ "Table information not found. Please check input for table name= "
+ + keyspace + "." + tablename);
+ throw new MusicServiceException(
+ "Table information not found. Please check input for table name= "
+ + keyspace + "." + tablename);
+ }
+ StringBuilder primaryKey = new StringBuilder();
+ for (MultivaluedMap.Entry<String, List<String>> entry : rowParams.entrySet()) {
+ String keyName = entry.getKey();
+ List<String> valueList = entry.getValue();
+ String indValue = valueList.get(0);
+ DataType colType = null;
+ Object formattedValue = null;
+ try {
+ colType = tableInfo.getColumn(entry.getKey()).getType();
+ formattedValue = MusicUtil.convertToActualDataType(colType, indValue);
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger,e);
+ }
+ if(tableInfo.getPrimaryKey().get(0).getName().equals(entry.getKey())) {
+ primaryKey.append(indValue);
+ }
+ rowSpec.append(keyName + "= ?");
+ queryObject.addValue(formattedValue);
+ if (counter != rowParams.size() - 1) {
+ rowSpec.append(" AND ");
+ }
+ counter = counter + 1;
+ }
+ return new RowIdentifier(primaryKey.toString(), rowSpec.toString(), queryObject);
+ }
+
+}