package eu.europeana.cloud.service.uis.persistent.dao;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.exceptions.NoHostAvailableException;
import eu.europeana.cloud.cassandra.CassandraConnectionProvider;
import eu.europeana.cloud.common.exceptions.ProviderDoesNotExistException;
import eu.europeana.cloud.common.model.CloudId;
import eu.europeana.cloud.common.model.IdentifierErrorInfo;
import eu.europeana.cloud.common.model.LocalId;
import eu.europeana.cloud.service.uis.exception.DatabaseConnectionException;
import eu.europeana.cloud.service.uis.exception.RecordDatasetEmptyException;
import eu.europeana.cloud.service.uis.status.IdentifierErrorTemplate;
/**
* Dao providing access to the search based on record id and provider id
* operations
*
* @author Yorgos.Mamakis@ kb.nl
*
*/
public class CassandraLocalIdDAO {
private String hostList;
private String port;
private String keyspaceName;
private CassandraConnectionProvider dbService;
private PreparedStatement insertStatement;
private PreparedStatement deleteStatement;
private PreparedStatement updateStatement;
private PreparedStatement searchByProviderStatement;
private PreparedStatement searchByRecordIdStatement;
private PreparedStatement searchByProviderAndRecordLessThanStatement;
/**
* The LocalId Dao
*
* @param dbService The service that exposes the database connection
*/
public CassandraLocalIdDAO(CassandraConnectionProvider dbService) {
this.dbService = dbService;
this.hostList = dbService.getHosts();
this.port = dbService.getPort();
this.keyspaceName = dbService.getKeyspaceName();
prepareStatements();
}
private void prepareStatements() {
insertStatement = dbService.getSession().prepare(
"INSERT INTO Provider_Record_Id(provider_id,record_id,cloud_id,deleted) VALUES(?,?,?,false)");
insertStatement.setConsistencyLevel(dbService.getConsistencyLevel());
deleteStatement = dbService.getSession().prepare(
"UPDATE Provider_Record_Id SET deleted=true WHERE provider_id=? AND record_Id=?");
deleteStatement.setConsistencyLevel(dbService.getConsistencyLevel());
updateStatement = dbService.getSession().prepare(
"UPDATE Provider_Record_Id SET cloud_id=? WHERE provider_id=? AND record_Id=?");
updateStatement.setConsistencyLevel(dbService.getConsistencyLevel());
searchByProviderStatement = dbService.getSession().prepare(
"SELECT * FROM Provider_Record_Id WHERE provider_id=? AND deleted = ?");
searchByProviderStatement.setConsistencyLevel(dbService.getConsistencyLevel());
searchByRecordIdStatement = dbService.getSession().prepare(
"SELECT * FROM Provider_Record_Id WHERE provider_id=? AND record_id=? AND deleted=?");
searchByRecordIdStatement.setConsistencyLevel(dbService.getConsistencyLevel());
searchByProviderAndRecordLessThanStatement = dbService.getSession().prepare(
"SELECT * FROM Provider_Record_Id WHERE provider_id=? AND record_id>? AND deleted=? LIMIT ?");
searchByProviderAndRecordLessThanStatement.setConsistencyLevel(dbService.getConsistencyLevel());
}
public List<CloudId> searchById(boolean deleted, String... args) throws DatabaseConnectionException,
ProviderDoesNotExistException, RecordDatasetEmptyException {
try {
ResultSet rs = null;
if (args.length == 1) {
rs = dbService.getSession().execute(searchByProviderStatement.bind(args[0], deleted));
} else if (args.length >= 2) {
rs = dbService.getSession().execute(searchByRecordIdStatement.bind(args[0], args[1], deleted));
}
return createCloudIdsFromRs(rs);
} catch (NoHostAvailableException e) {
throw new DatabaseConnectionException(new IdentifierErrorInfo(
IdentifierErrorTemplate.DATABASE_CONNECTION_ERROR.getHttpCode(),
IdentifierErrorTemplate.DATABASE_CONNECTION_ERROR.getErrorInfo(hostList, port, e.getMessage())));
}
}
public List<CloudId> searchActive(String... args) throws DatabaseConnectionException,
ProviderDoesNotExistException, RecordDatasetEmptyException {
return searchById(false, args);
}
/**
* Enable pagination search on active local Id information
*
* @param startRecordId Record to start from
* @param limit The number of record to retrieve
* @param providerId The provider Identifier
* @return A list of CloudId objects
*/
public List<CloudId> searchActiveWithPagination(String startRecordId, int limit, String providerId) throws ProviderDoesNotExistException, RecordDatasetEmptyException, DatabaseConnectionException {
List<CloudId> first = searchActive(providerId,startRecordId);
if(first.size() > 0 && first.size() < limit) {
ResultSet lessThanRS = dbService.getSession().execute(searchByProviderAndRecordLessThanStatement.bind(providerId, startRecordId, false, limit - 1));
List<CloudId> result = createCloudIdsFromRs(lessThanRS);
result.add(0,first.get(0));
return result;
}else{
return first;
}
}
public List<CloudId> insert(String... args) throws DatabaseConnectionException, ProviderDoesNotExistException,
RecordDatasetEmptyException {
try {
dbService.getSession().execute(insertStatement.bind(args[0], args[1], args[2]));
} catch (NoHostAvailableException e) {
throw new DatabaseConnectionException(new IdentifierErrorInfo(
IdentifierErrorTemplate.DATABASE_CONNECTION_ERROR.getHttpCode(),
IdentifierErrorTemplate.DATABASE_CONNECTION_ERROR.getErrorInfo(hostList, port, e.getMessage())));
}
List<CloudId> cIds = new ArrayList<>();
CloudId cId = new CloudId();
LocalId lId = new LocalId();
lId.setProviderId(args[0]);
lId.setRecordId(args[1]);
cId.setLocalId(lId);
cId.setId(args[2]);
cIds.add(cId);
return cIds;
}
public void delete(String... args) throws DatabaseConnectionException {
try {
dbService.getSession().execute(deleteStatement.bind(args[0], args[1]));
} catch (NoHostAvailableException e) {
throw new DatabaseConnectionException(new IdentifierErrorInfo(
IdentifierErrorTemplate.DATABASE_CONNECTION_ERROR.getHttpCode(),
IdentifierErrorTemplate.DATABASE_CONNECTION_ERROR.getErrorInfo(hostList, port, e.getMessage())));
}
}
public void update(String... args) throws DatabaseConnectionException {
try {
dbService.getSession().execute(updateStatement.bind(args[0], args[1], args[2]));
} catch (NoHostAvailableException e) {
throw new DatabaseConnectionException(new IdentifierErrorInfo(
IdentifierErrorTemplate.DATABASE_CONNECTION_ERROR.getHttpCode(),
IdentifierErrorTemplate.DATABASE_CONNECTION_ERROR.getErrorInfo(hostList, port, e.getMessage())));
}
}
public String getHostList() {
return hostList;
}
public String getKeyspace() {
return keyspaceName;
}
private List<CloudId>
createCloudIdsFromRs(ResultSet rs) {
List<CloudId> cloudIds = new LinkedList<>();
if (rs != null) {
for (Row row : rs.all()) {
LocalId lId = new LocalId();
lId.setProviderId(row.getString("provider_Id"));
lId.setRecordId(row.getString("record_Id"));
CloudId cloudId = new CloudId();
cloudId.setId(row.getString("cloud_id"));
cloudId.setLocalId(lId);
cloudIds.add(cloudId);
}
}
return cloudIds;
}
public String getPort() {
return this.port;
}
}