spring-cassandra now compiling

This commit is contained in:
Matthew Adams
2013-11-25 18:33:44 -06:00
parent af0273b864
commit 86224eb06d
178 changed files with 4 additions and 16807 deletions

View File

@@ -22,6 +22,7 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.cassandra.core.CassandraOperations;
import org.springframework.cassandra.core.CassandraTemplate;
import org.springframework.cassandra.core.Keyspace;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
@@ -31,7 +32,6 @@ import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.CassandraAdminOperations;
import org.springframework.data.cassandra.core.CassandraAdminTemplate;
import org.springframework.data.cassandra.core.Keyspace;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;

View File

@@ -5,6 +5,7 @@ import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cassandra.core.Keyspace;
import org.springframework.cassandra.core.SessionCallback;
import org.springframework.cassandra.support.CassandraExceptionTranslator;
import org.springframework.cassandra.support.exception.CassandraTableExistsException;

View File

@@ -24,6 +24,7 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cassandra.core.Keyspace;
import org.springframework.cassandra.support.CassandraExceptionTranslator;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;

View File

@@ -11,8 +11,8 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cassandra.core.Keyspace;
import org.springframework.context.ApplicationContext;
import org.springframework.data.cassandra.core.Keyspace;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;

View File

@@ -1,80 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.DriverException;
/**
* Created a PreparedStatement and retrieved the PreparedStatement from cache if the statement has been prepared
* previously. In general, this creator should be used over the {@link SimplePreparedStatementCreator} as it provides
* better performance.
*
* <p>
* There is overhead in Cassandra when Preparing a Statement. This is negligible on a single data center configuration,
* but when your cluster spans multiple data centers, preparing the same statement over and over again is not necessary
* and causes performance issues in high throughput use cases.
* </p>
*
* @author David Webb
*
*/
public class CachedPreparedStatementCreator implements PreparedStatementCreator, CqlProvider {
private static Logger log = LoggerFactory.getLogger(CachedPreparedStatementCreator.class);
private final String cql;
private PreparedStatement cache;
/**
* Create a CachedPreparedStatementCreator from the provided CQL.
*
* @param cql
*/
public CachedPreparedStatementCreator(String cql) {
Assert.notNull(cql, "CQL is required to create a PreparedStatement");
this.cql = cql;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.PreparedStatementCreator#createPreparedStatement(com.datastax.driver.core.Session)
*/
@Override
public PreparedStatement createPreparedStatement(Session session) throws DriverException {
if (cache == null) {
log.debug("PreparedStatement cache is null, preparing new Statement");
cache = session.prepare(getCql());
} else {
log.debug("Using cached PreparedStatement");
}
return cache;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CqlProvider#getCql()
*/
@Override
public String getCql() {
return this.cql;
}
}

View File

@@ -1,401 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.springframework.dao.DataAccessException;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Session;
/**
* Operations for interacting with Cassandra at the lowest level. This interface provides Exception Translation.
*
* @author David Webb
* @author Matthew Adams
*/
public interface CassandraOperations {
/**
* Executes the supplied {@link SessionCallback} in the current Template Session. The implementation of
* SessionCallback can decide whether or not to <code>execute()</code> or <code>executeAsync()</code> the operation.
*
* @param sessionCallback
* @return Type<T> defined in the SessionCallback
*/
<T> T execute(SessionCallback<T> sessionCallback) throws DataAccessException;
/**
* Executes the supplied CQL Query and returns nothing.
*
* @param cql
*/
void execute(final String cql) throws DataAccessException;
/**
* Executes the supplied CQL Query Asynchronously and returns nothing.
*
* @param cql The CQL Statement to execute
*/
void executeAsynchronously(final String cql) throws DataAccessException;
/**
* Executes the provided CQL Query, and extracts the results with the ResultSetExtractor.
*
* @param cql The Query
* @param rse The implementation for extracting the ResultSet
*
* @return Type <T> specified in the ResultSetExtractor
* @throws DataAccessException
*/
<T> T query(final String cql, ResultSetExtractor<T> rse) throws DataAccessException;
/**
* Executes the provided CQL Query asynchronously, and extracts the results with the ResultSetFutureExtractor
*
* @param cql The Query
* @param rse The implementation for extracting the future results
* @return
* @throws DataAccessException
*/
<T> T queryAsynchronously(final String cql, ResultSetFutureExtractor<T> rse) throws DataAccessException;
/**
* Executes the provided CQL Query, and then processes the results with the <code>RowCallbackHandler</code>.
*
* @param cql The Query
* @param rch The implementation for processing the rows returned.
* @throws DataAccessException
*/
void query(final String cql, RowCallbackHandler rch) throws DataAccessException;
/**
* Processes the ResultSet through the RowCallbackHandler and return nothing. This is used internal to the Template
* for core operations, but is made available through Operations in the event you have a ResultSet to process. The
* ResultsSet could come from a ResultSetFuture after an asynchronous query.
*
* @param resultSet Results to process
* @param rch RowCallbackHandler with the processing implementation
* @throws DataAccessException
*/
void process(ResultSet resultSet, RowCallbackHandler rch) throws DataAccessException;
/**
* Executes the provided CQL Query, and maps all Rows returned with the supplied RowMapper.
*
* @param cql The Query
* @param rowMapper The implementation for mapping all rows
* @return List of <T> processed by the RowMapper
* @throws DataAccessException
*/
<T> List<T> query(final String cql, RowMapper<T> rowMapper) throws DataAccessException;
/**
* Processes the ResultSet through the RowMapper and returns the List of mapped Rows. This is used internal to the
* Template for core operations, but is made available through Operations in the event you have a ResultSet to
* process. The ResultsSet could come from a ResultSetFuture after an asynchronous query.
*
* @param resultSet Results to process
* @param rowMapper RowMapper with the processing implementation
* @return List of <T> generated by the RowMapper
* @throws DataAccessException
*/
<T> List<T> process(ResultSet resultSet, RowMapper<T> rowMapper) throws DataAccessException;
/**
* Executes the provided CQL Query, and maps <b>ONE</b> Row returned with the supplied RowMapper.
*
* <p>
* This expects only ONE row to be returned. More than one Row will cause an Exception to be thrown.
* </p>
*
* @param cql The Query
* @param rowMapper The implementation for convert the Row to <T>
* @return Object<T>
* @throws DataAccessException
*/
<T> T queryForObject(final String cql, RowMapper<T> rowMapper) throws DataAccessException;
/**
* Process a ResultSet through a RowMapper. This is used internal to the Template for core operations, but is made
* available through Operations in the event you have a ResultSet to process. The ResultsSet could come from a
* ResultSetFuture after an asynchronous query.
*
* @param resultSet
* @param rowMapper
* @return
* @throws DataAccessException
*/
<T> T processOne(ResultSet resultSet, RowMapper<T> rowMapper) throws DataAccessException;
/**
* Executes the provided query and tries to return the first column of the first Row as a Class<T>.
*
* @param cql The Query
* @param requiredType Valid Class that Cassandra Data Types can be converted to.
* @return The Object<T> - item [0,0] in the result table of the query.
* @throws DataAccessException
*/
<T> T queryForObject(final String cql, Class<T> requiredType) throws DataAccessException;
/**
* Process a ResultSet, trying to convert the first columns of the first Row to Class<T>. This is used internal to the
* Template for core operations, but is made available through Operations in the event you have a ResultSet to
* process. The ResultsSet could come from a ResultSetFuture after an asynchronous query.
*
* @param resultSet
* @param requiredType
* @return
* @throws DataAccessException
*/
<T> T processOne(ResultSet resultSet, Class<T> requiredType) throws DataAccessException;
/**
* Executes the provided CQL Query and maps <b>ONE</b> Row to a basic Map of Strings and Objects. If more than one Row
* is returned from the Query, an exception will be thrown.
*
* @param cql The Query
* @return Map representing the results of the Query
* @throws DataAccessException
*/
Map<String, Object> queryForMap(final String cql) throws DataAccessException;
/**
* Process a ResultSet with <b>ONE</b> Row and convert to a Map. This is used internal to the Template for core
* operations, but is made available through Operations in the event you have a ResultSet to process. The ResultsSet
* could come from a ResultSetFuture after an asynchronous query.
*
* @param resultSet
* @return
* @throws DataAccessException
*/
Map<String, Object> processMap(ResultSet resultSet) throws DataAccessException;
/**
* Executes the provided CQL and returns all values in the first column of the Results as a List of the Type in the
* second argument.
*
* @param cql The Query
* @param elementType Type to cast the data values to
* @return List of elementType
* @throws DataAccessException
*/
<T> List<T> queryForList(final String cql, Class<T> elementType) throws DataAccessException;
/**
* Process a ResultSet and convert the first column of the results to a List. This is used internal to the Template
* for core operations, but is made available through Operations in the event you have a ResultSet to process. The
* ResultsSet could come from a ResultSetFuture after an asynchronous query.
*
* @param resultSet
* @param elementType
* @return
* @throws DataAccessException
*/
<T> List<T> processList(ResultSet resultSet, Class<T> elementType) throws DataAccessException;
/**
* Executes the provided CQL and converts the results to a basic List of Maps. Each element in the List represents a
* Row returned from the Query. Each Row's columns are put into the map as column/value.
*
* @param cql The Query
* @return List of Maps with the query results
* @throws DataAccessException
*/
List<Map<String, Object>> queryForListOfMap(final String cql) throws DataAccessException;
/**
* Process a ResultSet and convert it to a List of Maps with column/value. This is used internal to the Template for
* core operations, but is made available through Operations in the event you have a ResultSet to process. The
* ResultsSet could come from a ResultSetFuture after an asynchronous query.
*
* @param resultSet
* @return
* @throws DataAccessException
*/
List<Map<String, Object>> processListOfMap(ResultSet resultSet) throws DataAccessException;
/**
* Converts the CQL provided into a {@link SimplePreparedStatementCreator}. <b>This can only be used for CQL
* Statements that do not have data binding.</b> The results of the PreparedStatement are processed with
* PreparedStatementCallback implementation provided by the Application Code.
*
* @param cql The CQL Statement to Execute
* @param action What to do with the results of the PreparedStatement
* @return Type<T> as determined by the supplied Callback.
* @throws DataAccessException
*/
<T> T execute(String cql, PreparedStatementCallback<T> action) throws DataAccessException;
/**
* Uses the provided PreparedStatementCreator to prepare a new Session call, then executes the statement and processes
* the statement using the provided Callback. <b>This can only be used for CQL Statements that do not have data
* binding.</b> The results of the PreparedStatement are processed with PreparedStatementCallback implementation
* provided by the Application Code.
*
* @param psc The implementation to create the PreparedStatement
* @param action What to do with the results of the PreparedStatement
* @return Type<T> as determined by the supplied Callback.
* @throws DataAccessException
*/
<T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action) throws DataAccessException;
/**
* Converts the CQL provided into a {@link SimplePreparedStatementCreator}. Then, the PreparedStatementBinder will
* bind its values to the bind variables in the provided CQL String. The results of the PreparedStatement are
* processed with the ResultSetExtractor implementation provided by the Application Code. The can return any object,
* including a List of Objects to support the ResultSet processing.
*
* @param cql The Query to Prepare
* @param psb The Binding implementation
* @param rse The implementation for extracting the results of the query.
* @return Type<T> generated by the ResultSetExtractor
* @throws DataAccessException
*/
<T> T query(final String cql, PreparedStatementBinder psb, ResultSetExtractor<T> rse) throws DataAccessException;
/**
* Converts the CQL provided into a {@link SimplePreparedStatementCreator}. Then, the PreparedStatementBinder will
* bind its values to the bind variables in the provided CQL String. The results of the PreparedStatement are
* processed with the RowCallbackHandler implementation provided and nothing is returned.
*
* @param cql The Query to Prepare
* @param psb The Binding implementation
* @param rch The RowCallbackHandler for processing the ResultSet
* @throws DataAccessException
*/
void query(final String cql, PreparedStatementBinder psb, RowCallbackHandler rch) throws DataAccessException;
/**
* Converts the CQL provided into a {@link SimplePreparedStatementCreator}. Then, the PreparedStatementBinder will
* bind its values to the bind variables in the provided CQL String. The results of the PreparedStatement are
* processed with the RowMapper implementation provided and a List is returned with elements of Type <T> for each Row
* returned.
*
* @param cql The Query to Prepare
* @param psb The Binding implementation
* @param rowMapper The implementation for Mapping a Row to Type <T>
* @return List of <T> for each Row returned from the Query.
* @throws DataAccessException
*/
<T> List<T> query(final String cql, PreparedStatementBinder psb, RowMapper<T> rowMapper) throws DataAccessException;
/**
* Uses the provided PreparedStatementCreator to prepare a new Session call. <b>This can only be used for CQL
* Statements that do not have data binding.</b> The results of the PreparedStatement are processed with
* ResultSetExtractor implementation provided by the Application Code.
*
* @param psc The implementation to create the PreparedStatement
* @param rse Implementation for extracting from the ResultSet
* @return Type <T> which is the output of the ResultSetExtractor
* @throws DataAccessException
*/
<T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse) throws DataAccessException;
/**
* Uses the provided PreparedStatementCreator to prepare a new Session call. <b>This can only be used for CQL
* Statements that do not have data binding.</b> The results of the PreparedStatement are processed with
* RowCallbackHandler and nothing is returned.
*
* @param psc The implementation to create the PreparedStatement
* @param rch The implementation to process Results
* @throws DataAccessException
*/
void query(PreparedStatementCreator psc, RowCallbackHandler rch) throws DataAccessException;
/**
* Uses the provided PreparedStatementCreator to prepare a new Session call. <b>This can only be used for CQL
* Statements that do not have data binding.</b> The results of the PreparedStatement are processed with RowMapper
* implementation provided and a List is returned with elements of Type <T> for each Row returned.
*
* @param psc The implementation to create the PreparedStatement
* @param rowMapper The implementation for mapping each Row returned.
* @return List of Type <T> mapped from each Row in the Results
* @throws DataAccessException
*/
<T> List<T> query(PreparedStatementCreator psc, RowMapper<T> rowMapper) throws DataAccessException;
/**
* Uses the provided PreparedStatementCreator to prepare a new Session call. Binds the values from the
* PreparedStatementBinder to the available bind variables. The results of the PreparedStatement are processed with
* ResultSetExtractor implementation provided by the Application Code.
*
* @param psc The implementation to create the PreparedStatement
* @param psb The implementation to bind variables to values
* @param rse Implementation for extracting from the ResultSet
* @return Type <T> which is the output of the ResultSetExtractor
* @throws DataAccessException
*/
<T> T query(PreparedStatementCreator psc, final PreparedStatementBinder psb, final ResultSetExtractor<T> rse)
throws DataAccessException;
/**
* Uses the provided PreparedStatementCreator to prepare a new Session call. Binds the values from the
* PreparedStatementBinder to the available bind variables. The results of the PreparedStatement are processed with
* RowCallbackHandler and nothing is returned.
*
* @param psc The implementation to create the PreparedStatement
* @param psb The implementation to bind variables to values
* @param rch The implementation to process Results
* @return Type <T> which is the output of the ResultSetExtractor
* @throws DataAccessException
*/
void query(PreparedStatementCreator psc, final PreparedStatementBinder psb, final RowCallbackHandler rch)
throws DataAccessException;
/**
* Uses the provided PreparedStatementCreator to prepare a new Session call. Binds the values from the
* PreparedStatementBinder to the available bind variables. The results of the PreparedStatement are processed with
* RowMapper implementation provided and a List is returned with elements of Type <T> for each Row returned.
*
* @param psc The implementation to create the PreparedStatement
* @param psb The implementation to bind variables to values
* @param rowMapper The implementation for mapping each Row returned.
* @return Type <T> which is the output of the ResultSetExtractor
* @throws DataAccessException
*/
<T> List<T> query(PreparedStatementCreator psc, final PreparedStatementBinder psb, final RowMapper<T> rowMapper)
throws DataAccessException;
/**
* Describe the current Ring. This uses the provided {@link RingMemberHostMapper} to provide the basics of the
* Cassandra Ring topology.
*
* @return The list of ring tokens that are active in the cluster
*/
List<RingMember> describeRing() throws DataAccessException;
/**
* Describe the current Ring. Application code must provide its own {@link HostMapper} implementation to process the
* lists of hosts returned by the Cassandra Cluster Metadata.
*
* @param hostMapper The implementation to use for host mapping.
* @return Collection generated by the provided HostMapper.
* @throws DataAccessException
*/
<T> Collection<T> describeRing(HostMapper<T> hostMapper) throws DataAccessException;
/**
* Get the current Session used for operations in the implementing class.
*
* @return The DataStax Driver Session Object
*/
Session getSession();
}

View File

@@ -1,562 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.cassandra.support.CassandraAccessor;
import org.springframework.dao.DataAccessException;
import org.springframework.data.cassandra.core.CassandraDataTemplate;
import org.springframework.util.Assert;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.ColumnDefinitions;
import com.datastax.driver.core.ColumnDefinitions.Definition;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.Metadata;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.DriverException;
/**
* <b>This is the Central class in the Cassandra core package.</b> It simplifies the use of Cassandra and helps to avoid
* common errors. It executes the core Cassandra workflow, leaving application code to provide CQL and result
* extraction. This class execute CQL Queries, provides different ways to extract/map results, and provides Exception
* translation to the generic, more informative exception hierarchy defined in the <code>org.springframework.dao</code>
* package.
*
* <p>
* For working with POJOs, use the {@link CassandraDataTemplate}.
* </p>
*
* @author David Webb
* @author Matthew Adams
*/
public class CassandraTemplate extends CassandraAccessor implements CassandraOperations {
/**
* Blank constructor. You must wire in the Session before use.
*
*/
public CassandraTemplate() {
}
/**
* Constructor used for a basic template configuration
*
* @param session must not be {@literal null}.
*/
public CassandraTemplate(Session session) {
setSession(session);
afterPropertiesSet();
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraOperations#execute(org.springframework.data.cassandra.core.SessionCallback)
*/
@Override
public <T> T execute(SessionCallback<T> sessionCallback) throws DataAccessException {
return doExecute(sessionCallback);
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraOperations#execute(java.lang.String)
*/
@Override
public void execute(final String cql) throws DataAccessException {
doExecute(cql);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(java.lang.String, org.springframework.cassandra.core.FutureResultSetExtractor)
*/
@Override
public <T> T queryAsynchronously(final String cql, ResultSetFutureExtractor<T> rse) throws DataAccessException {
return rse.extractData(execute(new SessionCallback<ResultSetFuture>() {
@Override
public ResultSetFuture doInSession(Session s) throws DataAccessException {
return s.executeAsync(cql);
}
}));
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(java.lang.String, org.springframework.cassandra.core.ResultSetExtractor)
*/
public <T> T query(String cql, ResultSetExtractor<T> rse) throws DataAccessException {
ResultSet rs = doExecute(cql);
return rse.extractData(rs);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(java.lang.String, org.springframework.cassandra.core.RowCallbackHandler)
*/
public void query(String cql, RowCallbackHandler rch) throws DataAccessException {
process(doExecute(cql), rch);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(java.lang.String, org.springframework.cassandra.core.RowMapper)
*/
public <T> List<T> query(String cql, RowMapper<T> rowMapper) throws DataAccessException {
return process(doExecute(cql), rowMapper);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#queryForList(java.lang.String)
*/
public List<Map<String, Object>> queryForListOfMap(String cql) throws DataAccessException {
return processListOfMap(doExecute(cql));
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#queryForList(java.lang.String, java.lang.Class)
*/
public <T> List<T> queryForList(String cql, Class<T> elementType) throws DataAccessException {
return processList(doExecute(cql), elementType);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#queryForMap(java.lang.String)
*/
public Map<String, Object> queryForMap(String cql) throws DataAccessException {
return processMap(doExecute(cql));
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#queryForObject(java.lang.String, java.lang.Class)
*/
public <T> T queryForObject(String cql, Class<T> requiredType) throws DataAccessException {
return processOne(doExecute(cql), requiredType);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#queryForObject(java.lang.String, org.springframework.cassandra.core.RowMapper)
*/
public <T> T queryForObject(String cql, RowMapper<T> rowMapper) throws DataAccessException {
return processOne(doExecute(cql), rowMapper);
}
/**
* Execute a command at the Session Level
*
* @param callback
* @return
*/
protected <T> T doExecute(SessionCallback<T> callback) {
Assert.notNull(callback);
try {
return callback.doInSession(getSession());
} catch (DataAccessException e) {
throw throwTranslated(e);
}
}
/**
* Execute a command at the Session Level
*
* @param callback
* @return
*/
protected ResultSet doExecute(final String cql) {
return doExecute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(cql);
}
});
}
/**
* Execute a command at the Session Level
*
* @param callback
* @return
*/
protected ResultSet doExecute(final BoundStatement bs) {
return doExecute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(bs);
}
});
}
/**
* @param row
* @return
*/
protected Object firstColumnToObject(Row row) {
ColumnDefinitions cols = row.getColumnDefinitions();
if (cols.size() == 0) {
return null;
}
return cols.getType(0).deserialize(row.getBytesUnsafe(0));
}
/**
* @param row
* @return
*/
protected Map<String, Object> toMap(Row row) {
if (row == null) {
return null;
}
ColumnDefinitions cols = row.getColumnDefinitions();
Map<String, Object> map = new HashMap<String, Object>(cols.size());
for (Definition def : cols.asList()) {
String name = def.getName();
map.put(name, def.getType().deserialize(row.getBytesUnsafe(name)));
}
return map;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#describeRing()
*/
@Override
public List<RingMember> describeRing() throws DataAccessException {
return new ArrayList<RingMember>(describeRing(new RingMemberHostMapper()));
}
/**
* Pulls the list of Hosts for the current Session
*
* @return
*/
private Set<Host> getHosts() {
/*
* Get the cluster metadata for this session
*/
Metadata clusterMetadata = doExecute(new SessionCallback<Metadata>() {
@Override
public Metadata doInSession(Session s) throws DataAccessException {
return s.getCluster().getMetadata();
}
});
/*
* Get all hosts in the cluster
*/
Set<Host> hosts = clusterMetadata.getAllHosts();
return hosts;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#describeRing(org.springframework.cassandra.core.HostMapper)
*/
@Override
public <T> Collection<T> describeRing(HostMapper<T> hostMapper) throws DataAccessException {
Set<Host> hosts = getHosts();
return hostMapper.mapHosts(hosts);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#executeAsynchronously(java.lang.String)
*/
@Override
public void executeAsynchronously(final String cql) throws DataAccessException {
execute(new SessionCallback<Object>() {
@Override
public Object doInSession(Session s) throws DataAccessException {
return s.executeAsync(cql);
}
});
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#process(com.datastax.driver.core.ResultSet, org.springframework.cassandra.core.RowCallbackHandler)
*/
@Override
public void process(ResultSet resultSet, RowCallbackHandler rch) throws DataAccessException {
try {
for (Row row : resultSet.all()) {
rch.processRow(row);
}
} catch (DriverException dx) {
throwTranslated(dx);
}
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#process(com.datastax.driver.core.ResultSet, org.springframework.cassandra.core.RowMapper)
*/
@Override
public <T> List<T> process(ResultSet resultSet, RowMapper<T> rowMapper) throws DataAccessException {
List<T> mappedRows = new ArrayList<T>();
try {
int i = 0;
for (Row row : resultSet.all()) {
mappedRows.add(rowMapper.mapRow(row, i++));
}
} catch (DriverException dx) {
throwTranslated(dx);
}
return mappedRows;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#processOne(com.datastax.driver.core.ResultSet, org.springframework.cassandra.core.RowMapper)
*/
@Override
public <T> T processOne(ResultSet resultSet, RowMapper<T> rowMapper) throws DataAccessException {
T row = null;
Assert.notNull(resultSet, "ResultSet cannot be null");
try {
List<Row> rows = resultSet.all();
Assert.notNull(rows, "null row list returned from query");
Assert.isTrue(rows.size() == 1, "row list has " + rows.size() + " rows instead of one");
row = rowMapper.mapRow(rows.get(0), 0);
} catch (DriverException dx) {
throwTranslated(dx);
}
return row;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#processOne(com.datastax.driver.core.ResultSet, java.lang.Class)
*/
@SuppressWarnings("unchecked")
@Override
public <T> T processOne(ResultSet resultSet, Class<T> requiredType) throws DataAccessException {
if (resultSet == null) {
return null;
}
Row row = resultSet.one();
if (row == null) {
return null;
}
return (T) firstColumnToObject(row);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#processMap(com.datastax.driver.core.ResultSet)
*/
@Override
public Map<String, Object> processMap(ResultSet resultSet) throws DataAccessException {
if (resultSet == null) {
return null;
}
return toMap(resultSet.one());
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#processList(com.datastax.driver.core.ResultSet, java.lang.Class)
*/
@Override
public <T> List<T> processList(ResultSet resultSet, Class<T> elementType) throws DataAccessException {
List<Row> rows = resultSet.all();
List<T> list = new ArrayList<T>(rows.size());
for (Row row : rows) {
list.add((T) firstColumnToObject(row));
}
return list;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#processListOfMap(com.datastax.driver.core.ResultSet)
*/
@Override
public List<Map<String, Object>> processListOfMap(ResultSet resultSet) throws DataAccessException {
List<Row> rows = resultSet.all();
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(rows.size());
for (Row row : rows) {
list.add(toMap(row));
}
return list;
}
/**
* Attempt to translate a Runtime Exception to a Spring Data Exception
*
* @param ex
* @return
*/
protected RuntimeException throwTranslated(RuntimeException ex) {
RuntimeException resolved = getExceptionTranslator().translateExceptionIfPossible(ex);
return resolved == null ? ex : resolved;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#execute(org.springframework.cassandra.core.PreparedStatementCreator, org.springframework.cassandra.core.PreparedStatementCallback)
*/
@Override
public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action) {
try {
PreparedStatement ps = psc.createPreparedStatement(getSession());
return action.doInPreparedStatement(ps);
} catch (DriverException dx) {
throwTranslated(dx);
}
return null;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#execute(java.lang.String, org.springframework.cassandra.core.PreparedStatementCallback)
*/
@Override
public <T> T execute(String cql, PreparedStatementCallback<T> action) {
return execute(new SimplePreparedStatementCreator(cql), action);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(org.springframework.cassandra.core.PreparedStatementCreator, org.springframework.cassandra.core.ResultSetExtractor)
*/
@Override
public <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse) throws DataAccessException {
return query(psc, null, rse);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(org.springframework.cassandra.core.PreparedStatementCreator, org.springframework.cassandra.core.RowCallbackHandler)
*/
@Override
public void query(PreparedStatementCreator psc, RowCallbackHandler rch) throws DataAccessException {
query(psc, null, rch);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(org.springframework.cassandra.core.PreparedStatementCreator, org.springframework.cassandra.core.RowMapper)
*/
@Override
public <T> List<T> query(PreparedStatementCreator psc, RowMapper<T> rowMapper) throws DataAccessException {
return query(psc, null, rowMapper);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(org.springframework.cassandra.core.PreparedStatementCreator, org.springframework.cassandra.core.PreparedStatementSetter, org.springframework.cassandra.core.ResultSetExtractor)
*/
public <T> T query(PreparedStatementCreator psc, final PreparedStatementBinder psb, final ResultSetExtractor<T> rse)
throws DataAccessException {
Assert.notNull(rse, "ResultSetExtractor must not be null");
logger.debug("Executing prepared CQL query");
return execute(psc, new PreparedStatementCallback<T>() {
public T doInPreparedStatement(PreparedStatement ps) throws DriverException {
ResultSet rs = null;
BoundStatement bs = null;
if (psb != null) {
bs = psb.bindValues(ps);
} else {
bs = ps.bind();
}
rs = doExecute(bs);
return rse.extractData(rs);
}
});
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(java.lang.String, org.springframework.cassandra.core.PreparedStatementSetter, org.springframework.cassandra.core.ResultSetExtractor)
*/
@Override
public <T> T query(String cql, PreparedStatementBinder psb, ResultSetExtractor<T> rse) throws DataAccessException {
return query(new SimplePreparedStatementCreator(cql), psb, rse);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(java.lang.String, org.springframework.cassandra.core.PreparedStatementSetter, org.springframework.cassandra.core.RowCallbackHandler)
*/
@Override
public void query(String cql, PreparedStatementBinder psb, RowCallbackHandler rch) throws DataAccessException {
query(new SimplePreparedStatementCreator(cql), psb, rch);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(java.lang.String, org.springframework.cassandra.core.PreparedStatementSetter, org.springframework.cassandra.core.RowMapper)
*/
@Override
public <T> List<T> query(String cql, PreparedStatementBinder psb, RowMapper<T> rowMapper) throws DataAccessException {
return query(new SimplePreparedStatementCreator(cql), psb, rowMapper);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(org.springframework.cassandra.core.PreparedStatementCreator, org.springframework.cassandra.core.PreparedStatementBinder, org.springframework.cassandra.core.RowCallbackHandler)
*/
@Override
public void query(PreparedStatementCreator psc, final PreparedStatementBinder psb, final RowCallbackHandler rch)
throws DataAccessException {
Assert.notNull(rch, "RowCallbackHandler must not be null");
logger.debug("Executing prepared CQL query");
execute(psc, new PreparedStatementCallback<Object>() {
public Object doInPreparedStatement(PreparedStatement ps) throws DriverException {
ResultSet rs = null;
BoundStatement bs = null;
if (psb != null) {
bs = psb.bindValues(ps);
} else {
bs = ps.bind();
}
rs = doExecute(bs);
process(rs, rch);
return null;
}
});
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CassandraOperations#query(org.springframework.cassandra.core.PreparedStatementCreator, org.springframework.cassandra.core.PreparedStatementBinder, org.springframework.cassandra.core.RowMapper)
*/
@Override
public <T> List<T> query(PreparedStatementCreator psc, final PreparedStatementBinder psb, final RowMapper<T> rowMapper)
throws DataAccessException {
Assert.notNull(rowMapper, "RowMapper must not be null");
logger.debug("Executing prepared CQL query");
return execute(psc, new PreparedStatementCallback<List<T>>() {
public List<T> doInPreparedStatement(PreparedStatement ps) throws DriverException {
ResultSet rs = null;
BoundStatement bs = null;
if (psb != null) {
bs = psb.bindValues(ps);
} else {
bs = ps.bind();
}
rs = doExecute(bs);
return process(rs, rowMapper);
}
});
}
}

View File

@@ -1,139 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import java.util.LinkedList;
import java.util.List;
import org.springframework.util.Assert;
import com.datastax.driver.core.DataType;
/**
* @author David Webb
*
*/
public class CqlParameter {
/** The name of the parameter, if any */
private String name;
/** SQL type constant from {@link DataType} */
private final DataType type;
/** The scale to apply in case of a NUMERIC or DECIMAL type, if any */
private Integer scale;
/**
* Create a new anonymous CqlParameter, supplying the SQL type.
*
* @param type Cassandra Data Type of the parameter according to {@link DataType}
*/
public CqlParameter(DataType type) {
this.type = type;
}
/**
* Create a new anonymous CqlParameter, supplying the SQL type.
*
* @param type Cassandra Data Type of the parameter according to {@link DataType}
* @param scale the number of digits after the decimal point
*/
public CqlParameter(DataType type, int scale) {
this.type = type;
this.scale = scale;
}
/**
* Create a new CqlParameter, supplying name and SQL type.
*
* @param name name of the parameter, as used in input and output maps
* @param type Cassandra Data Type of the parameter according to {@link DataType}
*/
public CqlParameter(String name, DataType type) {
this.name = name;
this.type = type;
}
/**
* Create a new CqlParameter, supplying name and SQL type.
*
* @param name name of the parameter, as used in input and output maps
* @param type Cassandra Data Type of the parameter according to {@link DataType}
* @param scale the number of digits after the decimal point (for DECIMAL and NUMERIC types)
*/
public CqlParameter(String name, DataType type, int scale) {
this.name = name;
this.type = type;
this.scale = scale;
}
/**
* Copy constructor.
*
* @param otherParam the CqlParameter object to copy from
*/
public CqlParameter(CqlParameter otherParam) {
Assert.notNull(otherParam, "CqlParameter object must not be null");
this.name = otherParam.name;
this.type = otherParam.type;
this.scale = otherParam.scale;
}
/**
* Return the name of the parameter.
*/
public String getName() {
return this.name;
}
/**
* Return the SQL type of the parameter.
*/
public DataType getType() {
return this.type;
}
/**
* Return the scale of the parameter, if any.
*/
public Integer getScale() {
return this.scale;
}
/**
* Return whether this parameter holds input values that should be set before execution even if they are {@code null}.
* <p>
* This implementation always returns {@code true}.
*/
public boolean isInputValueProvided() {
return true;
}
/**
* Convert a list of JDBC types, as defined in {@code java.sql.Types}, to a List of CqlParameter objects as used in
* this package.
*/
public static List<CqlParameter> sqlTypesToAnonymousParameterList(DataType[] types) {
List<CqlParameter> result = new LinkedList<CqlParameter>();
if (types != null) {
for (DataType type : types) {
result.add(new CqlParameter(type));
}
}
return result;
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import com.datastax.driver.core.DataType;
/**
* @author David Webb
*
*/
public class CqlParameterValue extends CqlParameter {
private final Object value;
/**
* Create a new CqlParameterValue, supplying the Cassandra DataType.
*
* @param type Cassandra Data Type of the parameter according to {@link DataType}
* @param value the value object
*/
public CqlParameterValue(DataType type, Object value) {
super(type);
this.value = value;
}
/**
* Create a new CqlParameterValue, supplying the Cassandra DataType.
*
* @param type Cassandra Data Type of the parameter according to {@link DataType}
* @param scale the number of digits after the decimal point (for DECIMAL and NUMERIC types)
* @param value the value object
*/
public CqlParameterValue(DataType type, int scale, Object value) {
super(type, scale);
this.value = value;
}
/**
* Create a new CqlParameterValue based on the given CqlParameter declaration.
*
* @param declaredParam the declared CqlParameter to define a value for
* @param value the value object
*/
public CqlParameterValue(CqlParameter declaredParam, Object value) {
super(declaredParam);
this.value = value;
}
/**
* Return the value object that this parameter value holds.
*/
public Object getValue() {
return this.value;
}
}

View File

@@ -1,26 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
/**
* @author David Webb
*
*/
public interface CqlProvider {
String getCql();
}

View File

@@ -1,13 +0,0 @@
package org.springframework.cassandra.core;
import java.util.Collection;
import java.util.Set;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.exceptions.DriverException;
public interface HostMapper<T> {
Collection<T> mapHosts(Set<Host> host) throws DriverException;
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.exceptions.DriverException;
/**
* @author David Webb
*
*/
public interface PreparedStatementBinder {
BoundStatement bindValues(PreparedStatement ps) throws DriverException;
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import org.springframework.dao.DataAccessException;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.exceptions.DriverException;
/**
* @author David Webb
*
*/
public interface PreparedStatementCallback<T> {
T doInPreparedStatement(PreparedStatement ps) throws DriverException, DataAccessException;
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.DriverException;
/**
* Creates a PreparedStatement for the usage with the DataStax Java Driver
*
* @author David Webb
*
*/
public interface PreparedStatementCreator {
/**
* Create a statement in this session. Allows implementations to use PreparedStatements. The CassandraTemlate will
* attempt to cache the PreparedStatement for future use without the overhead of re-preparing on the entire cluster.
*
* @param session Session to use to create statement
* @return a prepared statement
* @throws DriverException there is no need to catch DriverException that may be thrown in the implementation of this
* method. The CassandraTemlate class will handle them.
*/
PreparedStatement createPreparedStatement(Session session) throws DriverException;
}

View File

@@ -1,202 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.util.Assert;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.DriverException;
/**
* @author David Webb
*
*/
public class PreparedStatementCreatorFactory {
/**
* The CQL, which won't change when the parameters change
*/
private final String cql;
/** List of CqlParameter objects. May not be {@code null}. */
private final List<CqlParameter> declaredParameters;
/**
* Create a new factory.
*/
public PreparedStatementCreatorFactory(String cql) {
this.cql = cql;
this.declaredParameters = new LinkedList<CqlParameter>();
}
/**
* Create a new factory with the given CQL and parameters.
*
* @param cql CQL
* @param declaredParameters list of {@link CqlParameter} objects
* @see CqlParameter
*/
public PreparedStatementCreatorFactory(String cql, List<CqlParameter> declaredParameters) {
this.cql = cql;
this.declaredParameters = declaredParameters;
}
/**
* Return a new PreparedStatementBinder for the given parameters.
*
* @param params list of parameters (may be {@code null})
*/
public PreparedStatementBinder newPreparedStatementBinder(List<CqlParameterValue> params) {
return new PreparedStatementCreatorImpl(params != null ? params : Collections.emptyList());
}
/**
* Return a new PreparedStatementBinder for the given parameters.
*
* @param params the parameter array (may be {@code null})
*/
public PreparedStatementBinder newPreparedStatementBinder(Object[] params) {
return new PreparedStatementCreatorImpl(params != null ? Arrays.asList(params) : Collections.emptyList());
}
/**
* Return a new PreparedStatementCreator for the given parameters.
*
* @param params list of parameters (may be {@code null})
*/
public PreparedStatementCreator newPreparedStatementCreator(List<CqlParameterValue> params) {
return new PreparedStatementCreatorImpl(params != null ? params : Collections.emptyList());
}
/**
* Return a new PreparedStatementCreator for the given parameters.
*
* @param params the parameter array (may be {@code null})
*/
public PreparedStatementCreator newPreparedStatementCreator(Object[] params) {
return new PreparedStatementCreatorImpl(params != null ? Arrays.asList(params) : Collections.emptyList());
}
/**
* Return a new PreparedStatementCreator for the given parameters.
*
* @param sqlToUse the actual SQL statement to use (if different from the factory's, for example because of named
* parameter expanding)
* @param params the parameter array (may be {@code null})
*/
public PreparedStatementCreator newPreparedStatementCreator(String sqlToUse, Object[] params) {
return new PreparedStatementCreatorImpl(sqlToUse, params != null ? Arrays.asList(params) : Collections.emptyList());
}
/**
* PreparedStatementCreator implementation returned by this class.
*/
private class PreparedStatementCreatorImpl implements PreparedStatementCreator, PreparedStatementBinder, CqlProvider {
private final String actualCql;
private final List<?> parameters;
public PreparedStatementCreatorImpl(List<?> parameters) {
this(cql, parameters);
}
/**
* @param actualCql
* @param parameters
*/
public PreparedStatementCreatorImpl(String actualCql, List<?> parameters) {
this.actualCql = actualCql;
Assert.notNull(parameters, "Parameters List must not be null");
this.parameters = parameters;
if (this.parameters.size() != declaredParameters.size()) {
Set<String> names = new HashSet<String>();
for (int i = 0; i < parameters.size(); i++) {
Object param = parameters.get(i);
if (param instanceof CqlParameterValue) {
names.add(((CqlParameterValue) param).getName());
} else {
names.add("Parameter #" + i);
}
}
if (names.size() != declaredParameters.size()) {
throw new InvalidDataAccessApiUsageException("CQL [" + cql + "]: given " + names.size()
+ " parameters but expected " + declaredParameters.size());
}
}
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.PreparedStatementCreator#createPreparedStatement(com.datastax.driver.core.Session)
*/
@Override
public PreparedStatement createPreparedStatement(Session session) throws DriverException {
return session.prepare(this.actualCql);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.PreparedStatementBinder#bindValues(com.datastax.driver.core.PreparedStatement)
*/
@Override
public BoundStatement bindValues(PreparedStatement ps) throws DriverException {
if (this.parameters == null || this.parameters.size() == 0) {
return ps.bind();
}
// Test the type of the first value
Object v = this.parameters.get(0);
Object[] values;
if (v instanceof CqlParameterValue) {
LinkedList<Object> valuesList = new LinkedList<Object>();
for (Object value : this.parameters) {
valuesList.add(((CqlParameterValue) value).getValue());
}
values = valuesList.toArray();
} else {
values = this.parameters.toArray();
}
return ps.bind(values);
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CqlProvider#getCql()
*/
@Override
public String getCql() {
return cql;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("PreparedStatementCreatorFactory.PreparedStatementCreatorImpl: cql=[");
sb.append(cql).append("]; parameters=").append(this.parameters);
return sb.toString();
}
}
}

View File

@@ -1,73 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import java.util.List;
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.DriverException;
/**
* @author David Webb
*
*/
public class PreparedStatementCreatorImpl implements PreparedStatementCreator, CqlProvider, PreparedStatementBinder {
private final String cql;
private List<Object> values;
public PreparedStatementCreatorImpl(String cql) {
this.cql = cql;
}
public PreparedStatementCreatorImpl(String cql, List<Object> values) {
this.cql = cql;
this.values = values;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.PreparedStatementSetter#setValues(com.datastax.driver.core.PreparedStatement)
*/
@Override
public BoundStatement bindValues(PreparedStatement ps) throws DriverException {
// Nothing to set if there are no values
if (values == null) {
return null;
}
return ps.bind(values.toArray());
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CqlProvider#getCql()
*/
@Override
public String getCql() {
return this.cql;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.PreparedStatementCreator#createPreparedStatement(com.datastax.driver.core.Session)
*/
@Override
public PreparedStatement createPreparedStatement(Session session) throws DriverException {
return session.prepare(this.cql);
}
}

View File

@@ -1,11 +0,0 @@
package org.springframework.cassandra.core;
import org.springframework.dao.DataAccessException;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.exceptions.DriverException;
public interface ResultSetExtractor<T> {
T extractData(ResultSet rs) throws DriverException, DataAccessException;
}

View File

@@ -1,11 +0,0 @@
package org.springframework.cassandra.core;
import org.springframework.dao.DataAccessException;
import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.exceptions.DriverException;
public interface ResultSetFutureExtractor<T> {
T extractData(ResultSetFuture rs) throws DriverException, DataAccessException;
}

View File

@@ -1,43 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import java.io.Serializable;
import com.datastax.driver.core.Host;
/**
* @author David Webb
*
*/
public final class RingMember implements Serializable {
/*
* Ring attributes
*/
public String hostName;
public String address;
public String DC;
public String rack;
public RingMember(Host h) {
this.hostName = h.getAddress().getHostName();
this.address = h.getAddress().getHostAddress();
this.DC = h.getDatacenter();
this.rack = h.getRack();
}
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.springframework.util.Assert;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.exceptions.DriverException;
/**
* @author David Webb
* @param <T>
*
*/
public class RingMemberHostMapper implements HostMapper<RingMember> {
/* (non-Javadoc)
* @see org.springframework.cassandra.core.HostMapper#mapHosts(java.util.Set)
*/
@Override
public List<RingMember> mapHosts(Set<Host> hosts) throws DriverException {
List<RingMember> members = new ArrayList<RingMember>();
Assert.notNull(hosts);
Assert.notEmpty(hosts);
RingMember r = null;
for (Host host : hosts) {
r = new RingMember(host);
members.add(r);
}
return members;
}
}

View File

@@ -1,29 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import com.datastax.driver.core.Row;
/**
* Simple internal callback to allow operations on a {@link Row}.
*
* @author Alex Shvid
*/
public interface RowCallback<T> {
T doWith(Row object);
}

View File

@@ -1,10 +0,0 @@
package org.springframework.cassandra.core;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.exceptions.DriverException;
public interface RowCallbackHandler {
void processRow(Row row) throws DriverException;
}

View File

@@ -1,10 +0,0 @@
package org.springframework.cassandra.core;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.exceptions.DriverException;
public interface RowMapper<T> {
T mapRow(Row row, int rowNum) throws DriverException;
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright 2010-2011 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import org.springframework.dao.DataAccessException;
import com.datastax.driver.core.Session;
/**
* Interface for operations on a Cassandra Session.
*
* @author David Webb
*
* @param <T>
*/
public interface SessionCallback<T> {
/**
* Perform the operation in the given Session
*
* @param s
* @return
* @throws DataAccessException
*/
T doInSession(Session s) throws DataAccessException;
}

View File

@@ -1,87 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.cassandra.core.Keyspace;
import com.datastax.driver.core.Session;
/**
* @author David Webb
*
*/
public class SessionFactoryBean implements FactoryBean<Session>, InitializingBean {
private Keyspace keyspace;
public SessionFactoryBean() {
}
public SessionFactoryBean(Keyspace keyspace) {
setKeyspace(keyspace);
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
if (keyspace == null) {
throw new IllegalStateException("Keyspace required.");
}
}
/**
* @return Returns the keyspace.
*/
public Keyspace getKeyspace() {
return keyspace;
}
/**
* @param keyspace The keyspace to set.
*/
public void setKeyspace(Keyspace keyspace) {
this.keyspace = keyspace;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
@Override
public Session getObject() {
return keyspace.getSession();
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
@Override
public Class<?> getObjectType() {
return Session.class;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
*/
@Override
public boolean isSingleton() {
return true;
}
}

View File

@@ -1,58 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.core;
import org.springframework.util.Assert;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.DriverException;
/**
* @author David Webb
*
*/
public class SimplePreparedStatementCreator implements PreparedStatementCreator, CqlProvider {
private final String cql;
/**
* Create a PreparedStatementCreator from the provided CQL.
*
* @param cql
*/
public SimplePreparedStatementCreator(String cql) {
Assert.notNull(cql, "CQL is required to create a PreparedStatement");
this.cql = cql;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.CqlProvider#getCql()
*/
@Override
public String getCql() {
return this.cql;
}
/* (non-Javadoc)
* @see org.springframework.cassandra.core.PreparedStatementCreator#createPreparedStatement(com.datastax.driver.core.Session)
*/
@Override
public PreparedStatement createPreparedStatement(Session session) throws DriverException {
return session.prepare(this.cql);
}
}

View File

@@ -1,117 +0,0 @@
package org.springframework.cassandra.core.cql;
import java.util.regex.Pattern;
public class CqlStringUtils {
protected static final String SINGLE_QUOTE = "\'";
protected static final String DOUBLE_SINGLE_QUOTE = "\'\'";
protected static final String DOUBLE_QUOTE = "\"";
protected static final String DOUBLE_DOUBLE_QUOTE = "\"\"";
public static StringBuilder noNull(StringBuilder sb) {
return sb == null ? new StringBuilder() : sb;
}
public static final String UNESCAPED_DOUBLE_QUOTE_REGEX = "TODO";
public static final Pattern UNESCAPED_DOUBLE_QUOTE_PATTERN = Pattern.compile(UNESCAPED_DOUBLE_QUOTE_REGEX);
public static final String UNQUOTED_IDENTIFIER_REGEX = "[a-zA-Z_][a-zA-Z0-9_]*";
public static final Pattern UNQUOTED_IDENTIFIER_PATTERN = Pattern.compile(UNQUOTED_IDENTIFIER_REGEX);
public static boolean isUnquotedIdentifier(CharSequence chars) {
return UNQUOTED_IDENTIFIER_PATTERN.matcher(chars).matches();
}
public static void checkUnquotedIdentifier(CharSequence chars) {
if (!CqlStringUtils.isUnquotedIdentifier(chars)) {
throw new IllegalArgumentException("[" + chars + "] is not a valid CQL identifier");
}
}
public static final String QUOTED_IDENTIFIER_REGEX = "[a-zA-Z_]([a-zA-Z0-9_]|\"{2}+)*";
public static final Pattern QUOTED_IDENTIFIER_PATTERN = Pattern.compile(QUOTED_IDENTIFIER_REGEX);
public static boolean isQuotedIdentifier(CharSequence chars) {
return QUOTED_IDENTIFIER_PATTERN.matcher(chars).matches();
}
public static void checkQuotedIdentifier(CharSequence chars) {
if (!CqlStringUtils.isQuotedIdentifier(chars)) {
throw new IllegalArgumentException("[" + chars + "] is not a valid CQL quoted identifier");
}
}
public static boolean isIdentifier(CharSequence chars) {
return isUnquotedIdentifier(chars) || isQuotedIdentifier(chars);
}
public static void checkIdentifier(CharSequence chars) {
if (!CqlStringUtils.isIdentifier(chars)) {
throw new IllegalArgumentException("[" + chars + "] is not a valid CQL quoted or unquoted identifier");
}
}
/**
* Renders the given string as a legal Cassandra identifier.
* <ul>
* <li>If the given identifier is a legal unquoted identifier, it is returned unchanged.</li>
* <li>If the given identifier is a legal quoted identifier, it is returned encased in double quotes.</li>
* <li>If the given identifier is illegal, an {@link IllegalArgumentException} is thrown.</li>
* </ul>
*/
public static String identifize(String candidate) {
checkIdentifier(candidate);
if (isUnquotedIdentifier(candidate)) {
return candidate;
}
// else it must be quoted
return doubleQuote(candidate);
}
/**
* Renders the given string as a legal Cassandra string column or table option value, by escaping single quotes and
* encasing the result in single quotes. Given <code>null</code>, returns <code>null</code>.
*/
public static String valuize(String candidate) {
if (candidate == null) {
return null;
}
return singleQuote(escapeSingle(candidate));
}
/**
* Doubles single quote characters (' -&gt; ''). Given <code>null</code>, returns <code>null</code>.
*/
public static String escapeSingle(Object things) {
return things == null ? (String) null : things.toString().replace(SINGLE_QUOTE, DOUBLE_SINGLE_QUOTE);
}
/**
* Doubles double quote characters (" -&gt; ""). Given <code>null</code>, returns <code>null</code>.
*/
public static String escapeDouble(Object things) {
return things == null ? (String) null : things.toString().replace(DOUBLE_QUOTE, DOUBLE_DOUBLE_QUOTE);
}
/**
* Surrounds given object's {@link Object#toString()} with single quotes. Given <code>null</code>, returns
* <code>null</code>.
*/
public static String singleQuote(Object thing) {
return thing == null ? (String) null : new StringBuilder().append(SINGLE_QUOTE).append(thing).append(SINGLE_QUOTE)
.toString();
}
/**
* Surrounds given object's {@link Object#toString()} with double quotes. Given <code>null</code>, returns
* <code>null</code>.
*/
public static String doubleQuote(Object thing) {
return thing == null ? (String) null : new StringBuilder().append(DOUBLE_QUOTE).append(thing).append(DOUBLE_QUOTE)
.toString();
}
}

View File

@@ -1,22 +0,0 @@
package org.springframework.cassandra.core.cql.generator;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import org.springframework.cassandra.core.keyspace.AddColumnSpecification;
/**
* CQL generator for generating an <code>ADD</code> clause of an <code>ALTER TABLE</code> statement.
*
* @author Matthew T. Adams
*/
public class AddColumnCqlGenerator extends ColumnChangeCqlGenerator<AddColumnSpecification> {
public AddColumnCqlGenerator(AddColumnSpecification specification) {
super(specification);
}
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("ADD ").append(spec().getNameAsIdentifier()).append(" TYPE ")
.append(spec().getType().getName());
}
}

View File

@@ -1,22 +0,0 @@
package org.springframework.cassandra.core.cql.generator;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import org.springframework.cassandra.core.keyspace.AlterColumnSpecification;
/**
* CQL generator for generating an <code>ALTER</code> column clause of an <code>ALTER TABLE</code> statement.
*
* @author Matthew T. Adams
*/
public class AlterColumnCqlGenerator extends ColumnChangeCqlGenerator<AlterColumnSpecification> {
public AlterColumnCqlGenerator(AlterColumnSpecification specification) {
super(specification);
}
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("ALTER ").append(spec().getNameAsIdentifier()).append(" TYPE ")
.append(spec().getType().getName());
}
}

View File

@@ -1,106 +0,0 @@
package org.springframework.cassandra.core.cql.generator;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import java.util.Map;
import org.springframework.cassandra.core.keyspace.AddColumnSpecification;
import org.springframework.cassandra.core.keyspace.AlterColumnSpecification;
import org.springframework.cassandra.core.keyspace.AlterTableSpecification;
import org.springframework.cassandra.core.keyspace.ColumnChangeSpecification;
import org.springframework.cassandra.core.keyspace.DropColumnSpecification;
import org.springframework.cassandra.core.keyspace.Option;
/**
* CQL generator for generating <code>ALTER TABLE</code> statements.
*
* @author Matthew T. Adams
*/
public class AlterTableCqlGenerator extends TableOptionsCqlGenerator<AlterTableSpecification> {
public AlterTableCqlGenerator(AlterTableSpecification specification) {
super(specification);
}
public StringBuilder toCql(StringBuilder cql) {
cql = noNull(cql);
preambleCql(cql);
changesCql(cql);
optionsCql(cql);
cql.append(";");
return cql;
}
protected StringBuilder preambleCql(StringBuilder cql) {
return noNull(cql).append("ALTER TABLE ").append(spec().getNameAsIdentifier()).append(" ");
}
protected StringBuilder changesCql(StringBuilder cql) {
cql = noNull(cql);
boolean first = true;
for (ColumnChangeSpecification change : spec().getChanges()) {
if (first) {
first = false;
} else {
cql.append(" ");
}
getCqlGeneratorFor(change).toCql(cql);
}
return cql;
}
protected ColumnChangeCqlGenerator<?> getCqlGeneratorFor(ColumnChangeSpecification change) {
if (change instanceof AddColumnSpecification) {
return new AddColumnCqlGenerator((AddColumnSpecification) change);
}
if (change instanceof DropColumnSpecification) {
return new DropColumnCqlGenerator((DropColumnSpecification) change);
}
if (change instanceof AlterColumnSpecification) {
return new AlterColumnCqlGenerator((AlterColumnSpecification) change);
}
throw new Error("unknown ColumnChangeSpecification type: " + change.getClass().getName());
}
@SuppressWarnings("unchecked")
protected StringBuilder optionsCql(StringBuilder cql) {
cql = noNull(cql);
Map<String, Object> options = spec().getOptions();
if (options == null || options.isEmpty()) {
return cql;
}
cql.append(" WITH ");
boolean first = true;
for (String key : options.keySet()) {
if (first) {
first = false;
} else {
cql.append(" AND ");
}
cql.append(key);
Object value = options.get(key);
if (value == null) {
continue;
}
cql.append(" = ");
if (value instanceof Map) {
optionValueMap((Map<Option, Object>) value, cql);
continue;
}
// else just use value as string
cql.append(value.toString());
}
return cql;
}
}

View File

@@ -1,35 +0,0 @@
package org.springframework.cassandra.core.cql.generator;
import org.springframework.cassandra.core.keyspace.ColumnChangeSpecification;
import org.springframework.util.Assert;
/**
* Base class for column change CQL generators.
*
* @author Matthew T. Adams
* @param <T> The corresponding {@link ColumnChangeSpecification} type for this CQL generator.
*/
public abstract class ColumnChangeCqlGenerator<T extends ColumnChangeSpecification> {
public abstract StringBuilder toCql(StringBuilder cql);
private ColumnChangeSpecification specification;
public ColumnChangeCqlGenerator(ColumnChangeSpecification specification) {
setSpecification(specification);
}
protected void setSpecification(ColumnChangeSpecification specification) {
Assert.notNull(specification);
this.specification = specification;
}
@SuppressWarnings("unchecked")
public T getSpecification() {
return (T) specification;
}
protected T spec() {
return getSpecification();
}
}

View File

@@ -1,173 +0,0 @@
package org.springframework.cassandra.core.cql.generator;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import static org.springframework.data.cassandra.mapping.KeyType.PARTITION;
import static org.springframework.data.cassandra.mapping.KeyType.PRIMARY;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.cassandra.core.keyspace.ColumnSpecification;
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
import org.springframework.cassandra.core.keyspace.Option;
/**
* CQL generator for generating a <code>CREATE TABLE</code> statement.
*
* @author Matthew T. Adams
*/
public class CreateTableCqlGenerator extends TableCqlGenerator<CreateTableSpecification> {
public CreateTableCqlGenerator(CreateTableSpecification specification) {
super(specification);
}
public StringBuilder toCql(StringBuilder cql) {
cql = noNull(cql);
preambleCql(cql);
columnsAndOptionsCql(cql);
cql.append(";");
return cql;
}
protected StringBuilder preambleCql(StringBuilder cql) {
return noNull(cql).append("CREATE TABLE ").append(spec().getIfNotExists() ? "IF NOT EXISTS " : "")
.append(spec().getNameAsIdentifier());
}
@SuppressWarnings("unchecked")
protected StringBuilder columnsAndOptionsCql(StringBuilder cql) {
cql = noNull(cql);
// begin columns
cql.append(" (");
List<ColumnSpecification> partitionKeys = new ArrayList<ColumnSpecification>();
List<ColumnSpecification> primaryKeys = new ArrayList<ColumnSpecification>();
for (ColumnSpecification col : spec().getColumns()) {
col.toCql(cql).append(", ");
if (col.getKeyType() == PARTITION) {
partitionKeys.add(col);
} else if (col.getKeyType() == PRIMARY) {
primaryKeys.add(col);
}
}
// begin primary key clause
cql.append("PRIMARY KEY ");
StringBuilder partitions = new StringBuilder();
StringBuilder primaries = new StringBuilder();
if (partitionKeys.size() > 1) {
partitions.append("(");
}
boolean first = true;
for (ColumnSpecification col : partitionKeys) {
if (first) {
first = false;
} else {
partitions.append(", ");
}
partitions.append(col.getName());
}
if (partitionKeys.size() > 1) {
partitions.append(")");
}
StringBuilder clustering = null;
boolean clusteringFirst = true;
first = true;
for (ColumnSpecification col : primaryKeys) {
if (first) {
first = false;
} else {
primaries.append(", ");
}
primaries.append(col.getName());
if (col.getOrdering() != null) { // then ordering specified
if (clustering == null) { // then initialize clustering clause
clustering = new StringBuilder().append("CLUSTERING ORDER BY (");
}
if (clusteringFirst) {
clusteringFirst = false;
} else {
clustering.append(", ");
}
clustering.append(col.getName()).append(" ").append(col.getOrdering().cql());
}
}
if (clustering != null) { // then end clustering option
clustering.append(")");
}
boolean parenthesize = true;// partitionKeys.size() + primaryKeys.size() > 1;
cql.append(parenthesize ? "(" : "");
cql.append(partitions);
cql.append(primaryKeys.size() > 0 ? ", " : "");
cql.append(primaries);
cql.append(parenthesize ? ")" : "");
// end primary key clause
cql.append(")");
// end columns
// begin options
// begin option clause
Map<String, Object> options = spec().getOptions();
if (clustering != null || !options.isEmpty()) {
// option preamble
first = true;
cql.append(" WITH ");
// end option preamble
if (clustering != null) {
cql.append(clustering);
first = false;
}
if (!options.isEmpty()) {
for (String name : options.keySet()) {
// append AND if we're not on first option
if (first) {
first = false;
} else {
cql.append(" AND ");
}
// append <name> = <value>
cql.append(name);
Object value = options.get(name);
if (value == null) { // then assume string-only, valueless option like "COMPACT STORAGE"
continue;
}
cql.append(" = ");
if (value instanceof Map) {
optionValueMap((Map<Option, Object>) value, cql);
continue; // end non-empty value map
}
// else just use value as string
cql.append(value.toString());
}
}
}
// end options
return cql;
}
}

View File

@@ -1,21 +0,0 @@
package org.springframework.cassandra.core.cql.generator;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import org.springframework.cassandra.core.keyspace.DropColumnSpecification;
/**
* CQL generator for generating a <code>DROP</code> column clause of an <code>ALTER TABLE</code> statement.
*
* @author Matthew T. Adams
*/
public class DropColumnCqlGenerator extends ColumnChangeCqlGenerator<DropColumnSpecification> {
public DropColumnCqlGenerator(DropColumnSpecification specification) {
super(specification);
}
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("DROP ").append(spec().getNameAsIdentifier());
}
}

View File

@@ -1,22 +0,0 @@
package org.springframework.cassandra.core.cql.generator;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import org.springframework.cassandra.core.keyspace.DropTableSpecification;
/**
* CQL generator for generating a <code>DROP TABLE</code> statement.
*
* @author Matthew T. Adams
*/
public class DropTableCqlGenerator extends TableNameCqlGenerator<DropTableSpecification> {
public DropTableCqlGenerator(DropTableSpecification specification) {
super(specification);
}
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("DROP TABLE ").append(spec().getIfExists() ? "IF EXISTS " : "")
.append(spec().getNameAsIdentifier()).append(";");
}
}

View File

@@ -1,65 +0,0 @@
package org.springframework.cassandra.core.cql.generator;
import static org.springframework.cassandra.core.cql.CqlStringUtils.escapeSingle;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import static org.springframework.cassandra.core.cql.CqlStringUtils.singleQuote;
import java.util.Map;
import org.springframework.cassandra.core.keyspace.Option;
import org.springframework.cassandra.core.keyspace.TableSpecification;
/**
* Base class that contains behavior common to CQL generation for table operations.
*
* @author Matthew T. Adams
* @param T The subtype of this class for which this is a CQL generator.
*/
public abstract class TableCqlGenerator<T extends TableSpecification<T>> extends
TableOptionsCqlGenerator<TableSpecification<T>> {
public TableCqlGenerator(TableSpecification<T> specification) {
super(specification);
}
@SuppressWarnings("unchecked")
protected T spec() {
return (T) getSpecification();
}
protected StringBuilder optionValueMap(Map<Option, Object> valueMap, StringBuilder cql) {
cql = noNull(cql);
if (valueMap == null || valueMap.isEmpty()) {
return cql;
}
// else option value is a non-empty map
// append { 'name' : 'value', ... }
cql.append("{ ");
boolean mapFirst = true;
for (Map.Entry<Option, Object> entry : valueMap.entrySet()) {
if (mapFirst) {
mapFirst = false;
} else {
cql.append(", ");
}
Option option = entry.getKey();
cql.append(singleQuote(option.getName())); // entries in map keys are always quoted
cql.append(" : ");
Object entryValue = entry.getValue();
entryValue = entryValue == null ? "" : entryValue.toString();
if (option.escapesValue()) {
entryValue = escapeSingle(entryValue);
}
if (option.quotesValue()) {
entryValue = singleQuote(entryValue);
}
cql.append(entryValue);
}
cql.append(" }");
return cql;
}
}

View File

@@ -1,36 +0,0 @@
package org.springframework.cassandra.core.cql.generator;
import org.springframework.cassandra.core.keyspace.TableNameSpecification;
import org.springframework.util.Assert;
public abstract class TableNameCqlGenerator<T extends TableNameSpecification<T>> {
public abstract StringBuilder toCql(StringBuilder cql);
private TableNameSpecification<T> specification;
public TableNameCqlGenerator(TableNameSpecification<T> specification) {
setSpecification(specification);
}
protected void setSpecification(TableNameSpecification<T> specification) {
Assert.notNull(specification);
this.specification = specification;
}
@SuppressWarnings("unchecked")
public T getSpecification() {
return (T) specification;
}
/**
* Convenient synonymous method of {@link #getSpecification()}.
*/
protected T spec() {
return getSpecification();
}
public String toCql() {
return toCql(null).toString();
}
}

View File

@@ -1,65 +0,0 @@
package org.springframework.cassandra.core.cql.generator;
import static org.springframework.cassandra.core.cql.CqlStringUtils.escapeSingle;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import static org.springframework.cassandra.core.cql.CqlStringUtils.singleQuote;
import java.util.Map;
import org.springframework.cassandra.core.keyspace.Option;
import org.springframework.cassandra.core.keyspace.TableOptionsSpecification;
/**
* Base class that contains behavior common to CQL generation for table operations.
*
* @author Matthew T. Adams
* @param T The subtype of this class for which this is a CQL generator.
*/
public abstract class TableOptionsCqlGenerator<T extends TableOptionsSpecification<T>> extends
TableNameCqlGenerator<TableOptionsSpecification<T>> {
public TableOptionsCqlGenerator(TableOptionsSpecification<T> specification) {
super(specification);
}
@SuppressWarnings("unchecked")
protected T spec() {
return (T) getSpecification();
}
protected StringBuilder optionValueMap(Map<Option, Object> valueMap, StringBuilder cql) {
cql = noNull(cql);
if (valueMap == null || valueMap.isEmpty()) {
return cql;
}
// else option value is a non-empty map
// append { 'name' : 'value', ... }
cql.append("{ ");
boolean mapFirst = true;
for (Map.Entry<Option, Object> entry : valueMap.entrySet()) {
if (mapFirst) {
mapFirst = false;
} else {
cql.append(", ");
}
Option option = entry.getKey();
cql.append(singleQuote(option.getName())); // entries in map keys are always quoted
cql.append(" : ");
Object entryValue = entry.getValue();
entryValue = entryValue == null ? "" : entryValue.toString();
if (option.escapesValue()) {
entryValue = escapeSingle(entryValue);
}
if (option.quotesValue()) {
entryValue = singleQuote(entryValue);
}
cql.append(entryValue);
}
cql.append(" }");
return cql;
}
}

View File

@@ -1,10 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import com.datastax.driver.core.DataType;
public class AddColumnSpecification extends ColumnTypeChangeSpecification {
public AddColumnSpecification(String name, DataType type) {
super(name, type);
}
}

View File

@@ -1,10 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import com.datastax.driver.core.DataType;
public class AlterColumnSpecification extends ColumnTypeChangeSpecification {
public AlterColumnSpecification(String name, DataType type) {
super(name, type);
}
}

View File

@@ -1,51 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.datastax.driver.core.DataType;
/**
* Builder class to construct an <code>ALTER TABLE</code> specification.
*
* @author Matthew T. Adams
*/
public class AlterTableSpecification extends TableOptionsSpecification<AlterTableSpecification> {
/**
* The list of column changes.
*/
private List<ColumnChangeSpecification> changes = new ArrayList<ColumnChangeSpecification>();
/**
* Adds a <code>DROP</code> to the list of column changes.
*/
public AlterTableSpecification drop(String column) {
changes.add(new DropColumnSpecification(column));
return this;
}
/**
* Adds an <code>ADD</code> to the list of column changes.
*/
public AlterTableSpecification add(String column, DataType type) {
changes.add(new AddColumnSpecification(column, type));
return this;
}
/**
* Adds an <code>ALTER</code> to the list of column changes.
*/
public AlterTableSpecification alter(String column, DataType type) {
changes.add(new AlterColumnSpecification(column, type));
return this;
}
/**
* Returns an unmodifiable list of column changes.
*/
public List<ColumnChangeSpecification> getChanges() {
return Collections.unmodifiableList(changes);
}
}

View File

@@ -1,26 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize;
public abstract class ColumnChangeSpecification {
private String name;
public ColumnChangeSpecification(String name) {
setName(name);
}
private void setName(String name) {
checkIdentifier(name);
this.name = name;
}
public String getName() {
return name;
}
public String getNameAsIdentifier() {
return identifize(name);
}
}

View File

@@ -1,167 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize;
import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
import static org.springframework.data.cassandra.mapping.KeyType.PARTITION;
import static org.springframework.data.cassandra.mapping.KeyType.PRIMARY;
import static org.springframework.data.cassandra.mapping.Ordering.ASCENDING;
import org.springframework.data.cassandra.mapping.KeyType;
import org.springframework.data.cassandra.mapping.Ordering;
import com.datastax.driver.core.DataType;
/**
* Builder class to help construct CQL statements that involve column manipulation. Not threadsafe.
* <p/>
* Use {@link #name(String)} and {@link #type(String)} to set the name and type of the column, respectively. To specify
* a <code>PRIMARY KEY</code> column, use {@link #primary()} or {@link #primary(Ordering)}. To specify that the
* <code>PRIMARY KEY</code> column is or is part of the partition key, use {@link #partition()} instead of
* {@link #primary()} or {@link #primary(Ordering)}.
*
* @author Matthew T. Adams
*/
public class ColumnSpecification {
/**
* Default ordering of primary key fields; value is {@link Ordering#ASCENDING}.
*/
public static final Ordering DFAULT_ORDERING = ASCENDING;
private String name;
private DataType type; // TODO: determining if we should be coupling this to Datastax Java Driver type?
private KeyType keyType;
private Ordering ordering;
/**
* Sets the column's name.
*
* @return this
*/
public ColumnSpecification name(String name) {
checkIdentifier(name);
this.name = name;
return this;
}
/**
* Sets the column's type.
*
* @return this
*/
public ColumnSpecification type(DataType type) {
this.type = type;
return this;
}
/**
* Identifies this column as a primary key column that is also part of a partition key. Sets the column's
* {@link #keyType} to {@link KeyType#PARTITION} and its {@link #ordering} to <code>null</code>.
*
* @return this
*/
public ColumnSpecification partition() {
return partition(true);
}
/**
* Toggles the identification of this column as a primary key column that also is or is part of a partition key. Sets
* {@link #ordering} to <code>null</code> and, if the given boolean is <code>true</code>, then sets the column's
* {@link #keyType} to {@link KeyType#PARTITION}, else sets it to <code>null</code>.
*
* @return this
*/
public ColumnSpecification partition(boolean partition) {
this.keyType = partition ? PARTITION : null;
this.ordering = null;
return this;
}
/**
* Identifies this column as a primary key column with default ordering. Sets the column's {@link #keyType} to
* {@link KeyType#PRIMARY} and its {@link #ordering} to {@link #DFAULT_ORDERING}.
*
* @return this
*/
public ColumnSpecification primary() {
return primary(DFAULT_ORDERING);
}
/**
* Identifies this column as a primary key column with the given ordering. Sets the column's {@link #keyType} to
* {@link KeyType#PRIMARY} and its {@link #ordering} to the given {@link Ordering}.
*
* @return this
*/
public ColumnSpecification primary(Ordering order) {
return primary(order, true);
}
/**
* Toggles the identification of this column as a primary key column. If the given boolean is <code>true</code>, then
* sets the column's {@link #keyType} to {@link KeyType#PARTITION} and {@link #ordering} to the given {@link Ordering}
* , else sets both {@link #keyType} and {@link #ordering} to <code>null</code>.
*
* @return this
*/
public ColumnSpecification primary(Ordering order, boolean primary) {
this.keyType = primary ? PRIMARY : null;
this.ordering = primary ? order : null;
return this;
}
/**
* Sets the column's {@link #keyType}.
*
* @return this
*/
/* package */ColumnSpecification keyType(KeyType keyType) {
this.keyType = keyType;
return this;
}
/**
* Sets the column's {@link #ordering}.
*
* @return this
*/
/* package */ColumnSpecification ordering(Ordering ordering) {
this.ordering = ordering;
return this;
}
public String getName() {
return name;
}
public String getNameAsIdentifier() {
return identifize(name);
}
public DataType getType() {
return type;
}
public KeyType getKeyType() {
return keyType;
}
public Ordering getOrdering() {
return ordering;
}
public String toCql() {
return toCql(null).toString();
}
public StringBuilder toCql(StringBuilder cql) {
return (cql = noNull(cql)).append(name).append(" ").append(type);
}
@Override
public String toString() {
return toCql(null).append(" /* keyType=").append(keyType).append(", ordering=").append(ordering).append(" */ ")
.toString();
}
}

View File

@@ -1,24 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import org.springframework.util.Assert;
import com.datastax.driver.core.DataType;
public abstract class ColumnTypeChangeSpecification extends ColumnChangeSpecification {
private DataType type;
public ColumnTypeChangeSpecification(String name, DataType type) {
super(name);
setType(type);
}
private void setType(DataType type) {
Assert.notNull(type);
this.type = type;
}
public DataType getType() {
return type;
}
}

View File

@@ -1,34 +0,0 @@
package org.springframework.cassandra.core.keyspace;
/**
* Builder class to construct a <code>CREATE TABLE</code> specification.
*
* @author Matthew T. Adams
*/
public class CreateTableSpecification extends TableSpecification<CreateTableSpecification> {
private boolean ifNotExists = false;
/**
* Causes the inclusion of an <code>IF NOT EXISTS</code> clause.
*
* @return this
*/
public CreateTableSpecification ifNotExists() {
return ifNotExists(true);
}
/**
* Toggles the inclusion of an <code>IF NOT EXISTS</code> clause.
*
* @return this
*/
public CreateTableSpecification ifNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists;
return this;
}
public boolean getIfNotExists() {
return ifNotExists;
}
}

View File

@@ -1,157 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.escapeSingle;
import static org.springframework.cassandra.core.cql.CqlStringUtils.singleQuote;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Map;
import org.springframework.util.Assert;
/**
* A default implementation of {@link Option}.
*
* @author Matthew T. Adams
*/
public class DefaultOption implements Option {
private String name;
private Class<?> type;
private boolean requiresValue;
private boolean escapesValue;
private boolean quotesValue;
public DefaultOption(String name, Class<?> type, boolean requiresValue, boolean escapesValue, boolean quotesValue) {
setName(name);
setType(type);
this.requiresValue = requiresValue;
this.escapesValue = escapesValue;
this.quotesValue = quotesValue;
}
protected void setName(String name) {
Assert.hasLength(name);
this.name = name;
}
protected void setType(Class<?> type) {
if (type != null) {
if (type.isInterface() && !(Map.class.isAssignableFrom(type) || Collection.class.isAssignableFrom(type))) {
throw new IllegalArgumentException("given type [" + type.getName() + "] must be a class, Map or Collection");
}
}
this.type = type;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public boolean isCoerceable(Object value) {
if (value == null || type == null) {
return true;
}
// check map
if (Map.class.isAssignableFrom(type)) {
return Map.class.isAssignableFrom(value.getClass());
}
// check collection
if (Collection.class.isAssignableFrom(type)) {
return Collection.class.isAssignableFrom(value.getClass());
}
// check enum
if (type.isEnum()) {
try {
String name = value instanceof Enum ? name = ((Enum) value).name() : value.toString();
Enum.valueOf((Class<? extends Enum>) type, name);
return true;
} catch (NullPointerException x) {
return false;
} catch (IllegalArgumentException x) {
return false;
}
}
// check class via String constructor
try {
Constructor<?> ctor = type.getConstructor(String.class);
if (!ctor.isAccessible()) {
ctor.setAccessible(true);
}
ctor.newInstance(value.toString());
return true;
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (IllegalArgumentException e) {
} catch (InvocationTargetException e) {
} catch (NoSuchMethodException e) {
} catch (SecurityException e) {
}
return false;
}
public Class<?> getType() {
return type;
}
public String getName() {
return name;
}
public boolean takesValue() {
return type != null;
}
public boolean requiresValue() {
return this.requiresValue;
}
public boolean escapesValue() {
return this.escapesValue;
}
public boolean quotesValue() {
return this.quotesValue;
}
public void checkValue(Object value) {
if (takesValue()) {
if (value == null) {
if (requiresValue) {
throw new IllegalArgumentException("Option [" + getName() + "] requires a value");
}
return; // doesn't require a value, so null is ok
}
// else value is not null
if (isCoerceable(value)) {
return;
}
// else value is not coerceable into the expected type
throw new IllegalArgumentException("Option [" + getName() + "] takes value coerceable to type ["
+ getType().getName() + "]");
}
// else this option doesn't take a value
if (value != null) {
throw new IllegalArgumentException("Option [" + getName() + "] takes no value");
}
}
public String toString(Object value) {
if (value == null) {
return null;
}
checkValue(value);
String string = value.toString();
string = escapesValue ? escapeSingle(string) : string;
string = quotesValue ? singleQuote(string) : string;
return string;
}
@Override
public String toString() {
return "[name=" + name + ", type=" + type.getName() + ", requiresValue=" + requiresValue + ", escapesValue="
+ escapesValue + ", quotesValue=" + quotesValue + "]";
}
}

View File

@@ -1,17 +0,0 @@
package org.springframework.cassandra.core.keyspace;
/**
* Convenient default implementation of {@link TableDescriptor} as an extension of {@link TableSpecification} that
* doesn't require the use of generics.
*
* @author Matthew T. Adams
*/
public class DefaultTableDescriptor extends TableSpecification<DefaultTableDescriptor> {
/**
* Factory method to produce a new {@link DefaultTableDescriptor}. Convenient if imported statically.
*/
public static DefaultTableDescriptor table() {
return new DefaultTableDescriptor();
}
}

View File

@@ -1,8 +0,0 @@
package org.springframework.cassandra.core.keyspace;
public class DropColumnSpecification extends ColumnChangeSpecification {
public DropColumnSpecification(String name) {
super(name);
}
}

View File

@@ -1,24 +0,0 @@
package org.springframework.cassandra.core.keyspace;
/**
* Builder class that supports the construction of <code>DROP TABLE</code> specifications.
*
* @author Matthew T. Adams
*/
public class DropTableSpecification extends TableNameSpecification<DropTableSpecification> {
private boolean ifExists;
public DropTableSpecification ifExists() {
return ifExists(true);
}
public DropTableSpecification ifExists(boolean ifExists) {
this.ifExists = ifExists;
return this;
}
public boolean getIfExists() {
return ifExists;
}
}

View File

@@ -1,61 +0,0 @@
package org.springframework.cassandra.core.keyspace;
/**
* Interface to represent option types.
*
* @author Matthew T. Adams
*/
public interface Option {
/**
* The type that values must be able to be coerced into for this option.
*/
Class<?> getType();
/**
* The (usually lower-cased, underscore-separated) name of this table option.
*/
String getName();
/**
* Whether this option takes a value.
*/
boolean takesValue();
/**
* Whether this option should escape single quotes in its value.
*/
boolean escapesValue();
/**
* Whether this option's value should be single-quoted.
*/
boolean quotesValue();
/**
* Whether this option requires a value.
*/
boolean requiresValue();
/**
* Checks that the given value can be coerced into the type given by {@link #getType()}.
*/
void checkValue(Object value);
/**
* Tests whether the given value can be coerced into the type given by {@link #getType()}.
*/
boolean isCoerceable(Object value);
/**
* First ensures that the given value is coerceable into the type expected by this option, then returns the result of
* {@link Object#toString()} called on the given value. If this option is escaping quotes ({@link #escapesValue()} is
* <code>true</code>), then single quotes will be escaped, and if this option is quoting values (
* {@link #quotesValue()} is <code>true</code>), then the value will be surrounded by single quotes. Given
* <code>null</code>, returns <code>null</code>.
*
* @see #escapesValue()
* @see #quotesValue()
*/
String toString(Object value);
}

View File

@@ -1,52 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import java.util.List;
import java.util.Map;
/**
* Describes a table.
*
* @author Matthew T. Adams
*/
public interface TableDescriptor {
/**
* Returns the name of the table.
*/
String getName();
/**
* Returns the name of the table as an identifer or quoted identifier as appropriate.
*/
String getNameAsIdentifier();
/**
* Returns an unmodifiable {@link List} of {@link ColumnSpecification}s.
*/
List<ColumnSpecification> getColumns();
/**
* Returns an unmodifiable list of all partition key columns.
*/
public List<ColumnSpecification> getPartitionKeyColumns();
/**
* Returns an unmodifiable list of all primary key columns that are not also partition key columns.
*/
public List<ColumnSpecification> getPrimaryKeyColumns();
/**
* Returns an unmodifiable list of all partition and primary key columns.
*/
public List<ColumnSpecification> getKeyColumns();
/**
* Returns an unmodifiable list of all non-key columns.
*/
public List<ColumnSpecification> getNonKeyColumns();
/**
* Returns an unmodifiable {@link Map} of table options.
*/
Map<String, Object> getOptions();
}

View File

@@ -1,38 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.checkIdentifier;
import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize;
/**
* Abstract builder class to support the construction of table specifications.
*
* @author Matthew T. Adams
* @param <T> The subtype of the {@link TableNameSpecification}
*/
public abstract class TableNameSpecification<T extends TableNameSpecification<T>> {
/**
* The name of the table.
*/
private String name;
/**
* Sets the table name.
*
* @return this
*/
@SuppressWarnings("unchecked")
public T name(String name) {
checkIdentifier(name);
this.name = name;
return (T) this;
}
public String getName() {
return name;
}
public String getNameAsIdentifier() {
return identifize(name);
}
}

View File

@@ -1,34 +0,0 @@
package org.springframework.cassandra.core.keyspace;
/**
* Class that offers static methods as entry points into the fluent API for building create, drop and alter table
* specifications. These methods are most convenient when imported statically.
*
* @author Matthew T. Adams
*/
public class TableOperations {
/**
* Entry point into the {@link CreateTableSpecification}'s fluent API to create a table. Convenient if imported
* statically.
*/
public static CreateTableSpecification createTable() {
return new CreateTableSpecification();
}
/**
* Entry point into the {@link DropTableSpecification}'s fluent API to drop a table. Convenient if imported
* statically.
*/
public static DropTableSpecification dropTable() {
return new DropTableSpecification();
}
/**
* Entry point into the {@link AlterTableSpecification}'s fluent API to alter a table. Convenient if imported
* statically.
*/
public static AlterTableSpecification alterTable() {
return new AlterTableSpecification();
}
}

View File

@@ -1,287 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import java.util.Map;
/**
* Enumeration that represents all known table options. If a table option is not listed here, but is supported by
* Cassandra, use the method {@link CreateTableSpecification#with(String, Object, boolean, boolean)} to write the raw
* value.
*
* Implements {@link Option} via delegation, since {@link Enum}s can't extend anything.
*
* @author Matthew T. Adams
* @see CompactionOption
* @see CompressionOption
* @see CachingOption
*/
public enum TableOption implements Option {
/**
* <code>comment</code>
*/
COMMENT("comment", String.class, true, true, true),
/**
* <code>COMPACT STORAGE</code>
*/
COMPACT_STORAGE("COMPACT STORAGE", null, false, false, false),
/**
* <code>compaction</code>. Value is a <code>Map&lt;CompactionOption,Object&gt;</code>.
*
* @see CompactionOption
*/
COMPACTION("compaction", Map.class, true, false, false),
/**
* <code>compression</code>. Value is a <code>Map&lt;CompressionOption,Object&gt;</code>.
*
* @see {@link CompressionOption}
*/
COMPRESSION("compression", Map.class, true, false, false),
/**
* <code>replicate_on_write</code>
*/
REPLICATE_ON_WRITE("replicate_on_write", Boolean.class, true, false, false),
/**
* <code>caching</code>
*
* @see CachingOption
*/
CACHING("caching", CachingOption.class, true, false, false),
/**
* <code>bloom_filter_fp_chance</code>
*/
BLOOM_FILTER_FP_CHANCE("bloom_filter_fp_chance", Double.class, true, false, false),
/**
* <code>read_repair_chance</code>
*/
READ_REPAIR_CHANCE("read_repair_chance", Double.class, true, false, false),
/**
* <code>dclocal_read_repair_chance</code>
*/
DCLOCAL_READ_REPAIR_CHANCE("dclocal_read_repair_chance", Double.class, true, false, false),
/**
* <code>gc_grace_seconds</code>
*/
GC_GRACE_SECONDS("gc_grace_seconds", Long.class, true, false, false);
private Option delegate;
private TableOption(String name, Class<?> type, boolean requiresValue, boolean escapesValue, boolean quotesValue) {
this.delegate = new DefaultOption(name, type, requiresValue, escapesValue, quotesValue);
}
public Class<?> getType() {
return delegate.getType();
}
public boolean takesValue() {
return delegate.takesValue();
}
public String getName() {
return delegate.getName();
}
public boolean escapesValue() {
return delegate.escapesValue();
}
public boolean quotesValue() {
return delegate.quotesValue();
}
public boolean requiresValue() {
return delegate.requiresValue();
}
public void checkValue(Object value) {
delegate.checkValue(value);
}
public boolean isCoerceable(Object value) {
return delegate.isCoerceable(value);
}
public String toString() {
return delegate.toString();
}
public String toString(Object value) {
return delegate.toString(value);
}
/**
* Known caching options.
*
* @author Matthew T. Adams
*/
public enum CachingOption {
ALL("all"), KEYS_ONLY("keys_only"), ROWS_ONLY("rows_only"), NONE("none");
private String value;
private CachingOption(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public String toString() {
return getValue();
}
}
/**
* Known compaction options.
*
* @author Matthew T. Adams
*/
public enum CompactionOption implements Option {
/**
* <code>tombstone_threshold</code>
*/
TOMBSTONE_THRESHOLD("tombstone_threshold", Double.class, true, false, false),
/**
* <code>tombstone_compaction_interval</code>
*/
TOMBSTONE_COMPACTION_INTERVAL("tombstone_compaction_interval", Double.class, true, false, false),
/**
* <code>min_sstable_size</code>
*/
MIN_SSTABLE_SIZE("min_sstable_size", Long.class, true, false, false),
/**
* <code>min_threshold</code>
*/
MIN_THRESHOLD("min_threshold", Long.class, true, false, false),
/**
* <code>max_threshold</code>
*/
MAX_THRESHOLD("max_threshold", Long.class, true, false, false),
/**
* <code>bucket_low</code>
*/
BUCKET_LOW("bucket_low", Double.class, true, false, false),
/**
* <code>bucket_high</code>
*/
BUCKET_HIGH("bucket_high", Double.class, true, false, false),
/**
* <code>sstable_size_in_mb</code>
*/
SSTABLE_SIZE_IN_MB("sstable_size_in_mb", Long.class, true, false, false);
private Option delegate;
private CompactionOption(String name, Class<?> type, boolean requiresValue, boolean escapesValue,
boolean quotesValue) {
this.delegate = new DefaultOption(name, type, requiresValue, escapesValue, quotesValue);
}
public Class<?> getType() {
return delegate.getType();
}
public boolean takesValue() {
return delegate.takesValue();
}
public String getName() {
return delegate.getName();
}
public boolean escapesValue() {
return delegate.escapesValue();
}
public boolean quotesValue() {
return delegate.quotesValue();
}
public boolean requiresValue() {
return delegate.requiresValue();
}
public void checkValue(Object value) {
delegate.checkValue(value);
}
public boolean isCoerceable(Object value) {
return delegate.isCoerceable(value);
}
public String toString() {
return delegate.toString();
}
public String toString(Object value) {
return delegate.toString(value);
}
}
/**
* Known compression options.
*
* @author Matthew T. Adams
*/
public enum CompressionOption implements Option {
/**
* <code>sstable_compression</code>
*/
STABLE_COMPRESSION("sstable_compression", String.class, true, false, false),
/**
* <code>chunk_length_kb</code>
*/
CHUNK_LENGTH_KB("chunk_length_kb", Long.class, true, false, false),
/**
* <code>crc_check_chance</code>
*/
CRC_CHECK_CHANCE("crc_check_chance", Double.class, true, false, false);
private Option delegate;
private CompressionOption(String name, Class<?> type, boolean requiresValue, boolean escapesValue,
boolean quotesValue) {
this.delegate = new DefaultOption(name, type, requiresValue, escapesValue, quotesValue);
}
public Class<?> getType() {
return delegate.getType();
}
public boolean takesValue() {
return delegate.takesValue();
}
public String getName() {
return delegate.getName();
}
public boolean escapesValue() {
return delegate.escapesValue();
}
public boolean quotesValue() {
return delegate.quotesValue();
}
public boolean requiresValue() {
return delegate.requiresValue();
}
public void checkValue(Object value) {
delegate.checkValue(value);
}
public boolean isCoerceable(Object value) {
return delegate.isCoerceable(value);
}
public String toString() {
return delegate.toString();
}
public String toString(Object value) {
return delegate.toString(value);
}
}
}

View File

@@ -1,93 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import static org.springframework.cassandra.core.cql.CqlStringUtils.escapeSingle;
import static org.springframework.cassandra.core.cql.CqlStringUtils.singleQuote;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.cassandra.core.cql.CqlStringUtils;
/**
* Abstract builder class to support the construction of table specifications that have table options, that is, those
* options normally specified by <code>WITH ... AND ...</code>.
* <p/>
* It is important to note that although this class depends on {@link TableOption} for convenient and typesafe use, it
* ultimately stores its options in a <code>Map<String,Object></code> for flexibility. This means that
* {@link #with(TableOption)} and {@link #with(TableOption, Object)} delegate to
* {@link #with(String, Object, boolean, boolean)}. This design allows the API to support new Cassandra options as they
* are introduced without having to update the code immediately.
*
* @author Matthew T. Adams
* @param <T> The subtype of the {@link TableOptionsSpecification}.
*/
public abstract class TableOptionsSpecification<T extends TableOptionsSpecification<T>> extends
TableNameSpecification<TableOptionsSpecification<T>> {
protected Map<String, Object> options = new LinkedHashMap<String, Object>();
@SuppressWarnings("unchecked")
public T name(String name) {
return (T) super.name(name);
}
/**
* Convenience method that calls <code>with(option, null)</code>.
*
* @return this
*/
public T with(TableOption option) {
return with(option, null);
}
/**
* Sets the given table option. This is a convenience method that calls
* {@link #with(String, Object, boolean, boolean)} appropriately from the given {@link TableOption} and value for that
* option.
*
* @param option The option to set.
* @param value The value of the option. Must be type-compatible with the {@link TableOption}.
* @return this
* @see #with(String, Object, boolean, boolean)
*/
public T with(TableOption option, Object value) {
option.checkValue(value);
return (T) with(option.getName(), value, option.escapesValue(), option.quotesValue());
}
/**
* Adds the given option by name to this table's options.
* <p/>
* Options that have <code>null</code> values are considered single string options where the name of the option is the
* string to be used. Otherwise, the result of {@link Object#toString()} is considered to be the value of the option
* with the given name. The value, after conversion to string, may have embedded single quotes escaped according to
* parameter <code>escape</code> and may be single-quoted according to parameter <code>quote</code>.
*
* @param name The name of the option
* @param value The value of the option. If <code>null</code>, the value is ignored and the option is considered to be
* composed of only the name, otherwise the value's {@link Object#toString()} value is used.
* @param escape Whether to escape the value via {@link CqlStringUtils#escapeSingle(Object)}. Ignored if given value
* is an instance of a {@link Map}.
* @param quote Whether to quote the value via {@link CqlStringUtils#singleQuote(Object)}. Ignored if given value is
* an instance of a {@link Map}.
* @return this
*/
@SuppressWarnings("unchecked")
public T with(String name, Object value, boolean escape, boolean quote) {
if (!(value instanceof Map)) {
if (escape) {
value = escapeSingle(value);
}
if (quote) {
value = singleQuote(value);
}
}
options.put(name, value);
return (T) this;
}
public Map<String, Object> getOptions() {
return Collections.unmodifiableMap(options);
}
}

View File

@@ -1,162 +0,0 @@
package org.springframework.cassandra.core.keyspace;
import static org.springframework.data.cassandra.mapping.KeyType.PARTITION;
import static org.springframework.data.cassandra.mapping.KeyType.PRIMARY;
import static org.springframework.data.cassandra.mapping.Ordering.ASCENDING;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.data.cassandra.mapping.KeyType;
import org.springframework.data.cassandra.mapping.Ordering;
import com.datastax.driver.core.DataType;
/**
* Builder class to support the construction of table specifications that have columns. This class can also be used as a
* standalone {@link TableDescriptor}, independent of {@link CreateTableSpecification}.
*
* @author Matthew T. Adams
*/
public class TableSpecification<T> extends TableOptionsSpecification<TableSpecification<T>> implements TableDescriptor {
/**
* List of all columns.
*/
private List<ColumnSpecification> columns = new ArrayList<ColumnSpecification>();
/**
* List of only those columns that comprise the partition key.
*/
private List<ColumnSpecification> partitionKeyColumns = new ArrayList<ColumnSpecification>();
/**
* List of only those columns that comprise the primary key that are not also part of the partition key.
*/
private List<ColumnSpecification> primaryKeyColumns = new ArrayList<ColumnSpecification>();
/**
* List of only those columns that are not partition or primary key columns.
*/
private List<ColumnSpecification> nonKeyColumns = new ArrayList<ColumnSpecification>();
/**
* Adds the given non-key column to the table. Must be specified after all primary key columns.
*
* @param name The column name; must be a valid unquoted or quoted identifier without the surrounding double quotes.
* @param type The data type of the column.
*/
public T column(String name, DataType type) {
return column(name, type, null, null);
}
/**
* Adds the given partition key column to the table. Must be specified before any other columns.
*
* @param name The column name; must be a valid unquoted or quoted identifier without the surrounding double quotes.
* @param type The data type of the column.
* @return this
*/
public T partitionKeyColumn(String name, DataType type) {
return column(name, type, PARTITION, null);
}
/**
* Adds the given primary key column to the table with ascending ordering. Must be specified after all partition key
* columns and before any non-key columns.
*
* @param name The column name; must be a valid unquoted or quoted identifier without the surrounding double quotes.
* @param type The data type of the column.
* @return this
*/
public T primaryKeyColumn(String name, DataType type) {
return primaryKeyColumn(name, type, ASCENDING);
}
/**
* Adds the given primary key column to the table with the given ordering (<code>null</code> meaning ascending). Must
* be specified after all partition key columns and before any non-key columns.
*
* @param name The column name; must be a valid unquoted or quoted identifier without the surrounding double quotes.
* @param type The data type of the column.
* @return this
*/
public T primaryKeyColumn(String name, DataType type, Ordering ordering) {
return column(name, type, PRIMARY, ordering);
}
/**
* Adds the given info as a new column to the table. Partition key columns must precede primary key columns, which
* must precede non-key columns.
*
* @param name The column name; must be a valid unquoted or quoted identifier without the surrounding double quotes.
* @param type The data type of the column.
* @param keyType Indicates key type. Null means that the column is not a key column.
* @param ordering If the given {@link KeyType} is {@link KeyType#PRIMARY}, then the given ordering is used, else
* ignored.
* @return this
*/
@SuppressWarnings("unchecked")
protected T column(String name, DataType type, KeyType keyType, Ordering ordering) {
ColumnSpecification column = new ColumnSpecification().name(name).type(type).keyType(keyType)
.ordering(keyType == PRIMARY ? ordering : null);
columns.add(column);
if (keyType == KeyType.PARTITION) {
partitionKeyColumns.add(column);
}
if (keyType == KeyType.PRIMARY) {
primaryKeyColumns.add(column);
}
if (keyType == null) {
nonKeyColumns.add(column);
}
return (T) this;
}
/**
* Returns an unmodifiable list of all columns.
*/
public List<ColumnSpecification> getColumns() {
return Collections.unmodifiableList(columns);
}
/**
* Returns an unmodifiable list of all partition key columns.
*/
public List<ColumnSpecification> getPartitionKeyColumns() {
return Collections.unmodifiableList(partitionKeyColumns);
}
/**
* Returns an unmodifiable list of all primary key columns that are not also partition key columns.
*/
public List<ColumnSpecification> getPrimaryKeyColumns() {
return Collections.unmodifiableList(primaryKeyColumns);
}
/**
* Returns an unmodifiable list of all primary key columns that are not also partition key columns.
*/
public List<ColumnSpecification> getKeyColumns() {
ArrayList<ColumnSpecification> keyColumns = new ArrayList<ColumnSpecification>();
keyColumns.addAll(partitionKeyColumns);
keyColumns.addAll(primaryKeyColumns);
return Collections.unmodifiableList(keyColumns);
}
/**
* Returns an unmodifiable list of all non-key columns.
*/
public List<ColumnSpecification> getNonKeyColumns() {
return Collections.unmodifiableList(nonKeyColumns);
}
}

View File

@@ -1,126 +0,0 @@
package org.springframework.cassandra.core.util;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* Builder for maps, which also conveniently implements {@link Map} via delegation for convenience so you don't have to
* actually {@link #build()} it (or forget to).
*
* @author Matthew T. Adams
* @param <K> The key type of the map.
* @param <V> The value type of the map.
*/
public class MapBuilder<K, V> implements Map<K, V> {
/**
* Factory method to construct a new <code>MapBuilder&lt;Object,Object&gt;</code>. Convenient if imported statically.
*/
public static MapBuilder<Object, Object> map() {
return map(Object.class, Object.class);
}
/**
* Factory method to construct a new builder with the given key &amp; value types. Convenient if imported statically.
*/
public static <K, V> MapBuilder<K, V> map(Class<K> keyType, Class<V> valueType) {
return new MapBuilder<K, V>();
}
/**
* Factory method to construct a new builder with a shallow copy of the given map. Convenient if imported statically.
*/
public static <K, V> MapBuilder<K, V> map(Map<K, V> source) {
return new MapBuilder<K, V>(source);
}
private Map<K, V> map;
public MapBuilder() {
this(new LinkedHashMap<K, V>());
}
/**
* Constructs a new instance with a copy of the given map.
*/
public MapBuilder(Map<K, V> source) {
this.map = new LinkedHashMap<K, V>(source);
}
/**
* Adds an entry to this map, then returns <code>this</code>.
*
* @return this
*/
public MapBuilder<K, V> entry(K key, V value) {
map.put(key, value);
return this;
}
/**
* Returns a new map based on the current state of this builder's map.
*
* @return A new Map<K, V> with this builder's map's current content.
*/
public Map<K, V> build() {
return new LinkedHashMap<K, V>(map);
}
public int size() {
return map.size();
}
public boolean isEmpty() {
return map.isEmpty();
}
public boolean containsKey(Object key) {
return map.containsKey(key);
}
public boolean containsValue(Object value) {
return map.containsValue(value);
}
public V get(Object key) {
return map.get(key);
}
public V put(K key, V value) {
return map.put(key, value);
}
public V remove(Object key) {
return map.remove(key);
}
public void putAll(Map<? extends K, ? extends V> m) {
map.putAll(m);
}
public void clear() {
map.clear();
}
public Set<K> keySet() {
return map.keySet();
}
public Collection<V> values() {
return map.values();
}
public Set<java.util.Map.Entry<K, V>> entrySet() {
return map.entrySet();
}
public boolean equals(Object o) {
return map.equals(o);
}
public int hashCode() {
return map.hashCode();
}
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import com.datastax.driver.core.Session;
/**
* @author David Webb
*
*/
public class CassandraAccessor implements InitializingBean {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private Session session;
private CassandraExceptionTranslator exceptionTranslator;
/**
* Set the exception translator for this instance.
*
* @see org.springframework.cassandra.support.CassandraExceptionTranslator
*/
public void setExceptionTranslator(CassandraExceptionTranslator exceptionTranslator) {
this.exceptionTranslator = exceptionTranslator;
}
/**
* Return the exception translator for this instance.
*/
public CassandraExceptionTranslator getExceptionTranslator() {
return this.exceptionTranslator;
}
/**
* Ensure that the Cassandra Session has been set
*/
public void afterPropertiesSet() {
if (getSession() == null) {
throw new IllegalArgumentException("Property 'session' is required");
}
}
/**
* @return Returns the session.
*/
public Session getSession() {
return session;
}
/**
* @param session The session to set.
*/
public void setSession(Session session) {
this.session = session;
}
}

View File

@@ -1,136 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support;
import org.springframework.cassandra.support.exception.CassandraAuthenticationException;
import org.springframework.cassandra.support.exception.CassandraConnectionFailureException;
import org.springframework.cassandra.support.exception.CassandraInsufficientReplicasAvailableException;
import org.springframework.cassandra.support.exception.CassandraInternalException;
import org.springframework.cassandra.support.exception.CassandraInvalidConfigurationInQueryException;
import org.springframework.cassandra.support.exception.CassandraInvalidQueryException;
import org.springframework.cassandra.support.exception.CassandraKeyspaceExistsException;
import org.springframework.cassandra.support.exception.CassandraQuerySyntaxException;
import org.springframework.cassandra.support.exception.CassandraReadTimeoutException;
import org.springframework.cassandra.support.exception.CassandraTableExistsException;
import org.springframework.cassandra.support.exception.CassandraTraceRetrievalException;
import org.springframework.cassandra.support.exception.CassandraTruncateException;
import org.springframework.cassandra.support.exception.CassandraTypeMismatchException;
import org.springframework.cassandra.support.exception.CassandraUnauthorizedException;
import org.springframework.cassandra.support.exception.CassandraUncategorizedException;
import org.springframework.cassandra.support.exception.CassandraWriteTimeoutException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import com.datastax.driver.core.WriteType;
import com.datastax.driver.core.exceptions.AlreadyExistsException;
import com.datastax.driver.core.exceptions.AuthenticationException;
import com.datastax.driver.core.exceptions.DriverException;
import com.datastax.driver.core.exceptions.DriverInternalError;
import com.datastax.driver.core.exceptions.InvalidConfigurationInQueryException;
import com.datastax.driver.core.exceptions.InvalidQueryException;
import com.datastax.driver.core.exceptions.InvalidTypeException;
import com.datastax.driver.core.exceptions.NoHostAvailableException;
import com.datastax.driver.core.exceptions.ReadTimeoutException;
import com.datastax.driver.core.exceptions.SyntaxError;
import com.datastax.driver.core.exceptions.TraceRetrievalException;
import com.datastax.driver.core.exceptions.TruncateException;
import com.datastax.driver.core.exceptions.UnauthorizedException;
import com.datastax.driver.core.exceptions.UnavailableException;
import com.datastax.driver.core.exceptions.WriteTimeoutException;
/**
* Simple {@link PersistenceExceptionTranslator} for Cassandra. Convert the given runtime exception to an appropriate
* exception from the {@code org.springframework.dao} hierarchy. Return {@literal null} if no translation is
* appropriate: any other exception may have resulted from user code, and should not be translated.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public class CassandraExceptionTranslator implements PersistenceExceptionTranslator {
/*
* (non-Javadoc)
*
* @see org.springframework.dao.support.PersistenceExceptionTranslator#
* translateExceptionIfPossible(java.lang.RuntimeException)
*/
public DataAccessException translateExceptionIfPossible(RuntimeException x) {
if (!(x instanceof DriverException)) {
return null;
}
if (x instanceof DataAccessException) {
return (DataAccessException) x;
}
// Remember: subclasses must come before superclasses, otherwise the
// superclass would match before the subclass!
if (x instanceof AuthenticationException) {
return new CassandraAuthenticationException(((AuthenticationException) x).getHost(), x.getMessage(), x);
}
if (x instanceof DriverInternalError) {
return new CassandraInternalException(x.getMessage(), x);
}
if (x instanceof InvalidTypeException) {
return new CassandraTypeMismatchException(x.getMessage(), x);
}
if (x instanceof NoHostAvailableException) {
return new CassandraConnectionFailureException(((NoHostAvailableException) x).getErrors(), x.getMessage(), x);
}
if (x instanceof ReadTimeoutException) {
return new CassandraReadTimeoutException(((ReadTimeoutException) x).wasDataRetrieved(), x.getMessage(), x);
}
if (x instanceof WriteTimeoutException) {
WriteType writeType = ((WriteTimeoutException) x).getWriteType();
return new CassandraWriteTimeoutException(writeType == null ? null : writeType.name(), x.getMessage(), x);
}
if (x instanceof TruncateException) {
return new CassandraTruncateException(x.getMessage(), x);
}
if (x instanceof UnavailableException) {
UnavailableException ux = (UnavailableException) x;
return new CassandraInsufficientReplicasAvailableException(ux.getRequiredReplicas(), ux.getAliveReplicas(),
x.getMessage(), x);
}
if (x instanceof AlreadyExistsException) {
AlreadyExistsException aex = (AlreadyExistsException) x;
return aex.wasTableCreation() ? new CassandraTableExistsException(aex.getTable(), x.getMessage(), x)
: new CassandraKeyspaceExistsException(aex.getKeyspace(), x.getMessage(), x);
}
if (x instanceof InvalidConfigurationInQueryException) {
return new CassandraInvalidConfigurationInQueryException(x.getMessage(), x);
}
if (x instanceof InvalidQueryException) {
return new CassandraInvalidQueryException(x.getMessage(), x);
}
if (x instanceof SyntaxError) {
return new CassandraQuerySyntaxException(x.getMessage(), x);
}
if (x instanceof UnauthorizedException) {
return new CassandraUnauthorizedException(x.getMessage(), x);
}
if (x instanceof TraceRetrievalException) {
return new CassandraTraceRetrievalException(x.getMessage(), x);
}
// unknown or unhandled exception
return new CassandraUncategorizedException(x.getMessage(), x);
}
}

View File

@@ -1,42 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import java.net.InetAddress;
import org.springframework.dao.PermissionDeniedDataAccessException;
/**
* Spring data access exception for a Cassandra authentication failure.
*
* @author Matthew T. Adams
*/
public class CassandraAuthenticationException extends PermissionDeniedDataAccessException {
private static final long serialVersionUID = 8556304586797273927L;
private InetAddress host;
public CassandraAuthenticationException(InetAddress host, String msg, Throwable cause) {
super(msg, cause);
this.host = host;
}
public InetAddress getHost() {
return host;
}
}

View File

@@ -1,45 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import java.net.InetAddress;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.springframework.dao.DataAccessResourceFailureException;
/**
* Spring data access exception for Cassandra when no host is available.
*
* @author Matthew T. Adams
*/
public class CassandraConnectionFailureException extends DataAccessResourceFailureException {
private static final long serialVersionUID = 6299912054261646552L;
private final Map<InetAddress, String> messagesByHost = new HashMap<InetAddress, String>();
public CassandraConnectionFailureException(Map<InetAddress, String> messagesByHost, String msg, Throwable cause) {
super(msg, cause);
this.messagesByHost.putAll(messagesByHost);
}
public Map<InetAddress, String> getMessagesByHost() {
return Collections.unmodifiableMap(messagesByHost);
}
}

View File

@@ -1,51 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.TransientDataAccessException;
/**
* Spring data access exception for Cassandra when insufficient replicas are available for a given consistency level.
*
* @author Matthew T. Adams
*/
public class CassandraInsufficientReplicasAvailableException extends TransientDataAccessException {
private static final long serialVersionUID = 6415130674604814905L;
private int numberRequired;
private int numberAlive;
public CassandraInsufficientReplicasAvailableException(String msg) {
super(msg);
}
public CassandraInsufficientReplicasAvailableException(int numberRequired, int numberAlive, String msg,
Throwable cause) {
super(msg, cause);
this.numberRequired = numberRequired;
this.numberAlive = numberAlive;
}
public int getNumberRequired() {
return numberRequired;
}
public int getNumberAlive() {
return numberAlive;
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.DataAccessException;
/**
* Spring data access exception for a Cassandra internal error.
*
* @author Matthew T. Adams
*/
public class CassandraInternalException extends DataAccessException {
private static final long serialVersionUID = 433061676465346338L;
public CassandraInternalException(String msg) {
super(msg);
}
public CassandraInternalException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -1,38 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.InvalidDataAccessApiUsageException;
/**
* Spring data access exception for a Cassandra query that is syntactically correct but has an invalid configuration
* clause.
*
* @author Matthew T. Adams
*/
public class CassandraInvalidConfigurationInQueryException extends InvalidDataAccessApiUsageException {
private static final long serialVersionUID = 4594321191806182918L;
public CassandraInvalidConfigurationInQueryException(String msg) {
super(msg);
}
public CassandraInvalidConfigurationInQueryException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.InvalidDataAccessApiUsageException;
/**
* Spring data access exception for a Cassandra query that's syntactically correct but invalid.
*
* @author Matthew T. Adams
*/
public class CassandraInvalidQueryException extends InvalidDataAccessApiUsageException {
private static final long serialVersionUID = 4594321191806182918L;
public CassandraInvalidQueryException(String msg) {
super(msg);
}
public CassandraInvalidQueryException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
/**
* Spring data access exception for Cassandra when a keyspace being created already exists.
*
* @author Matthew T. Adams
*/
public class CassandraKeyspaceExistsException extends CassandraSchemaElementExistsException {
private static final long serialVersionUID = 6032967419751410352L;
public CassandraKeyspaceExistsException(String keyspaceName, String msg, Throwable cause) {
super(keyspaceName, ElementType.KEYSPACE, msg, cause);
}
public String getKeyspaceName() {
return getElementName();
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.InvalidDataAccessApiUsageException;
/**
* Spring data access exception for a Cassandra query syntax error.
*
* @author Matthew T. Adams
*/
public class CassandraQuerySyntaxException extends InvalidDataAccessApiUsageException {
private static final long serialVersionUID = 4398474399882434154L;
public CassandraQuerySyntaxException(String msg) {
super(msg);
}
public CassandraQuerySyntaxException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.QueryTimeoutException;
/**
* Spring data access exception for a Cassandra read timeout.
*
* @author Matthew T. Adams
*/
public class CassandraReadTimeoutException extends QueryTimeoutException {
private static final long serialVersionUID = -787022307935203387L;
private boolean wasDataReceived;
public CassandraReadTimeoutException(boolean wasDataReceived, String msg, Throwable cause) {
super(msg);
this.wasDataReceived = wasDataReceived;
}
public boolean getWasDataReceived() {
return wasDataReceived;
}
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.NonTransientDataAccessException;
/**
* Spring data access exception for when Cassandra schema element being created already exists.
*
* @author Matthew T. Adams
*/
public class CassandraSchemaElementExistsException extends NonTransientDataAccessException {
private static final long serialVersionUID = 7798361273692300162L;
public enum ElementType {
KEYSPACE, TABLE, COLUMN, INDEX;
}
private String elementName;
private ElementType elementType;
public CassandraSchemaElementExistsException(String elementName, ElementType elementType, String msg, Throwable cause) {
super(msg, cause);
this.elementName = elementName;
this.elementType = elementType;
}
public String getElementName() {
return elementName;
}
public ElementType getElementType() {
return elementType;
}
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
/**
* Spring data access exception for when a Cassandra table being created already exists.
*
* @author Matthew T. Adams
*/
public class CassandraTableExistsException extends CassandraSchemaElementExistsException {
private static final long serialVersionUID = 6032967419751410352L;
public CassandraTableExistsException(String tableName, String msg, Throwable cause) {
super(tableName, ElementType.TABLE, msg, cause);
}
public String getTableName() {
return getElementName();
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.TransientDataAccessException;
/**
* Spring data access exception for a Cassandra trace retrieval exception.
*
* @author Matthew T. Adams
*/
public class CassandraTraceRetrievalException extends TransientDataAccessException {
private static final long serialVersionUID = -3163557220324700239L;
public CassandraTraceRetrievalException(String msg) {
super(msg);
}
public CassandraTraceRetrievalException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.TransientDataAccessException;
/**
* Spring data access exception for a Cassandra truncate exception.
*
* @author Matthew T. Adams
*/
public class CassandraTruncateException extends TransientDataAccessException {
private static final long serialVersionUID = 5730642491362430311L;
public CassandraTruncateException(String msg) {
super(msg);
}
public CassandraTruncateException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.TypeMismatchDataAccessException;
/**
* Spring data access exception for a Cassandra type mismatch exception.
*
* @author Matthew T. Adams
*/
public class CassandraTypeMismatchException extends TypeMismatchDataAccessException {
private static final long serialVersionUID = -7420058975444905629L;
public CassandraTypeMismatchException(String msg) {
super(msg);
}
public CassandraTypeMismatchException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.PermissionDeniedDataAccessException;
/**
* Spring data access exception for when access to a Cassandra element is denied.
*
* @author Matthew T. Adams
*/
public class CassandraUnauthorizedException extends PermissionDeniedDataAccessException {
private static final long serialVersionUID = 4618185356687726647L;
public CassandraUnauthorizedException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -1,33 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.UncategorizedDataAccessException;
/**
* Spring data access exception for an uncategorized Cassandra exception.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public class CassandraUncategorizedException extends UncategorizedDataAccessException {
private static final long serialVersionUID = 1029525121238025444L;
public CassandraUncategorizedException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright 2010-2013 the original author or authors.
*
* 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 org.springframework.cassandra.support.exception;
import org.springframework.dao.QueryTimeoutException;
/**
* Spring data access exception for a Cassandra write timeout.
*
* @author Matthew T. Adams
*/
public class CassandraWriteTimeoutException extends QueryTimeoutException {
private static final long serialVersionUID = -4374826375213670718L;
private String writeType;
public CassandraWriteTimeoutException(String writeType, String msg, Throwable cause) {
super(msg, cause);
this.writeType = writeType;
}
public String getWriteType() {
return writeType;
}
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.data.cassandra;
/**
* @author David Webb
*
*/
public interface Constants {
}

View File

@@ -1,203 +0,0 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* 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 org.springframework.data.cassandra.config;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.cassandra.core.CassandraOperations;
import org.springframework.cassandra.core.CassandraTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.core.CassandraAdminOperations;
import org.springframework.data.cassandra.core.CassandraAdminTemplate;
import org.springframework.data.cassandra.core.Keyspace;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
/**
* Base class for Spring Data Cassandra configuration using JavaConfig.
*
* @author Alex Shvid
*/
@Configuration
public abstract class AbstractCassandraConfiguration implements BeanClassLoaderAware {
/**
* Used by CassandraTemplate and CassandraAdminTemplate
*/
private ClassLoader beanClassLoader;
/**
* Return the name of the keyspace to connect to.
*
* @return must not be {@literal null}.
*/
protected abstract String getKeyspaceName();
/**
* Return the {@link Cluster} instance to connect to.
*
* @return
* @throws Exception
*/
@Bean
public abstract Cluster cluster() throws Exception;
/**
* Creates a {@link Session} to be used by the {@link Keyspace}. Will use the {@link Cluster} instance configured in
* {@link #cluster()}.
*
* @see #cluster()
* @see #Keyspace()
* @return
* @throws Exception
*/
@Bean
public Session session() throws Exception {
String keyspace = getKeyspaceName();
if (StringUtils.hasText(keyspace)) {
return cluster().connect(keyspace);
} else {
return cluster().connect();
}
}
/**
* Creates a {@link Keyspace} to be used by the {@link CassandraTemplate}. Will use the {@link Session} instance
* configured in {@link #session()} and {@link CassandraConverter} configured in {@link #converter()}.
*
* @see #cluster()
* @see #Keyspace()
* @return
* @throws Exception
*/
@Bean
public Keyspace keyspace() throws Exception {
return new Keyspace(getKeyspaceName(), session(), converter());
}
/**
* Return the base package to scan for mapped {@link Table}s. Will return the package name of the configuration class'
* (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending
* {@link AbstractCassandraConfiguration} the base package will be considered {@code com.acme} unless the method is
* overriden to implement alternate behaviour.
*
* @return the base package to scan for mapped {@link Table} classes or {@literal null} to not enable scanning for
* entities.
*/
protected String getMappingBasePackage() {
return getClass().getPackage().getName();
}
/**
* Creates a {@link CassandraTemplate}.
*
* @return
* @throws Exception
*/
@Bean
public CassandraOperations cassandraTemplate() throws Exception {
return new CassandraTemplate(session());
}
/**
* Creates a {@link CassandraAdminTemplate}.
*
* @return
* @throws Exception
*/
@Bean
public CassandraAdminOperations cassandraAdminTemplate() throws Exception {
return new CassandraAdminTemplate(keyspace());
}
/**
* Return the {@link MappingContext} instance to map Entities to properties.
*
* @return
* @throws Exception
*/
@Bean
public MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext() {
return new CassandraMappingContext();
}
/**
* Return the {@link CassandraConverter} instance to convert Rows to Objects, Objects to BuiltStatements
*
* @return
* @throws Exception
*/
@Bean
public CassandraConverter converter() {
MappingCassandraConverter converter = new MappingCassandraConverter(mappingContext());
converter.setBeanClassLoader(beanClassLoader);
return converter;
}
/**
* Scans the mapping base package for classes annotated with {@link Table}.
*
* @see #getMappingBasePackage()
* @return
* @throws ClassNotFoundException
*/
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
String basePackage = getMappingBasePackage();
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Table.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(),
AbstractCassandraConfiguration.class.getClassLoader()));
}
}
return initialEntitySet;
}
/**
* Bean ClassLoader Aware for CassandraTemplate/CassandraAdminTemplate
*/
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright (c) 2011 by the original author(s).
*
* 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 org.springframework.data.cassandra.config;
/**
* @author Alex Shvid
* @author David Webb
*/
public final class BeanNames {
private BeanNames() {
}
public static final String CASSANDRA_CLUSTER = "cassandra-cluster";
public static final String CASSANDRA_KEYSPACE = "cassandra-keyspace";
public static final String CASSANDRA_SESSION = "cassandra-session";
}

View File

@@ -1,118 +0,0 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* 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 org.springframework.data.cassandra.config;
import java.util.List;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.cassandra.core.CassandraClusterFactoryBean;
import org.springframework.data.config.ParsingUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Parser for &lt;cluster;gt; definitions.
*
* @author Alex Shvid
*/
public class CassandraClusterParser extends AbstractSimpleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return CassandraClusterFactoryBean.class;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
*/
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
return StringUtils.hasText(id) ? id : BeanNames.CASSANDRA_CLUSTER;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String contactPoints = element.getAttribute("contactPoints");
if (StringUtils.hasText(contactPoints)) {
builder.addPropertyValue("contactPoints", contactPoints);
}
String port = element.getAttribute("port");
if (StringUtils.hasText(port)) {
builder.addPropertyValue("port", port);
}
String compression = element.getAttribute("compression");
if (StringUtils.hasText(compression)) {
builder.addPropertyValue("compressionType", CompressionType.valueOf(compression));
}
postProcess(builder, element);
}
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
List<Element> subElements = DomUtils.getChildElements(element);
// parse nested elements
for (Element subElement : subElements) {
String name = subElement.getLocalName();
if ("local-pooling-options".equals(name)) {
builder.addPropertyValue("localPoolingOptions", parsePoolingOptions(subElement));
} else if ("remote-pooling-options".equals(name)) {
builder.addPropertyValue("remotePoolingOptions", parsePoolingOptions(subElement));
} else if ("socket-options".equals(name)) {
builder.addPropertyValue("socketOptions", parseSocketOptions(subElement));
}
}
}
private BeanDefinition parsePoolingOptions(Element element) {
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(PoolingOptionsConfig.class);
ParsingUtils.setPropertyValue(defBuilder, element, "min-simultaneous-requests", "minSimultaneousRequests");
ParsingUtils.setPropertyValue(defBuilder, element, "max-simultaneous-requests", "maxSimultaneousRequests");
ParsingUtils.setPropertyValue(defBuilder, element, "core-connections", "coreConnections");
ParsingUtils.setPropertyValue(defBuilder, element, "max-connections", "maxConnections");
return defBuilder.getBeanDefinition();
}
private BeanDefinition parseSocketOptions(Element element) {
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(SocketOptionsConfig.class);
ParsingUtils.setPropertyValue(defBuilder, element, "connect-timeout-mls", "connectTimeoutMls");
ParsingUtils.setPropertyValue(defBuilder, element, "keep-alive", "keepAlive");
ParsingUtils.setPropertyValue(defBuilder, element, "reuse-address", "reuseAddress");
ParsingUtils.setPropertyValue(defBuilder, element, "so-linger", "soLinger");
ParsingUtils.setPropertyValue(defBuilder, element, "tcp-no-delay", "tcpNoDelay");
ParsingUtils.setPropertyValue(defBuilder, element, "receive-buffer-size", "receiveBufferSize");
ParsingUtils.setPropertyValue(defBuilder, element, "send-buffer-size", "sendBufferSize");
return defBuilder.getBeanDefinition();
}
}

View File

@@ -1,127 +0,0 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* 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 org.springframework.data.cassandra.config;
import java.util.List;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.cassandra.core.CassandraKeyspaceFactoryBean;
import org.springframework.data.config.ParsingUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Parser for &lt;keyspace;gt; definitions.
*
* @author Alex Shvid
*/
public class CassandraKeyspaceParser extends AbstractSimpleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return CassandraKeyspaceFactoryBean.class;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
*/
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
return StringUtils.hasText(id) ? id : BeanNames.CASSANDRA_KEYSPACE;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String name = element.getAttribute("name");
if (StringUtils.hasText(name)) {
builder.addPropertyValue("keyspace", name);
}
String clusterRef = element.getAttribute("cassandra-cluster-ref");
if (!StringUtils.hasText(clusterRef)) {
clusterRef = BeanNames.CASSANDRA_CLUSTER;
}
builder.addPropertyReference("cluster", clusterRef);
String converterRef = element.getAttribute("cassandra-converter-ref");
if (StringUtils.hasText(converterRef)) {
builder.addPropertyReference("converter", converterRef);
}
postProcess(builder, element);
}
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
List<Element> subElements = DomUtils.getChildElements(element);
// parse nested elements
for (Element subElement : subElements) {
String name = subElement.getLocalName();
if ("keyspace-attributes".equals(name)) {
builder.addPropertyValue("keyspaceAttributes", parseKeyspaceAttributes(subElement));
}
}
}
private BeanDefinition parseKeyspaceAttributes(Element element) {
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(KeyspaceAttributes.class);
ParsingUtils.setPropertyValue(defBuilder, element, "auto", "auto");
ParsingUtils.setPropertyValue(defBuilder, element, "replication-strategy", "replicationStrategy");
ParsingUtils.setPropertyValue(defBuilder, element, "replication-factor", "replicationFactor");
ParsingUtils.setPropertyValue(defBuilder, element, "durable-writes", "durableWrites");
List<Element> subElements = DomUtils.getChildElements(element);
ManagedList<Object> tables = new ManagedList<Object>(subElements.size());
// parse nested elements
for (Element subElement : subElements) {
String name = subElement.getLocalName();
if ("table".equals(name)) {
tables.add(parseTable(subElement));
}
}
if (!tables.isEmpty()) {
defBuilder.addPropertyValue("tables", tables);
}
return defBuilder.getBeanDefinition();
}
private BeanDefinition parseTable(Element element) {
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(TableAttributes.class);
ParsingUtils.setPropertyValue(defBuilder, element, "entity", "entity");
ParsingUtils.setPropertyValue(defBuilder, element, "name", "name");
return defBuilder.getBeanDefinition();
}
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.data.cassandra.config;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* Namespace handler for &lt;cassandra;gt;.
*
* @author Alex Shvid
*/
public class CassandraNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("cluster", new CassandraClusterParser());
registerBeanDefinitionParser("keyspace", new CassandraKeyspaceParser());
registerBeanDefinitionParser("session", new CassandraSessionParser());
}
}

View File

@@ -1,69 +0,0 @@
/*
* Copyright 2011-2012 the original author or authors.
*
* 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 org.springframework.data.cassandra.config;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.cassandra.core.SessionFactoryBean;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Parser for &lt;session;gt; definitions.
*
* @author David Webb
*/
public class CassandraSessionParser extends AbstractSimpleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return SessionFactoryBean.class;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
*/
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
return StringUtils.hasText(id) ? id : BeanNames.CASSANDRA_SESSION;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String keyspaceRef = element.getAttribute("cassandra-keyspace-ref");
if (!StringUtils.hasText(keyspaceRef)) {
keyspaceRef = BeanNames.CASSANDRA_KEYSPACE;
}
builder.addPropertyReference("keyspace", keyspaceRef);
postProcess(builder, element);
}
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
}
}

View File

@@ -1,25 +0,0 @@
/*
* Copyright 2010-2012 the original author or authors.
*
* 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 org.springframework.data.cassandra.config;
/**
* Simple enumeration for the various compression types.
*
* @author Alex Shvid
*/
public enum CompressionType {
NONE, SNAPPY;
}

View File

@@ -1,107 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.data.cassandra.config;
import java.util.Collection;
/**
* Keyspace attributes are used for manipulation around keyspace at the startup. Auto property defines the way how to do
* this. Other attributes used to ensure or update keyspace settings.
*
* @author Alex Shvid
*/
public class KeyspaceAttributes {
public static final String DEFAULT_REPLICATION_STRATEGY = "SimpleStrategy";
public static final int DEFAULT_REPLICATION_FACTOR = 1;
public static final boolean DEFAULT_DURABLE_WRITES = true;
/*
* auto possible values:
* validate: validate the keyspace, makes no changes.
* update: update the keyspace.
* create: creates the keyspace, destroying previous data.
* create-drop: drop the keyspace at the end of the session.
*/
public static final String AUTO_VALIDATE = "validate";
public static final String AUTO_UPDATE = "update";
public static final String AUTO_CREATE = "create";
public static final String AUTO_CREATE_DROP = "create-drop";
private String auto = AUTO_VALIDATE;
private String replicationStrategy = DEFAULT_REPLICATION_STRATEGY;
private int replicationFactor = DEFAULT_REPLICATION_FACTOR;
private boolean durableWrites = DEFAULT_DURABLE_WRITES;
private Collection<TableAttributes> tables;
public String getAuto() {
return auto;
}
public void setAuto(String auto) {
this.auto = auto;
}
public boolean isValidate() {
return AUTO_VALIDATE.equals(auto);
}
public boolean isUpdate() {
return AUTO_UPDATE.equals(auto);
}
public boolean isCreate() {
return AUTO_CREATE.equals(auto);
}
public boolean isCreateDrop() {
return AUTO_CREATE_DROP.equals(auto);
}
public String getReplicationStrategy() {
return replicationStrategy;
}
public void setReplicationStrategy(String replicationStrategy) {
this.replicationStrategy = replicationStrategy;
}
public int getReplicationFactor() {
return replicationFactor;
}
public void setReplicationFactor(int replicationFactor) {
this.replicationFactor = replicationFactor;
}
public boolean isDurableWrites() {
return durableWrites;
}
public void setDurableWrites(boolean durableWrites) {
this.durableWrites = durableWrites;
}
public Collection<TableAttributes> getTables() {
return tables;
}
public void setTables(Collection<TableAttributes> tables) {
this.tables = tables;
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.data.cassandra.config;
/**
* Pooling options POJO. Can be remote or local.
*
* @author Alex Shvid
*/
public class PoolingOptionsConfig {
private Integer minSimultaneousRequests;
private Integer maxSimultaneousRequests;
private Integer coreConnections;
private Integer maxConnections;
public Integer getMinSimultaneousRequests() {
return minSimultaneousRequests;
}
public void setMinSimultaneousRequests(Integer minSimultaneousRequests) {
this.minSimultaneousRequests = minSimultaneousRequests;
}
public Integer getMaxSimultaneousRequests() {
return maxSimultaneousRequests;
}
public void setMaxSimultaneousRequests(Integer maxSimultaneousRequests) {
this.maxSimultaneousRequests = maxSimultaneousRequests;
}
public Integer getCoreConnections() {
return coreConnections;
}
public void setCoreConnections(Integer coreConnections) {
this.coreConnections = coreConnections;
}
public Integer getMaxConnections() {
return maxConnections;
}
public void setMaxConnections(Integer maxConnections) {
this.maxConnections = maxConnections;
}
}

View File

@@ -1,89 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.data.cassandra.config;
/**
* Socket options POJO. Uses to configure Netty.
*
* @author Alex Shvid
*/
public class SocketOptionsConfig {
private Integer connectTimeoutMls;
private Boolean keepAlive;
private Boolean reuseAddress;
private Integer soLinger;
private Boolean tcpNoDelay;
private Integer receiveBufferSize;
private Integer sendBufferSize;
public Integer getConnectTimeoutMls() {
return connectTimeoutMls;
}
public void setConnectTimeoutMls(Integer connectTimeoutMls) {
this.connectTimeoutMls = connectTimeoutMls;
}
public Boolean getKeepAlive() {
return keepAlive;
}
public void setKeepAlive(Boolean keepAlive) {
this.keepAlive = keepAlive;
}
public Boolean getReuseAddress() {
return reuseAddress;
}
public void setReuseAddress(Boolean reuseAddress) {
this.reuseAddress = reuseAddress;
}
public Integer getSoLinger() {
return soLinger;
}
public void setSoLinger(Integer soLinger) {
this.soLinger = soLinger;
}
public Boolean getTcpNoDelay() {
return tcpNoDelay;
}
public void setTcpNoDelay(Boolean tcpNoDelay) {
this.tcpNoDelay = tcpNoDelay;
}
public Integer getReceiveBufferSize() {
return receiveBufferSize;
}
public void setReceiveBufferSize(Integer receiveBufferSize) {
this.receiveBufferSize = receiveBufferSize;
}
public Integer getSendBufferSize() {
return sendBufferSize;
}
public void setSendBufferSize(Integer sendBufferSize) {
this.sendBufferSize = sendBufferSize;
}
}

View File

@@ -1,49 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.data.cassandra.config;
/**
* Table attributes are used for manipulation around table at the startup (create/update/validate).
*
* @author Alex Shvid
*/
public class TableAttributes {
private String entity;
private String name;
public String getEntity() {
return entity;
}
public void setEntity(String entity) {
this.entity = entity;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "TableAttributes [entity=" + entity + "]";
}
}

View File

@@ -1,67 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.data.cassandra.convert;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.convert.EntityInstantiators;
/**
* Base class for {@link CassandraConverter} implementations. Sets up a {@link GenericConversionService} and populates
* basic converters.
*
* @author Alex Shvid
*/
public abstract class AbstractCassandraConverter implements CassandraConverter, InitializingBean {
protected final GenericConversionService conversionService;
protected EntityInstantiators instantiators = new EntityInstantiators();
/**
* Creates a new {@link AbstractCassandraConverter} using the given {@link GenericConversionService}.
*
* @param conversionService
*/
public AbstractCassandraConverter(GenericConversionService conversionService) {
this.conversionService = conversionService == null ? new DefaultConversionService() : conversionService;
}
/**
* Registers {@link EntityInstantiators} to customize entity instantiation.
*
* @param instantiators
*/
public void setInstantiators(EntityInstantiators instantiators) {
this.instantiators = instantiators == null ? new EntityInstantiators() : instantiators;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.core.convert.MongoConverter#getConversionService()
*/
public ConversionService getConversionService() {
return conversionService;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() {
}
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright 2010-2011 the original author or authors.
*
* 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 org.springframework.data.cassandra.convert;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.convert.EntityConverter;
/**
* Central Cassandra specific converter interface from Object to Row.
*
* @author Alex Shvid
*/
public interface CassandraConverter extends
EntityConverter<CassandraPersistentEntity<?>, CassandraPersistentProperty, Object, Object> {
}

View File

@@ -1,95 +0,0 @@
/*
* Copyright 2012 the original author or authors.
*
* 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 org.springframework.data.cassandra.convert;
import java.nio.ByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.util.CqlUtils;
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
import org.springframework.data.mapping.model.PropertyValueProvider;
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
import org.springframework.util.Assert;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.Row;
/**
* {@link PropertyValueProvider} to read property values from a {@link Row}.
*
* @author Alex Shvid
*/
public class CassandraPropertyValueProvider implements PropertyValueProvider<CassandraPersistentProperty> {
private static Logger log = LoggerFactory.getLogger(CassandraPropertyValueProvider.class);
private final Row source;
private final SpELExpressionEvaluator evaluator;
/**
* Creates a new {@link CassandraPropertyValueProvider} with the given {@link Row} and
* {@link DefaultSpELExpressionEvaluator}.
*
* @param source must not be {@literal null}.
* @param evaluator must not be {@literal null}.
*/
public CassandraPropertyValueProvider(Row source, DefaultSpELExpressionEvaluator evaluator) {
Assert.notNull(source);
Assert.notNull(evaluator);
this.source = source;
this.evaluator = evaluator;
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.PropertyValueProvider#getPropertyValue(org.springframework.data.mapping.PersistentProperty)
*/
@SuppressWarnings("unchecked")
public <T> T getPropertyValue(CassandraPersistentProperty property) {
String expression = property.getSpelExpression();
if (expression != null) {
return evaluator.evaluate(expression);
}
String columnName = property.getColumnName();
if (source.isNull(property.getColumnName())) {
return null;
}
DataType columnType = source.getColumnDefinitions().getType(columnName);
log.info(columnType.getName().name());
/*
* Dave Webb - Added handler for text since getBytes was throwing
* InvalidTypeException when using getBytes on a text column.
*/
// TODO Might need to qualify all DataTypes as we encounter them.
if (columnType.equals(DataType.text())) {
return (T) source.getString(columnName);
}
if (columnType.equals(DataType.cint())) {
return (T) new Integer(source.getInt(columnName));
}
ByteBuffer bytes = source.getBytes(columnName);
return (T) columnType.deserialize(bytes);
}
}

View File

@@ -1,278 +0,0 @@
/*
* Copyright 2011-2013 by the original author(s).
*
* 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 org.springframework.data.cassandra.convert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.convert.EntityInstantiator;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
import org.springframework.data.mapping.model.PropertyValueProvider;
import org.springframework.data.mapping.model.SpELContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.ClassUtils;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.querybuilder.Delete.Where;
import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Update;
/**
* {@link CassandraConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
* {@link Row}.
*
* @author Alex Shvid
*/
public class MappingCassandraConverter extends AbstractCassandraConverter implements ApplicationContextAware,
BeanClassLoaderAware {
protected static final Logger log = LoggerFactory.getLogger(MappingCassandraConverter.class);
protected final MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext;
protected ApplicationContext applicationContext;
private SpELContext spELContext;
private boolean useFieldAccessOnly = true;
private ClassLoader beanClassLoader;
/**
* Creates a new {@link MappingCassandraConverter} given the new {@link MappingContext}.
*
* @param mappingContext must not be {@literal null}.
*/
public MappingCassandraConverter(
MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext) {
super(new DefaultConversionService());
this.mappingContext = mappingContext;
this.spELContext = new SpELContext(RowReaderPropertyAccessor.INSTANCE);
}
@SuppressWarnings("unchecked")
public <R> R readRow(Class<R> clazz, Row row) {
Class<R> beanClassLoaderClass = transformClassToBeanClassLoaderClass(clazz);
TypeInformation<? extends R> type = ClassTypeInformation.from(beanClassLoaderClass);
// TypeInformation<? extends R> typeToUse = typeMapper.readType(row, type);
TypeInformation<? extends R> typeToUse = type;
Class<? extends R> rawType = typeToUse.getType();
if (Row.class.isAssignableFrom(rawType)) {
return (R) row;
}
CassandraPersistentEntity<R> persistentEntity = (CassandraPersistentEntity<R>) mappingContext
.getPersistentEntity(typeToUse);
if (persistentEntity == null) {
throw new MappingException("No mapping metadata found for " + rawType.getName());
}
return readRowInternal(persistentEntity, row);
}
/*
* (non-Javadoc)
* @see org.springframework.data.convert.EntityConverter#getMappingContext()
*/
public MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> getMappingContext() {
return mappingContext;
}
/*
* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
this.spELContext = new SpELContext(this.spELContext, applicationContext);
}
private <S extends Object> S readRowInternal(final CassandraPersistentEntity<S> entity, final Row row) {
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(row, spELContext);
final PropertyValueProvider<CassandraPersistentProperty> propertyProvider = new CassandraPropertyValueProvider(row,
evaluator);
PersistentEntityParameterValueProvider<CassandraPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<CassandraPersistentProperty>(
entity, propertyProvider, null);
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
S instance = instantiator.createInstance(entity, parameterProvider);
final BeanWrapper<CassandraPersistentEntity<S>, S> wrapper = BeanWrapper.create(instance, conversionService);
final S result = wrapper.getBean();
// Set properties not already set in the constructor
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
boolean isConstructorProperty = entity.isConstructorArgument(prop);
boolean hasValueForProperty = row.getColumnDefinitions().contains(prop.getColumnName());
if (!hasValueForProperty || isConstructorProperty) {
return;
}
Object obj = propertyProvider.getPropertyValue(prop);
wrapper.setProperty(prop, obj, useFieldAccessOnly);
}
});
return result;
}
public void setUseFieldAccessOnly(boolean useFieldAccessOnly) {
this.useFieldAccessOnly = useFieldAccessOnly;
}
/* (non-Javadoc)
* @see org.springframework.data.convert.EntityWriter#write(java.lang.Object, java.lang.Object)
*/
@Override
public <R> R read(Class<R> type, Object row) {
if (row instanceof Row) {
return readRow(type, (Row) row);
}
throw new MappingException("Unknown row object " + row.getClass().getName());
}
/* (non-Javadoc)
* @see org.springframework.data.convert.EntityWriter#write(java.lang.Object, java.lang.Object)
*/
@Override
public void write(Object obj, Object builtStatement) {
if (obj == null) {
return;
}
Class<?> beanClassLoaderClass = transformClassToBeanClassLoaderClass(obj.getClass());
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(beanClassLoaderClass);
if (entity == null) {
throw new MappingException("No mapping metadata found for " + obj.getClass());
}
if (builtStatement instanceof Insert) {
writeInsertInternal(obj, (Insert) builtStatement, entity);
} else if (builtStatement instanceof Update) {
writeUpdateInternal(obj, (Update) builtStatement, entity);
} else if (builtStatement instanceof Where) {
writeDeleteWhereInternal(obj, (Where) builtStatement, entity);
} else {
throw new MappingException("Unknown buildStatement " + builtStatement.getClass().getName());
}
}
private void writeInsertInternal(final Object objectToSave, final Insert insert, CassandraPersistentEntity<?> entity) {
final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(objectToSave,
conversionService);
// Write the properties
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
if (propertyObj != null) {
insert.value(prop.getColumnName(), propertyObj);
}
}
});
}
private void writeUpdateInternal(final Object objectToSave, final Update update, CassandraPersistentEntity<?> entity) {
final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(objectToSave,
conversionService);
// Write the properties
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
if (propertyObj != null) {
if (prop.isIdProperty()) {
update.where(QueryBuilder.eq(prop.getColumnName(), propertyObj));
} else {
update.with(QueryBuilder.set(prop.getColumnName(), propertyObj));
}
}
}
});
}
private void writeDeleteWhereInternal(final Object objectToSave, final Where whereId,
CassandraPersistentEntity<?> entity) {
final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(objectToSave,
conversionService);
// Write the properties
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
if (prop.isIdProperty()) {
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
if (propertyObj != null) {
whereId.and(QueryBuilder.eq(prop.getColumnName(), propertyObj));
}
}
}
});
}
@SuppressWarnings("unchecked")
private <T> Class<T> transformClassToBeanClassLoaderClass(Class<T> entity) {
try {
return (Class<T>) ClassUtils.forName(entity.getName(), beanClassLoader);
} catch (ClassNotFoundException e) {
return entity;
} catch (LinkageError e) {
return entity;
}
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
}

View File

@@ -1,83 +0,0 @@
/*
* Copyright 2012 the original author or authors.
*
* 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 org.springframework.data.cassandra.convert;
import java.nio.ByteBuffer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.Row;
/**
* {@link PropertyAccessor} to read values from a {@link Row}.
*
* @author Alex Shvid
*/
enum RowReaderPropertyAccessor implements PropertyAccessor {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.expression.PropertyAccessor#getSpecificTargetClasses()
*/
public Class<?>[] getSpecificTargetClasses() {
return new Class<?>[] { Row.class };
}
/*
* (non-Javadoc)
* @see org.springframework.expression.PropertyAccessor#canRead(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.String)
*/
public boolean canRead(EvaluationContext context, Object target, String name) {
return ((Row) target).getColumnDefinitions().contains(name);
}
/*
* (non-Javadoc)
* @see org.springframework.expression.PropertyAccessor#read(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.String)
*/
public TypedValue read(EvaluationContext context, Object target, String name) {
Row row = (Row) target;
if (row.isNull(name)) {
return TypedValue.NULL;
}
DataType columnType = row.getColumnDefinitions().getType(name);
ByteBuffer bytes = row.getBytes(name);
Object object = columnType.deserialize(bytes);
return new TypedValue(object);
}
/*
* (non-Javadoc)
* @see org.springframework.expression.PropertyAccessor#canWrite(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.String)
*/
public boolean canWrite(EvaluationContext context, Object target, String name) {
return false;
}
/*
* (non-Javadoc)
* @see org.springframework.expression.PropertyAccessor#write(org.springframework.expression.EvaluationContext, java.lang.Object, java.lang.String, java.lang.Object)
*/
public void write(EvaluationContext context, Object target, String name, Object newValue) {
throw new UnsupportedOperationException();
}
}

View File

@@ -1,79 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.data.cassandra.core;
import java.util.Map;
import com.datastax.driver.core.TableMetadata;
/**
* Operations for managing a Cassandra keyspace.
*
* @author David Webb
* @author Matthew T. Adams
*/
public interface CassandraAdminOperations {
/**
* Get the given table's metadata.
*
* @param tableName The name of the table.
*/
TableMetadata getTableMetadata(String tableName);
/**
* Create a table with the name given and fields corresponding to the given class. If the table already exists and
* parameter <code>ifNotExists</code> is {@literal true}, this is a no-op and {@literal false} is returned. If the
* table doesn't exist, parameter <code>ifNotExists</code> is ignored, the table is created and {@literal true} is
* returned.
*
* @param ifNotExists If true, will only create the table if it doesn't exist, else the create operation will be
* ignored and the method will return {@literal false}.
* @param tableName The name of the table.
* @param entityClass The class whose fields determine the columns created.
* @param optionsByName Table options, given by the string option name and the appropriate option value.
* @return Returns true if a table was created, false if not.
*/
boolean createTable(boolean ifNotExists, String tableName, Class<?> entityClass, Map<String, Object> optionsByName);
/**
* Add columns to the given table from the given class. If parameter dropRemovedAttributColumns is true, then this
* effectively becomes a synchronization operation between the class's fields and the existing table's columns.
*
* @param tableName The name of the existing table.
* @param entityClass The class whose fields determine the columns added.
* @param dropRemovedAttributeColumns Whether to drop columns that exist on the table but that don't have
* corresponding fields in the class. If true, this effectively becomes a synchronziation operation.
*/
void alterTable(String tableName, Class<?> entityClass, boolean dropRemovedAttributeColumns);
/**
* Drops the existing table with the given name and creates a new one; basically a {@link #dropTable(String)} followed
* by a {@link #createTable(boolean, String, Class, Map)}.
*
* @param tableName The name of the table.
* @param entityClass The class whose fields determine the new table's columns.
* @param optionsByName Table options, given by the string option name and the appropriate option value.
*/
void replaceTable(String tableName, Class<?> entityClass, Map<String, Object> optionsByName);
/**
* Drops the named table.
*
* @param tableName The name of the table.
*/
void dropTable(String tableName);
}

View File

@@ -1,243 +0,0 @@
package org.springframework.data.cassandra.core;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cassandra.core.SessionCallback;
import org.springframework.cassandra.support.CassandraExceptionTranslator;
import org.springframework.cassandra.support.exception.CassandraTableExistsException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.util.CqlUtils;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.Assert;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.TableMetadata;
/**
* Default implementation of {@link CassandraAdminOperations}.
*/
public class CassandraAdminTemplate implements CassandraAdminOperations {
private static Logger log = LoggerFactory.getLogger(CassandraAdminTemplate.class);
private Keyspace keyspace;
private Session session;
private CassandraConverter converter;
private MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext;
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
/**
* Constructor used for a basic template configuration
*
* @param keyspace must not be {@literal null}.
*/
public CassandraAdminTemplate(Keyspace keyspace) {
setKeyspace(keyspace);
}
protected CassandraAdminTemplate setKeyspace(Keyspace keyspace) {
Assert.notNull(keyspace);
this.keyspace = keyspace;
return setSession(keyspace.getSession()).setCassandraConverter(keyspace.getCassandraConverter());
}
protected CassandraAdminTemplate setSession(Session session) {
Assert.notNull(session);
return this;
}
protected CassandraAdminTemplate setCassandraConverter(CassandraConverter converter) {
Assert.notNull(converter);
this.converter = converter;
return setMappingContext(converter.getMappingContext());
}
protected CassandraAdminTemplate setMappingContext(
MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext) {
Assert.notNull(mappingContext);
return this;
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraAdminOperations#createTable(boolean, java.lang.String, java.lang.Class, java.util.Map)
*/
@Override
public boolean createTable(boolean ifNotExists, final String tableName, Class<?> entityClass,
Map<String, Object> optionsByName) {
try {
final CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
execute(new SessionCallback<Object>() {
public Object doInSession(Session s) throws DataAccessException {
String cql = CqlUtils.createTable(tableName, entity);
log.info("CREATE TABLE CQL -> " + cql);
s.execute(cql);
return null;
}
});
return true;
} catch (CassandraTableExistsException ctex) {
return !ifNotExists;
} catch (RuntimeException x) {
throw tryToConvert(x);
}
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraAdminOperations#alterTable(java.lang.String, java.lang.Class, boolean)
*/
@Override
public void alterTable(String tableName, Class<?> entityClass, boolean dropRemovedAttributeColumns) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraAdminOperations#replaceTable(java.lang.String, java.lang.Class)
*/
@Override
public void replaceTable(String tableName, Class<?> entityClass, Map<String, Object> optionsByName) {
// TODO
}
/**
* Create a list of query operations to alter the table for the given entity
*
* @param entityClass
* @param tableName
*/
protected void doAlterTable(Class<?> entityClass, String tableName) {
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
Assert.notNull(entity);
final TableMetadata tableMetadata = getTableMetadata(tableName);
final List<String> queryList = CqlUtils.alterTable(tableName, entity, tableMetadata);
execute(new SessionCallback<Object>() {
public Object doInSession(Session s) throws DataAccessException {
for (String q : queryList) {
log.info(q);
s.execute(q);
}
return null;
}
});
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraOperations#dropTable(java.lang.Class)
*/
public void dropTable(Class<?> entityClass) {
final String tableName = determineTableName(entityClass);
dropTable(tableName);
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraOperations#dropTable(java.lang.String)
*/
@Override
public void dropTable(String tableName) {
log.info("Dropping table => " + tableName);
final String q = CqlUtils.dropTable(tableName);
log.info(q);
execute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(q);
}
});
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.CassandraOperations#getTableMetadata(java.lang.Class)
*/
@Override
public TableMetadata getTableMetadata(final String tableName) {
Assert.notNull(tableName);
return execute(new SessionCallback<TableMetadata>() {
public TableMetadata doInSession(Session s) throws DataAccessException {
log.info("Keyspace => " + keyspace.getKeyspace());
return s.getCluster().getMetadata().getKeyspace(keyspace.getKeyspace()).getTable(tableName);
}
});
}
/**
* Execute a command at the Session Level
*
* @param callback
* @return
*/
protected <T> T execute(SessionCallback<T> callback) {
Assert.notNull(callback);
try {
return callback.doInSession(session);
} catch (RuntimeException x) {
throw tryToConvert(x);
}
}
protected RuntimeException tryToConvert(RuntimeException x) {
RuntimeException resolved = exceptionTranslator.translateExceptionIfPossible(x);
return resolved == null ? x : resolved;
}
/**
* @param entityClass
* @return
*/
public String determineTableName(Class<?> entityClass) {
if (entityClass == null) {
throw new InvalidDataAccessApiUsageException(
"No class parameter provided, entity table name can't be determined!");
}
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityClass);
if (entity == null) {
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class "
+ entityClass.getName());
}
return entity.getTable();
}
}

View File

@@ -1,263 +0,0 @@
/*
* Copyright 2011-2013 the original author or authors.
*
* 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 org.springframework.data.cassandra.core;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cassandra.support.CassandraExceptionTranslator;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.cassandra.config.CompressionType;
import org.springframework.data.cassandra.config.PoolingOptionsConfig;
import org.springframework.data.cassandra.config.SocketOptionsConfig;
import org.springframework.util.StringUtils;
import com.datastax.driver.core.AuthProvider;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.HostDistance;
import com.datastax.driver.core.PoolingOptions;
import com.datastax.driver.core.ProtocolOptions.Compression;
import com.datastax.driver.core.SocketOptions;
import com.datastax.driver.core.policies.LoadBalancingPolicy;
import com.datastax.driver.core.policies.ReconnectionPolicy;
import com.datastax.driver.core.policies.RetryPolicy;
/**
* Convenient factory for configuring a Cassandra Cluster.
*
* @author Alex Shvid
*/
public class CassandraClusterFactoryBean implements FactoryBean<Cluster>, InitializingBean, DisposableBean,
PersistenceExceptionTranslator {
private static final int DEFAULT_PORT = 9042;
private Cluster cluster;
private String contactPoints;
private int port = DEFAULT_PORT;
private CompressionType compressionType;
private PoolingOptionsConfig localPoolingOptions;
private PoolingOptionsConfig remotePoolingOptions;
private SocketOptionsConfig socketOptions;
private AuthProvider authProvider;
private LoadBalancingPolicy loadBalancingPolicy;
private ReconnectionPolicy reconnectionPolicy;
private RetryPolicy retryPolicy;
private boolean metricsEnabled = true;
private final PersistenceExceptionTranslator exceptionTranslator = new CassandraExceptionTranslator();
public Cluster getObject() throws Exception {
return cluster;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
public Class<? extends Cluster> getObjectType() {
return Cluster.class;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
*/
public boolean isSingleton() {
return true;
}
/*
* (non-Javadoc)
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
*/
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
return exceptionTranslator.translateExceptionIfPossible(ex);
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
if (!StringUtils.hasText(contactPoints)) {
throw new IllegalArgumentException("at least one server is required");
}
Cluster.Builder builder = Cluster.builder();
builder.addContactPoints(StringUtils.commaDelimitedListToStringArray(contactPoints)).withPort(port);
if (compressionType != null) {
builder.withCompression(convertCompressionType(compressionType));
}
if (localPoolingOptions != null) {
builder.withPoolingOptions(configPoolingOptions(HostDistance.LOCAL, localPoolingOptions));
}
if (remotePoolingOptions != null) {
builder.withPoolingOptions(configPoolingOptions(HostDistance.REMOTE, remotePoolingOptions));
}
if (socketOptions != null) {
builder.withSocketOptions(configSocketOptions(socketOptions));
}
if (authProvider != null) {
builder.withAuthProvider(authProvider);
}
if (loadBalancingPolicy != null) {
builder.withLoadBalancingPolicy(loadBalancingPolicy);
}
if (reconnectionPolicy != null) {
builder.withReconnectionPolicy(reconnectionPolicy);
}
if (retryPolicy != null) {
builder.withRetryPolicy(retryPolicy);
}
if (!metricsEnabled) {
builder.withoutMetrics();
}
Cluster cluster = builder.build();
// initialize property
this.cluster = cluster;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.DisposableBean#destroy()
*/
public void destroy() throws Exception {
this.cluster.shutdown();
}
public void setContactPoints(String contactPoints) {
this.contactPoints = contactPoints;
}
public void setPort(int port) {
this.port = port;
}
public void setCompressionType(CompressionType compressionType) {
this.compressionType = compressionType;
}
public void setLocalPoolingOptions(PoolingOptionsConfig localPoolingOptions) {
this.localPoolingOptions = localPoolingOptions;
}
public void setRemotePoolingOptions(PoolingOptionsConfig remotePoolingOptions) {
this.remotePoolingOptions = remotePoolingOptions;
}
public void setSocketOptions(SocketOptionsConfig socketOptions) {
this.socketOptions = socketOptions;
}
public void setAuthProvider(AuthProvider authProvider) {
this.authProvider = authProvider;
}
public void setLoadBalancingPolicy(LoadBalancingPolicy loadBalancingPolicy) {
this.loadBalancingPolicy = loadBalancingPolicy;
}
public void setReconnectionPolicy(ReconnectionPolicy reconnectionPolicy) {
this.reconnectionPolicy = reconnectionPolicy;
}
public void setRetryPolicy(RetryPolicy retryPolicy) {
this.retryPolicy = retryPolicy;
}
public void setMetricsEnabled(boolean metricsEnabled) {
this.metricsEnabled = metricsEnabled;
}
private static Compression convertCompressionType(CompressionType type) {
switch (type) {
case NONE:
return Compression.NONE;
case SNAPPY:
return Compression.SNAPPY;
}
throw new IllegalArgumentException("unknown compression type " + type);
}
private static PoolingOptions configPoolingOptions(HostDistance hostDistance, PoolingOptionsConfig config) {
PoolingOptions poolingOptions = new PoolingOptions();
if (config.getMinSimultaneousRequests() != null) {
poolingOptions
.setMinSimultaneousRequestsPerConnectionThreshold(hostDistance, config.getMinSimultaneousRequests());
}
if (config.getMaxSimultaneousRequests() != null) {
poolingOptions
.setMaxSimultaneousRequestsPerConnectionThreshold(hostDistance, config.getMaxSimultaneousRequests());
}
if (config.getCoreConnections() != null) {
poolingOptions.setCoreConnectionsPerHost(hostDistance, config.getCoreConnections());
}
if (config.getMaxConnections() != null) {
poolingOptions.setMaxConnectionsPerHost(hostDistance, config.getMaxConnections());
}
return poolingOptions;
}
private static SocketOptions configSocketOptions(SocketOptionsConfig config) {
SocketOptions socketOptions = new SocketOptions();
if (config.getConnectTimeoutMls() != null) {
socketOptions.setConnectTimeoutMillis(config.getConnectTimeoutMls());
}
if (config.getKeepAlive() != null) {
socketOptions.setKeepAlive(config.getKeepAlive());
}
if (config.getReuseAddress() != null) {
socketOptions.setReuseAddress(config.getReuseAddress());
}
if (config.getSoLinger() != null) {
socketOptions.setSoLinger(config.getSoLinger());
}
if (config.getTcpNoDelay() != null) {
socketOptions.setTcpNoDelay(config.getTcpNoDelay());
}
if (config.getReceiveBufferSize() != null) {
socketOptions.setReceiveBufferSize(config.getReceiveBufferSize());
}
if (config.getSendBufferSize() != null) {
socketOptions.setSendBufferSize(config.getSendBufferSize());
}
return socketOptions;
}
}

Some files were not shown because too many files have changed in this diff Show More