diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/CqlIdentifier.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/CqlIdentifier.java
index 6f11f5792..3b3b17e97 100644
--- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/CqlIdentifier.java
+++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/CqlIdentifier.java
@@ -1,6 +1,15 @@
package org.springframework.cassandra.core;
+import java.util.regex.Pattern;
+
+import org.springframework.cassandra.core.cql.CqlStringUtils;
+
public class CqlIdentifier {
+ 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 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);
+
private String identifier;
private boolean quoted;
@@ -8,11 +17,29 @@ public class CqlIdentifier {
this(identifier, false);
}
+ /**
+ * Renders the given string as a legal Cassandra identifier.
+ *
+ * - If the given identifier is a legal quoted identifier or forceQuote is true, it is set encased in double quotes.
+ *
+ * - If the given identifier is a legal unquoted identifier, it is set unchanged.
+ * - If the given identifier is illegal, an {@link IllegalArgumentException} is thrown.
+ *
+ */
public CqlIdentifier(String identifier, boolean forceQuoting) {
+ if (isUnquotedIdentifier(identifier) && forceQuoting == false) {
+ this.identifier = identifier;
+ } else if (isQuotedIdentifier(identifier)) {
+ this.identifier = identifier;
+ quoted = true;
+ } else {
+ throw new IllegalArgumentException("[" + identifier + "] is not a valid CQL quoted or unquoted identifier");
+ }
}
public String toCql() {
- return identifier;
+ String id = quoted ? CqlStringUtils.doubleQuote(identifier) : identifier;
+ return id;
}
public StringBuilder toCql(StringBuilder sb) {
@@ -41,4 +68,44 @@ public class CqlIdentifier {
CqlIdentifier id = new CqlIdentifier(identifier, true);
return id;
}
+
+ public static boolean isIdentifier(CharSequence chars) {
+ return isUnquotedIdentifier(chars) || isQuotedIdentifier(chars);
+ }
+
+ public static boolean isUnquotedIdentifier(CharSequence chars) {
+ return UNQUOTED_IDENTIFIER_PATTERN.matcher(chars).matches();
+ }
+
+ public static boolean isQuotedIdentifier(CharSequence chars) {
+ return QUOTED_IDENTIFIER_PATTERN.matcher(chars).matches();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
+ result = prime * result + (quoted ? 1231 : 1237);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CqlIdentifier other = (CqlIdentifier) obj;
+ if (identifier == null) {
+ if (other.identifier != null)
+ return false;
+ } else if (!identifier.equals(other.identifier))
+ return false;
+ if (quoted != other.quoted)
+ return false;
+ return true;
+ }
}
diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/cql/CqlStringUtils.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/cql/CqlStringUtils.java
index 61180cc7f..73d0c70e3 100644
--- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/cql/CqlStringUtils.java
+++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/cql/CqlStringUtils.java
@@ -23,7 +23,7 @@ public class CqlStringUtils {
protected static final String SINGLE_QUOTE = "\'";
protected static final String DOUBLE_SINGLE_QUOTE = "\'\'";
- protected static final String DOUBLE_QUOTE = "\"";
+ public static final String DOUBLE_QUOTE = "\"";
protected static final String DOUBLE_DOUBLE_QUOTE = "\"\"";
protected static final String EMPTY_STRING = "";
protected static final String TYPE_PARAMETER_PREFIX = "<";
@@ -36,61 +36,6 @@ public class CqlStringUtils {
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.
- *
- * - If the given identifier is a legal unquoted identifier, it is returned unchanged.
- * - If the given identifier is a legal quoted identifier, it is returned encased in double quotes.
- * - If the given identifier is illegal, an {@link IllegalArgumentException} is thrown.
- *
- */
- 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 null, returns null.
diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/ColumnChangeSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/ColumnChangeSpecification.java
index 6cea473f8..665a52797 100644
--- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/ColumnChangeSpecification.java
+++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/ColumnChangeSpecification.java
@@ -15,8 +15,7 @@
*/
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 org.springframework.cassandra.core.CqlIdentifier;
/**
* Base class for column change specifications.
@@ -25,22 +24,21 @@ import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize;
*/
public abstract class ColumnChangeSpecification {
- private String name;
+ private CqlIdentifier identifier;
public ColumnChangeSpecification(String name) {
setName(name);
}
private void setName(String name) {
- checkIdentifier(name);
- this.name = name;
+ identifier = new CqlIdentifier(name);
}
public String getName() {
- return name;
+ return identifier.getIdentifier();
}
public String getNameAsIdentifier() {
- return identifize(name);
+ return identifier.toCql();
}
}
diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/ColumnSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/ColumnSpecification.java
index 9c2d0ba03..aa6e491e0 100644
--- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/ColumnSpecification.java
+++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/ColumnSpecification.java
@@ -15,15 +15,14 @@
*/
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.cassandra.core.PrimaryKeyType.PARTITIONED;
-import static org.springframework.cassandra.core.PrimaryKeyType.CLUSTERED;
import static org.springframework.cassandra.core.Ordering.ASCENDING;
+import static org.springframework.cassandra.core.PrimaryKeyType.CLUSTERED;
+import static org.springframework.cassandra.core.PrimaryKeyType.PARTITIONED;
+import static org.springframework.cassandra.core.cql.CqlStringUtils.noNull;
-import org.springframework.cassandra.core.PrimaryKeyType;
+import org.springframework.cassandra.core.CqlIdentifier;
import org.springframework.cassandra.core.Ordering;
+import org.springframework.cassandra.core.PrimaryKeyType;
import com.datastax.driver.core.DataType;
@@ -45,7 +44,7 @@ public class ColumnSpecification {
*/
public static final Ordering DEFAULT_ORDERING = ASCENDING;
- private String name;
+ private CqlIdentifier identifier;
private DataType type; // TODO: determining if we should be coupling this to Datastax Java Driver type?
private PrimaryKeyType keyType;
private Ordering ordering;
@@ -56,8 +55,7 @@ public class ColumnSpecification {
* @return this
*/
public ColumnSpecification name(String name) {
- checkIdentifier(name);
- this.name = name;
+ identifier = new CqlIdentifier(name);
return this;
}
@@ -148,11 +146,11 @@ public class ColumnSpecification {
}
public String getName() {
- return name;
+ return identifier.getIdentifier();
}
public String getNameAsIdentifier() {
- return identifize(name);
+ return identifier.toCql();
}
public DataType getType() {
@@ -172,7 +170,7 @@ public class ColumnSpecification {
}
public StringBuilder toCql(StringBuilder cql) {
- return (cql = noNull(cql)).append(name).append(" ").append(type);
+ return (cql = noNull(cql)).append(identifier).append(" ").append(type);
}
@Override
diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/CreateIndexSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/CreateIndexSpecification.java
index 1f9f89d46..bd782b1f3 100644
--- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/CreateIndexSpecification.java
+++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/CreateIndexSpecification.java
@@ -15,9 +15,7 @@
*/
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 org.springframework.cassandra.core.CqlIdentifier;
import org.springframework.util.StringUtils;
/**
@@ -31,7 +29,7 @@ public class CreateIndexSpecification extends IndexNameSpecification
/**
* The name of the index.
*/
- private String name;
+ private CqlIdentifier identifier;
/**
* Sets the index name.
@@ -38,17 +37,16 @@ public abstract class IndexNameSpecification
*/
@SuppressWarnings("unchecked")
public T name(String name) {
- checkIdentifier(name);
- this.name = name;
+ identifier = new CqlIdentifier(name);
return (T) this;
}
public String getName() {
- return name;
+ return identifier.getIdentifier();
}
public String getNameAsIdentifier() {
- return identifize(name);
+ return identifier.toCql();
}
}
diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceActionSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceActionSpecification.java
index cddc2115d..83c6db79e 100644
--- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceActionSpecification.java
+++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceActionSpecification.java
@@ -1,7 +1,6 @@
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 org.springframework.cassandra.core.CqlIdentifier;
/**
* Abstract builder class to support the construction of keyspace specifications.
@@ -13,9 +12,9 @@ import static org.springframework.cassandra.core.cql.CqlStringUtils.identifize;
public abstract class KeyspaceActionSpecification> {
/**
- * The name of the table.
+ * The name of the keyspace.
*/
- private String name;
+ private CqlIdentifier identifier;
/**
* Sets the keyspace name.
@@ -24,17 +23,16 @@ public abstract class KeyspaceActionSpecification thatSpec = (KeyspaceActionSpecification>) that;
- return this.name.equals(thatSpec.name) && this.getClass().equals(that.getClass());
+ return this.identifier.equals(thatSpec.identifier) && this.getClass().equals(that.getClass());
}
@Override
public int hashCode() {
- return this.name.hashCode() ^ this.getClass().hashCode();
+ return this.identifier.hashCode() ^ this.getClass().hashCode();
}
}
diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/TableNameSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/TableNameSpecification.java
index f99addd15..f66eb8e91 100644
--- a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/TableNameSpecification.java
+++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/TableNameSpecification.java
@@ -15,8 +15,7 @@
*/
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 org.springframework.cassandra.core.CqlIdentifier;
/**
* Abstract builder class to support the construction of table specifications.
@@ -29,7 +28,7 @@ public abstract class TableNameSpecification
/**
* The name of the table.
*/
- private String name;
+ private CqlIdentifier identifier;
/**
* Sets the table name.
@@ -38,16 +37,15 @@ public abstract class TableNameSpecification
*/
@SuppressWarnings("unchecked")
public T name(String name) {
- checkIdentifier(name);
- this.name = name;
+ identifier = new CqlIdentifier(name);
return (T) this;
}
public String getName() {
- return name;
+ return identifier.getIdentifier();
}
public String getNameAsIdentifier() {
- return identifize(name);
+ return identifier.toCql();
}
}
diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/CqlIdentifierTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/CqlIdentifierTest.java
new file mode 100644
index 000000000..8b404ec5e
--- /dev/null
+++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/CqlIdentifierTest.java
@@ -0,0 +1,20 @@
+package org.springframework.cassandra.test.unit.core.cql;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.springframework.cassandra.core.CqlIdentifier.isQuotedIdentifier;
+import static org.springframework.cassandra.core.CqlIdentifier.isUnquotedIdentifier;
+
+import org.junit.Test;
+
+public class CqlIdentifierTest {
+
+ @Test
+ public void testIsQuotedIdentifier() throws Exception {
+ assertFalse(isQuotedIdentifier("my\"id"));
+ assertTrue(isQuotedIdentifier("my\"\"id"));
+ assertFalse(isUnquotedIdentifier("my\"id"));
+ assertTrue(isUnquotedIdentifier("myid"));
+ }
+
+}
diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/CqlStringUtilsTest.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/CqlStringUtilsTest.java
index e54d7b29b..9da6874a5 100644
--- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/CqlStringUtilsTest.java
+++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/CqlStringUtilsTest.java
@@ -1,18 +1,5 @@
package org.springframework.cassandra.test.unit.core.cql;
-import static org.junit.Assert.*;
-import static org.springframework.cassandra.core.cql.CqlStringUtils.isQuotedIdentifier;
-import static org.springframework.cassandra.core.cql.CqlStringUtils.isUnquotedIdentifier;
-
-import org.junit.Test;
public class CqlStringUtilsTest {
-
- @Test
- public void testIsQuotedIdentifier() throws Exception {
- assertFalse(isQuotedIdentifier("my\"id"));
- assertTrue(isQuotedIdentifier("my\"\"id"));
- assertFalse(isUnquotedIdentifier("my\"id"));
- assertTrue(isUnquotedIdentifier("myid"));
- }
}
diff --git a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/AlterTableCqlGeneratorTests.java b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/AlterTableCqlGeneratorTests.java
index e281fdaa7..e1b3fe86e 100644
--- a/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/AlterTableCqlGeneratorTests.java
+++ b/spring-cassandra/src/test/java/org/springframework/cassandra/test/unit/core/cql/generator/AlterTableCqlGeneratorTests.java
@@ -26,6 +26,7 @@ public class AlterTableCqlGeneratorTests {
* Asserts that the preamble is first & correctly formatted in the given CQL string.
*/
public static void assertPreamble(String tableName, String cql) {
+ System.out.println("cql: " + cql);
assertTrue(cql.startsWith("ALTER TABLE " + tableName + " "));
}
diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/BasicCassandraPersistentEntity.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/BasicCassandraPersistentEntity.java
index a1b52dd25..863e8f838 100644
--- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/BasicCassandraPersistentEntity.java
+++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/BasicCassandraPersistentEntity.java
@@ -27,7 +27,6 @@ import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.data.cassandra.util.CassandraNamingUtils;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
-import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.util.TypeInformation;
diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/BasicCassandraPersistentEntityIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/BasicCassandraPersistentEntityIntegrationTests.java
index 306351a00..a59e06da6 100644
--- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/BasicCassandraPersistentEntityIntegrationTests.java
+++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/BasicCassandraPersistentEntityIntegrationTests.java
@@ -19,8 +19,6 @@ import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
-import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
-import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraDataOperationsTest.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraDataOperationsTest.java
index 047545bc8..7b8ca6c36 100644
--- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraDataOperationsTest.java
+++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/template/CassandraDataOperationsTest.java
@@ -16,7 +16,6 @@
package org.springframework.data.cassandra.test.integration.template;
import static org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification.createKeyspace;
-import static org.springframework.cassandra.core.keyspace.DropTableSpecification.dropTable;
import java.io.IOException;
import java.util.ArrayList;
@@ -24,30 +23,22 @@ import java.util.Arrays;
import java.util.List;
import java.util.UUID;
-import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cassandra.core.ConsistencyLevel;
import org.springframework.cassandra.core.QueryOptions;
import org.springframework.cassandra.core.RetryPolicy;
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
import org.springframework.context.annotation.Configuration;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
import org.springframework.data.cassandra.config.SchemaAction;
-import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.test.integration.simpletons.Book;
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.data.cassandra.test.integration.support.TestConfig;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import com.datastax.driver.core.TableMetadata;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;