/**
* Copyright (C) 2014 Stratio (http://stratio.com)
*
* 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.
*/
package com.stratio.decision.service;
import com.datastax.driver.core.ColumnMetadata;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.TableMetadata;
import com.datastax.driver.core.exceptions.AlreadyExistsException;
import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.utils.UUIDs;
import com.stratio.decision.commons.constants.STREAMING;
import com.stratio.decision.commons.messages.ColumnNameTypeValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
public class SaveToCassandraOperationsService {
private static final Logger log = LoggerFactory.getLogger(SaveToCassandraOperationsService.class);
private final Session session;
private HashMap<String, Integer> tablenames = new HashMap<>();
public SaveToCassandraOperationsService(Session session) {
this.session = session;
}
public Boolean check() throws Exception {
if (session == null)
return false;
try {
return session.getState().getConnectedHosts().size() > 0;
} catch (Exception e) {
return false;
}
}
public void refreshTablenames() {
Collection<TableMetadata> tableMetadatas = session.getCluster().getMetadata()
.getKeyspace(STREAMING.STREAMING_KEYSPACE_NAME).getTables();
tablenames = new HashMap<>();
for (TableMetadata tableMetadata : tableMetadatas) {
Set<String> columns = new HashSet<>();
for (ColumnMetadata columnMetadata : tableMetadata.getColumns()) {
columns.add(columnMetadata.getName());
}
tablenames.put(tableMetadata.getName(), columns.hashCode());
}
}
public void checkKeyspace() {
if (session!= null && session.getCluster().getMetadata().getKeyspace
(STREAMING.STREAMING_KEYSPACE_NAME) == null) {
createKeyspace(STREAMING.STREAMING_KEYSPACE_NAME);
}
refreshTablenames();
}
public void createKeyspace(String keyspaceName) {
session.execute(String.format(
"CREATE KEYSPACE %s WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}",
addQuotes(keyspaceName)));
}
public void createTable(String tableName, List<ColumnNameTypeValue> columns, String timestampColumnName) {
StringBuilder sb = new StringBuilder();
for (Entry<String, String> entry : getStreamFieldsAndTypes(columns).entrySet()) {
sb.append(addQuotes(entry.getKey()));
sb.append(" ");
sb.append(entry.getValue());
sb.append(",");
}
try {
session.execute(String
.format("CREATE TABLE %s.%s (%s timeuuid, %s PRIMARY KEY (%s)) WITH compression = {'sstable_compression': ''}",
STREAMING.STREAMING_KEYSPACE_NAME, addQuotes(tableName), addQuotes(timestampColumnName),
sb.toString(), addQuotes(timestampColumnName)));
} catch (AlreadyExistsException e) {
log.info("Stream table {} already exists", tableName);
}
}
public Insert createInsertStatement(String streamName, List<ColumnNameTypeValue> columns, String timestampColumnName) {
Insert insert = QueryBuilder.insertInto(addQuotes(STREAMING.STREAMING_KEYSPACE_NAME), addQuotes(streamName));
for (ColumnNameTypeValue column : columns) {
insert.value(addQuotes(column.getColumn()), column.getValue());
}
insert.value(addQuotes(timestampColumnName), UUIDs.timeBased());
return insert;
}
public void alterTable(String streamName, Set<String> oldColumnNames, List<ColumnNameTypeValue> columns) {
StringBuilder sb = new StringBuilder();
for (Entry<String, String> entry : getStreamFieldsAndTypes(columns).entrySet()) {
if (!oldColumnNames.contains(entry.getKey())) {
sb.append(String.format("ALTER TABLE %s.%s ADD %s %s;", STREAMING.STREAMING_KEYSPACE_NAME,
addQuotes(streamName), addQuotes(entry.getKey()), entry.getValue()));
}
}
if (!"".equals(sb.toString())) {
session.execute(sb.toString());
}
}
private String addQuotes(String source) {
return "\"".concat(source).concat("\"");
}
private HashMap<String, String> getStreamFieldsAndTypes(List<ColumnNameTypeValue> columns) {
HashMap<String, String> fields = new HashMap<String, String>();
for (ColumnNameTypeValue column : columns) {
switch (column.getType()) {
case BOOLEAN:
fields.put(column.getColumn(), DataType.Name.BOOLEAN.toString());
break;
case DOUBLE:
fields.put(column.getColumn(), DataType.Name.DOUBLE.toString());
break;
case FLOAT:
fields.put(column.getColumn(), DataType.Name.FLOAT.toString());
break;
case INTEGER:
fields.put(column.getColumn(), DataType.Name.INT.toString());
break;
case LONG:
fields.put(column.getColumn(), DataType.Name.DOUBLE.toString());
break;
case STRING:
fields.put(column.getColumn(), DataType.Name.TEXT.toString());
break;
default:
throw new RuntimeException("Unsupported Column type");
}
}
return fields;
}
public HashMap<String, Integer> getTableNames(){
return tablenames;
}
public Session getSession(){
return session;
}
}