diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/xml/CassandraMappingContextParser.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/xml/CassandraMappingContextParser.java index da02d2673..7bae9ee0a 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/xml/CassandraMappingContextParser.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/config/xml/CassandraMappingContextParser.java @@ -15,7 +15,9 @@ */ package org.springframework.data.cassandra.config.xml; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import org.springframework.beans.factory.BeanDefinitionStoreException; @@ -27,6 +29,7 @@ import org.springframework.data.cassandra.config.DefaultDataBeanNames; import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext; import org.springframework.data.cassandra.mapping.EntityMapping; import org.springframework.data.cassandra.mapping.Mapping; +import org.springframework.data.cassandra.mapping.PropertyMapping; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; @@ -85,23 +88,56 @@ public class CassandraMappingContextParser extends AbstractSingleBeanDefinitionP throw new IllegalStateException("class attribute must not be empty"); } + String tableName = ""; + String forceQuote = ""; Element table = DomUtils.getChildElementByTagName(entity, "table"); - if (table == null) { - return null; - } + if (table != null) { + tableName = table.getAttribute("name"); + if (!StringUtils.hasText(tableName)) { + tableName = ""; + } - String tableName = table.getAttribute("name"); - if (!StringUtils.hasText(tableName)) { - tableName = ""; - } - - String forceQuote = table.getAttribute("force-quote"); - if (!StringUtils.hasText(forceQuote)) { - forceQuote = Boolean.FALSE.toString(); + forceQuote = table.getAttribute("force-quote"); + if (!StringUtils.hasText(forceQuote)) { + forceQuote = Boolean.FALSE.toString(); + } } // TODO: parse future entity mappings here, like table options - return new EntityMapping(className, tableName, forceQuote); + Map propertyMappings = parsePropertyMappings(entity); + + EntityMapping entityMapping = new EntityMapping(className, tableName, forceQuote); + entityMapping.setPropertyMappings(propertyMappings); + + return entityMapping; + } + + protected Map parsePropertyMappings(Element entity) { + + Map pms = new HashMap(); + + for (Element property : DomUtils.getChildElementsByTagName(entity, "property")) { + + String value = property.getAttribute("name"); + if (!StringUtils.hasText(value)) { + throw new IllegalStateException("name attribute must not be empty"); + } + PropertyMapping pm = new PropertyMapping(value); + + value = property.getAttribute("column-name"); + if (StringUtils.hasText(value)) { + pm.setColumnName(value); + } + + value = property.getAttribute("force-quote"); + if (StringUtils.hasText(value)) { + pm.setForceQuote(value); + } + + pms.put(pm.getPropertyName(), pm); + } + + return pms; } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/BasicCassandraPersistentProperty.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/BasicCassandraPersistentProperty.java index f65bf7e9f..8ccde6be6 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/BasicCassandraPersistentProperty.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/BasicCassandraPersistentProperty.java @@ -20,6 +20,8 @@ import static org.springframework.cassandra.core.cql.CqlIdentifier.cqlId; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -54,6 +56,18 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP protected ApplicationContext context; protected StandardEvaluationContext spelContext; + /** + * An unmodifiable list of this property's column names. + */ + protected List columnNames; + /** + * An unmodifiable list of this property's explicitly set column names. + */ + protected List explicitColumnNames; + /** + * Whether this property has been explicitly instructed to force quote column names. + */ + protected Boolean forceQuote; /** * Creates a new {@link BasicCassandraPersistentProperty}. @@ -258,6 +272,10 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP @Override public List getColumnNames() { + if (this.columnNames != null) { + return columnNames; + } + List columnNames = new ArrayList(); if (isCompositePrimaryKey()) { // then the id type has @PrimaryKeyClass @@ -292,7 +310,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP } columnNames.add(createColumnName(defaultName, overriddenName, forceQuote)); - return columnNames; + return this.columnNames = Collections.unmodifiableList(columnNames); } protected CqlIdentifier createColumnName(String defaultName, String overriddenName, boolean forceQuote) { @@ -322,6 +340,48 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP }); } + @Override + public void setColumnName(CqlIdentifier columnName) { + + Assert.notNull(columnName); + setColumnNames(Arrays.asList(new CqlIdentifier[] { columnName })); + } + + @Override + public void setColumnNames(List columnNames) { + + Assert.notNull(columnNames); + if (this.columnNames == null) { + getColumnNames(); + } + if (this.columnNames.size() != columnNames.size()) { + throw new IllegalStateException(String.format( + "property [%s] on entity [%s] is mapped to [%s] column%s, but given column name list has size [%s]", + getName(), getOwner().getType().getName(), this.columnNames.size(), this.columnNames.size() == 1 ? "" : "s", + columnNames.size())); + } + + this.columnNames = this.explicitColumnNames = Collections + .unmodifiableList(new ArrayList(columnNames)); + } + + @Override + public void setForceQuote(boolean forceQuote) { + + if (this.forceQuote != null && this.forceQuote == forceQuote) { + return; + } else { + this.forceQuote = forceQuote; + } + + List columnNames = new ArrayList(this.columnNames == null ? 0 + : this.columnNames.size()); + for (CqlIdentifier columnName : getColumnNames()) { + columnNames.add(cqlId(columnName.getUnquoted(), forceQuote)); + } + this.columnNames = Collections.unmodifiableList(columnNames); + } + @Override public List getCompositePrimaryKeyProperties() { diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/CassandraPersistentProperty.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/CassandraPersistentProperty.java index 3e6dae79d..2630c8f80 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/CassandraPersistentProperty.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/CassandraPersistentProperty.java @@ -106,4 +106,29 @@ public interface CassandraPersistentProperty extends PersistentProperty getOwner(); + + /** + * Whether to force-quote the column names of this property. + * + * @param forceQuote + * @see CassandraPersistentProperty#getColumnNames() + */ + void setForceQuote(boolean forceQuote); + + /** + * If this property is mapped with a single column, set the column name to the given {@link CqlIdentifier}. If this + * property is not mapped by a single column, throws {@link IllegalStateException}. If the given column name is null, + * {@link IllegalArgumentException} is thrown. + * + * @param columnName + */ + void setColumnName(CqlIdentifier columnName); + + /** + * Sets this property's column names to the collection given. The given collection must have the same size as this + * property's current list of column names, and must contain no null elements. + * + * @param columnName + */ + void setColumnNames(List columnNames); } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/DefaultCassandraMappingContext.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/DefaultCassandraMappingContext.java index 4c80ece24..15f60b76c 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/DefaultCassandraMappingContext.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/DefaultCassandraMappingContext.java @@ -238,14 +238,43 @@ public class DefaultCassandraMappingContext extends } String tableName = entityMapping.getTableName(); - if (!StringUtils.hasText(tableName)) { - continue; + if (StringUtils.hasText(tableName)) { + entity.setTableName(cqlId(tableName, Boolean.valueOf(entityMapping.getForceQuote()))); } - entity.setTableName(cqlId(tableName, Boolean.valueOf(entityMapping.getForceQuote()))); + processMappingOverrides(entity, entityMapping); } } + protected void processMappingOverrides(CassandraPersistentEntity entity, EntityMapping entityMapping) { + + for (PropertyMapping mapping : entityMapping.getPropertyMappings().values()) { + processMappingOverride(entity, mapping); + } + } + + protected void processMappingOverride(CassandraPersistentEntity entity, PropertyMapping mapping) { + + CassandraPersistentProperty property = entity.getPersistentProperty(mapping.getPropertyName()); + if (property == null) { + throw new IllegalArgumentException(String.format("entity class [%s] has no persistent property named [%s]", + entity.getType().getName(), mapping.getPropertyName())); + } + + boolean forceQuote = false; + String value = mapping.getForceQuote(); + if (StringUtils.hasText(value)) { + property.setForceQuote(forceQuote = Boolean.valueOf(value)); + } + + value = mapping.getColumnName(); + + if (StringUtils.hasText(value)) { + property.setColumnName(cqlId(value, forceQuote)); + } + + } + public void setBeanClassLoader(ClassLoader beanClassLoader) { this.beanClassLoader = beanClassLoader; } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/EntityMapping.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/EntityMapping.java index 4c6705874..af1d6b073 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/EntityMapping.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/EntityMapping.java @@ -15,6 +15,7 @@ */ package org.springframework.data.cassandra.mapping; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -110,4 +111,13 @@ public class EntityMapping { public int hashCode() { return entityClassName.hashCode() ^ forceQuote.hashCode() ^ tableName.hashCode(); } + + public void setPropertyMappings(Map propertyMappings) { + propertyMappings = propertyMappings == null ? new HashMap() : propertyMappings; + this.propertyMappings = new HashMap(propertyMappings); + } + + public Map getPropertyMappings() { + return Collections.unmodifiableMap(propertyMappings); + } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/PropertyMapping.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/PropertyMapping.java index f82ca9e87..54864014d 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/PropertyMapping.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/mapping/PropertyMapping.java @@ -29,13 +29,17 @@ public class PropertyMapping { protected String propertyName; protected String columnName; - protected boolean forceQuote; + protected String forceQuote; - public PropertyMapping(String propertyName, String columnName) { - this(propertyName, columnName, false); + public PropertyMapping(String propertyName) { + setPropertyName(propertyName); } - public PropertyMapping(String propertyName, String columnName, boolean forceQuote) { + public PropertyMapping(String propertyName, String columnName) { + this(propertyName, columnName, "false"); + } + + public PropertyMapping(String propertyName, String columnName, String forceQuote) { setPropertyName(propertyName); setColumnName(columnName); @@ -60,11 +64,11 @@ public class PropertyMapping { this.columnName = columnName; } - public boolean getForceQuote() { + public String getForceQuote() { return forceQuote; } - public void setForceQuote(boolean forceQuote) { + public void setForceQuote(String forceQuote) { this.forceQuote = forceQuote; } @@ -95,7 +99,15 @@ public class PropertyMapping { if (other.columnName != null) { return false; } - } else if (!(forceQuote ? quotedCqlId(this.columnName) : cqlId(this.columnName)).equals(other.columnName)) { + } else if (!this.columnName.equals(other.columnName)) { + return false; + } + + if (this.forceQuote == null) { + if (other.forceQuote != null) { + return false; + } + } else if (this.forceQuote.equals(other.forceQuote)) { return false; } @@ -105,9 +117,9 @@ public class PropertyMapping { @Override public int hashCode() { int hashCode = 37; - hashCode ^= (propertyName == null ? 0 : propertyName.hashCode()); - hashCode ^= (columnName == null ? 0 : (forceQuote ? quotedCqlId(this.columnName) : cqlId(this.columnName)) - .hashCode()); + hashCode ^= propertyName == null ? 0 : propertyName.hashCode(); + hashCode ^= columnName == null ? 0 : columnName.hashCode(); + hashCode ^= forceQuote == null ? 0 : forceQuote.hashCode(); return hashCode; } } diff --git a/spring-data-cassandra/src/main/resources/org/springframework/data/cassandra/config/spring-cassandra-1.0.xsd b/spring-data-cassandra/src/main/resources/org/springframework/data/cassandra/config/spring-cassandra-1.0.xsd index 697b80100..37c645fd2 100644 --- a/spring-data-cassandra/src/main/resources/org/springframework/data/cassandra/config/spring-cassandra-1.0.xsd +++ b/spring-data-cassandra/src/main/resources/org/springframework/data/cassandra/config/spring-cassandra-1.0.xsd @@ -632,6 +632,8 @@ The replication factor for the data center. + @@ -650,7 +652,7 @@ Table name override. ]]> - + + + + + + + diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/Explicit.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/Explicit.java index 62c1f961c..de2337a6b 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/Explicit.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/Explicit.java @@ -11,21 +11,27 @@ public class Explicit { public static final String TABLE_NAME = "Xx"; @PrimaryKey - String key; + String primaryKey; + + String stringValue = UUID.randomUUID().toString(); public Explicit() { this(UUID.randomUUID().toString()); } - public Explicit(String key) { - setKey(key); + public Explicit(String primaryKey) { + setPrimaryKey(primaryKey); } - public String getKey() { - return key; + public String getPrimaryKey() { + return primaryKey; } - public void setKey(String key) { - this.key = key; + public void setPrimaryKey(String primaryKey) { + this.primaryKey = primaryKey; + } + + public String getStringValue() { + return stringValue; } } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ExplicitProperties.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ExplicitProperties.java new file mode 100644 index 000000000..632739b1e --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ExplicitProperties.java @@ -0,0 +1,44 @@ +package org.springframework.data.cassandra.test.integration.forcequote.config; + +import java.util.UUID; + +import org.springframework.data.cassandra.mapping.Column; +import org.springframework.data.cassandra.mapping.PrimaryKey; +import org.springframework.data.cassandra.mapping.Table; + +@Table +public class ExplicitProperties { + + public static final String EXPLICIT_PRIMARY_KEY = "ThePrimaryKey"; + public static final String EXPLICIT_STRING_VALUE = "TheStringValue"; + + @PrimaryKey(forceQuote = true, value = EXPLICIT_PRIMARY_KEY) + String primaryKey; + + @Column(forceQuote = true, value = EXPLICIT_STRING_VALUE) + String stringValue = UUID.randomUUID().toString(); + + public ExplicitProperties() { + this(UUID.randomUUID().toString()); + } + + public ExplicitProperties(String primaryKey) { + setPrimaryKey(primaryKey); + } + + public String getPrimaryKey() { + return primaryKey; + } + + public void setPrimaryKey(String primaryKey) { + this.primaryKey = primaryKey; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringy) { + this.stringValue = stringy; + } +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ExplicitPropertiesRepository.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ExplicitPropertiesRepository.java new file mode 100644 index 000000000..bf604f4b4 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ExplicitPropertiesRepository.java @@ -0,0 +1,6 @@ +package org.springframework.data.cassandra.test.integration.forcequote.config; + +import org.springframework.data.cassandra.repository.CassandraRepository; + +public interface ExplicitPropertiesRepository extends CassandraRepository { +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryIntegrationTests.java index 4dd20e4c6..234623135 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryIntegrationTests.java @@ -1,5 +1,6 @@ package org.springframework.data.cassandra.test.integration.forcequote.config; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; @@ -8,51 +9,91 @@ import org.springframework.data.cassandra.core.CassandraTemplate; public class ForceQuotedRepositoryIntegrationTests { - ImplicitRepository implicits; - ExplicitRepository explicits; - CassandraTemplate template; - - public ForceQuotedRepositoryIntegrationTests() { - } - - public ForceQuotedRepositoryIntegrationTests(ImplicitRepository implicits, ExplicitRepository explicits, - CassandraTemplate template) { - this.implicits = implicits; - this.explicits = explicits; - this.template = template; - } + ImplicitRepository i; + ImplicitPropertiesRepository ip; + ExplicitRepository e; + ExplicitPropertiesRepository ep; + CassandraTemplate t; public void before() { - template.deleteAll(Implicit.class); + t.deleteAll(Implicit.class); + } + + public String query(String columnName, String tableName, String keyColumnName, String key) { + return t.queryForObject( + String.format("select %s from %s where %s = '%s'", columnName, tableName, keyColumnName, key), String.class); } public void testImplicit() { Implicit entity = new Implicit(); - String key = entity.getKey(); + String key = entity.getPrimaryKey(); - Implicit si = implicits.save(entity); - assertSame(si, entity); + Implicit s = i.save(entity); + assertSame(s, entity); - Implicit fi = implicits.findOne(key); - assertNotSame(fi, entity); + Implicit f = i.findOne(key); + assertNotSame(f, entity); - implicits.delete(key); + String stringValue = query("stringvalue", "\"Implicit\"", "primarykey", f.getPrimaryKey()); + assertEquals(f.getStringValue(), stringValue); - assertNull(implicits.findOne(key)); + i.delete(key); + + assertNull(i.findOne(key)); } public void testExplicit() { Explicit entity = new Explicit(); - String key = entity.getKey(); + String key = entity.getPrimaryKey(); - Explicit si = explicits.save(entity); - assertSame(si, entity); + Explicit s = e.save(entity); + assertSame(s, entity); - Explicit fi = explicits.findOne(key); - assertNotSame(fi, entity); + Explicit f = e.findOne(key); + assertNotSame(f, entity); - explicits.delete(key); + String stringValue = query("stringvalue", "\"Xx\"", "primarykey", f.getPrimaryKey()); + assertEquals(f.getStringValue(), stringValue); - assertNull(explicits.findOne(key)); + e.delete(key); + + assertNull(e.findOne(key)); + } + + public void testImplicitProperties() { + ImplicitProperties entity = new ImplicitProperties(); + String key = entity.getPrimaryKey(); + + ImplicitProperties s = ip.save(entity); + assertSame(s, entity); + + ImplicitProperties f = ip.findOne(key); + assertNotSame(f, entity); + + String stringValue = query("\"stringValue\"", "implicitproperties", "\"primaryKey\"", f.getPrimaryKey()); + assertEquals(f.getStringValue(), stringValue); + + ip.delete(key); + + assertNull(ip.findOne(key)); + } + + public void testExplicitProperties(String stringValueColumnName, String primaryKeyColumnName) { + ExplicitProperties entity = new ExplicitProperties(); + String key = entity.getPrimaryKey(); + + ExplicitProperties s = ep.save(entity); + assertSame(s, entity); + + ExplicitProperties f = ep.findOne(key); + assertNotSame(f, entity); + + String stringValue = query(String.format("\"%s\"", ExplicitProperties.EXPLICIT_STRING_VALUE), "explicitproperties", + String.format("\"%s\"", ExplicitProperties.EXPLICIT_PRIMARY_KEY), f.getPrimaryKey()); + assertEquals(f.getStringValue(), stringValue); + + ip.delete(key); + + assertNull(ip.findOne(key)); } } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryIntegrationTestsDelegator.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryIntegrationTestsDelegator.java new file mode 100644 index 000000000..1c6ed7d6a --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryIntegrationTestsDelegator.java @@ -0,0 +1,68 @@ +package org.springframework.data.cassandra.test.integration.forcequote.config; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.cassandra.core.CassandraTemplate; +import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +public abstract class ForceQuotedRepositoryIntegrationTestsDelegator extends + AbstractSpringDataEmbeddedCassandraIntegrationTest { + + @Autowired + ImplicitRepository i; + + @Autowired + ImplicitPropertiesRepository ip; + + @Autowired + ExplicitRepository e; + + @Autowired + ExplicitPropertiesRepository ep; + + @Autowired + CassandraTemplate t; + + ForceQuotedRepositoryIntegrationTests tests; + + @Before + public void before() { + tests = new ForceQuotedRepositoryIntegrationTests(); + tests.i = i; + tests.ip = ip; + tests.e = e; + tests.ep = ep; + tests.t = t; + + tests.before(); + } + + @Test + public void testImplicit() { + tests.testImplicit(); + } + + @Test + public void testExplicit() { + tests.testExplicit(); + } + + @Test + public void testImplicitProperties() { + tests.testImplicitProperties(); + } + + /** + * Not a @Test -- used by subclasses! + * + * @see ForceQuotedRepositoryJavaConfigIntegrationTests#testExplicitPropertiesWithJavaValues() + * @see ForceQuotedRepositoryXmlConfigIntegrationTests#testExplicitPropertiesWithXmlValues() + */ + public void testExplicitProperties(String stringValueColumnName, String primaryKeyColumnName) { + tests.testExplicitProperties(stringValueColumnName, primaryKeyColumnName); + } +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryJavaConfigIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryJavaConfigIntegrationTests.java index 13c48298b..5222a6c83 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryJavaConfigIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryJavaConfigIntegrationTests.java @@ -1,50 +1,22 @@ package org.springframework.data.cassandra.test.integration.forcequote.config; -import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import org.springframework.data.cassandra.core.CassandraTemplate; import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories; -import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest; import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration -public class ForceQuotedRepositoryJavaConfigIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest { +public class ForceQuotedRepositoryJavaConfigIntegrationTests extends + ForceQuotedRepositoryIntegrationTestsDelegator { @Configuration @EnableCassandraRepositories(basePackageClasses = ForceQuotedRepositoryIntegrationTests.class) public static class Config extends IntegrationTestConfig { } - @Autowired - ImplicitRepository implicits; - - @Autowired - ExplicitRepository explicits; - - @Autowired - CassandraTemplate template; - - ForceQuotedRepositoryIntegrationTests tests; - - @Before - public void before() { - tests = new ForceQuotedRepositoryIntegrationTests(implicits, explicits, template); - tests.before(); - } - @Test - public void testImplicit() { - tests.testImplicit(); - } - - @Test - public void testExplicit() { - tests.testExplicit(); + public void testExplicitPropertiesWithJavaValues() { + tests.testExplicitProperties(ExplicitProperties.EXPLICIT_STRING_VALUE, ExplicitProperties.EXPLICIT_PRIMARY_KEY); } } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryXmlConfigIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryXmlConfigIntegrationTests.java index c94b40b28..351a59ace 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryXmlConfigIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryXmlConfigIntegrationTests.java @@ -1,42 +1,15 @@ package org.springframework.data.cassandra.test.integration.forcequote.config; -import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.cassandra.core.CassandraTemplate; -import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration -public class ForceQuotedRepositoryXmlConfigIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest { - - @Autowired - ImplicitRepository implicits; - - @Autowired - ExplicitRepository explicits; - - @Autowired - CassandraTemplate template; - - ForceQuotedRepositoryIntegrationTests tests; - - @Before - public void before() { - tests = new ForceQuotedRepositoryIntegrationTests(implicits, explicits, template); - tests.before(); - } +public class ForceQuotedRepositoryXmlConfigIntegrationTests extends ForceQuotedRepositoryIntegrationTestsDelegator { @Test - public void testImplicit() { - tests.testImplicit(); - } - - @Test - public void testExplicit() { - tests.testExplicit(); + public void testExplicitPropertiesWithXmlValues() { + // these values must match the values in + // src/test/resources/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryXmlConfigIntegrationTests-context.xml + tests.testExplicitProperties("XmlStringValue", "XmlPrimaryKey"); } } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/Implicit.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/Implicit.java index 87cd247eb..3f6136fae 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/Implicit.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/Implicit.java @@ -9,21 +9,27 @@ import org.springframework.data.cassandra.mapping.Table; public class Implicit { @PrimaryKey - String key; + String primaryKey; + + String stringValue = UUID.randomUUID().toString(); public Implicit() { this(UUID.randomUUID().toString()); } - public Implicit(String key) { - setKey(key); + public Implicit(String primaryKey) { + setPrimaryKey(primaryKey); } - public String getKey() { - return key; + public String getPrimaryKey() { + return primaryKey; } - public void setKey(String key) { - this.key = key; + public void setPrimaryKey(String primaryKey) { + this.primaryKey = primaryKey; + } + + public String getStringValue() { + return stringValue; } } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ImplicitProperties.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ImplicitProperties.java new file mode 100644 index 000000000..aacef094c --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ImplicitProperties.java @@ -0,0 +1,41 @@ +package org.springframework.data.cassandra.test.integration.forcequote.config; + +import java.util.UUID; + +import org.springframework.data.cassandra.mapping.Column; +import org.springframework.data.cassandra.mapping.PrimaryKey; +import org.springframework.data.cassandra.mapping.Table; + +@Table +public class ImplicitProperties { + + @PrimaryKey(forceQuote = true) + String primaryKey; + + @Column(forceQuote = true) + String stringValue = UUID.randomUUID().toString(); + + public ImplicitProperties() { + this(UUID.randomUUID().toString()); + } + + public ImplicitProperties(String primaryKey) { + setPrimaryKey(primaryKey); + } + + public String getPrimaryKey() { + return primaryKey; + } + + public void setPrimaryKey(String primaryKey) { + this.primaryKey = primaryKey; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringy) { + this.stringValue = stringy; + } +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ImplicitPropertiesRepository.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ImplicitPropertiesRepository.java new file mode 100644 index 000000000..875c897d0 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/config/ImplicitPropertiesRepository.java @@ -0,0 +1,6 @@ +package org.springframework.data.cassandra.test.integration.forcequote.config; + +import org.springframework.data.cassandra.repository.CassandraRepository; + +public interface ImplicitPropertiesRepository extends CassandraRepository { +} diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/simple/ForceQuotedPropertiesSimpleIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/simple/ForceQuotedPropertiesSimpleIntegrationTests.java new file mode 100644 index 000000000..58e4426c5 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/forcequote/simple/ForceQuotedPropertiesSimpleIntegrationTests.java @@ -0,0 +1,214 @@ +package org.springframework.data.cassandra.test.integration.forcequote.simple; + +import static org.junit.Assert.*; +import static org.springframework.cassandra.core.cql.CqlIdentifier.cqlId; +import static org.springframework.cassandra.core.cql.CqlIdentifier.quotedCqlId; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.springframework.cassandra.core.PrimaryKeyType; +import org.springframework.cassandra.core.cql.CqlIdentifier; +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.Column; +import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext; +import org.springframework.data.cassandra.mapping.PrimaryKey; +import org.springframework.data.cassandra.mapping.PrimaryKeyClass; +import org.springframework.data.cassandra.mapping.PrimaryKeyColumn; +import org.springframework.data.cassandra.mapping.Table; + +public class ForceQuotedPropertiesSimpleIntegrationTests { + + CassandraMappingContext context = new DefaultCassandraMappingContext(); + + @Test + public void testImplicit() { + CassandraPersistentEntity entity = context.getPersistentEntity(Implicit.class); + + CassandraPersistentProperty primaryKey = entity.getPersistentProperty("primaryKey"); + CassandraPersistentProperty aString = entity.getPersistentProperty("aString"); + + assertEquals("\"primaryKey\"", primaryKey.getColumnName().toCql()); + assertEquals("\"aString\"", aString.getColumnName().toCql()); + } + + @Table + public static class Implicit { + + @PrimaryKey(forceQuote = true) + String primaryKey; + + @Column(forceQuote = true) + String aString; + } + + @Test + public void testDefault() { + CassandraPersistentEntity entity = context.getPersistentEntity(Default.class); + + CassandraPersistentProperty primaryKey = entity.getPersistentProperty("primaryKey"); + CassandraPersistentProperty aString = entity.getPersistentProperty("aString"); + + assertEquals("primarykey", primaryKey.getColumnName().toCql()); + assertEquals("astring", aString.getColumnName().toCql()); + } + + @Table + public static class Default { + + @PrimaryKey + String primaryKey; + + @Column + String aString; + } + + public static final String EXPLICIT_PRIMARY_KEY_NAME = "ThePrimaryKey"; + public static final String EXPLICIT_COLUMN_NAME = "AnotherColumn"; + + @Test + public void testExplicit() { + CassandraPersistentEntity entity = context.getPersistentEntity(Explicit.class); + + CassandraPersistentProperty primaryKey = entity.getPersistentProperty("primaryKey"); + CassandraPersistentProperty aString = entity.getPersistentProperty("aString"); + + assertEquals("\"" + EXPLICIT_PRIMARY_KEY_NAME + "\"", primaryKey.getColumnName().toCql()); + assertEquals("\"" + EXPLICIT_COLUMN_NAME + "\"", aString.getColumnName().toCql()); + } + + @Table + public static class Explicit { + + @PrimaryKey(value = EXPLICIT_PRIMARY_KEY_NAME, forceQuote = true) + String primaryKey; + + @Column(value = EXPLICIT_COLUMN_NAME, forceQuote = true) + String aString; + } + + @Test + public void testImplicitComposite() { + CassandraPersistentEntity key = context.getPersistentEntity(ImplicitKey.class); + + CassandraPersistentProperty stringZero = key.getPersistentProperty("stringZero"); + CassandraPersistentProperty stringOne = key.getPersistentProperty("stringOne"); + + assertEquals("\"stringZero\"", stringZero.getColumnName().toCql()); + assertEquals("\"stringOne\"", stringOne.getColumnName().toCql()); + + List names = Arrays + .asList(new CqlIdentifier[] { quotedCqlId("stringZero"), quotedCqlId("stringOne") }); + CassandraPersistentEntity entity = context.getPersistentEntity(ImplicitComposite.class); + + assertEquals(names, entity.getPersistentProperty("primaryKey").getColumnNames()); + } + + @PrimaryKeyClass + public static class ImplicitKey implements Serializable { + + private static final long serialVersionUID = -1956747638065267667L; + + @PrimaryKeyColumn(ordinal = 0, forceQuote = true, type = PrimaryKeyType.PARTITIONED) + String stringZero; + + @PrimaryKeyColumn(ordinal = 1, forceQuote = true) + String stringOne; + } + + @Table + public static class ImplicitComposite { + + @PrimaryKey(forceQuote = true) + ImplicitKey primaryKey; + + @Column(forceQuote = true) + String aString; + } + + @Test + public void testDefaultComposite() { + CassandraPersistentEntity key = context.getPersistentEntity(DefaultKey.class); + + CassandraPersistentProperty stringZero = key.getPersistentProperty("stringZero"); + CassandraPersistentProperty stringOne = key.getPersistentProperty("stringOne"); + + assertTrue(stringZero.getColumnName().equals("stringZero")); + assertTrue(stringOne.getColumnName().equals("stringOne")); + assertEquals("stringzero", stringZero.getColumnName().toCql()); + assertEquals("stringone", stringOne.getColumnName().toCql()); + + List names = Arrays.asList(new CqlIdentifier[] { cqlId("stringZero"), cqlId("stringOne") }); + CassandraPersistentEntity entity = context.getPersistentEntity(DefaultComposite.class); + + assertEquals(names, entity.getPersistentProperty("primaryKey").getColumnNames()); + } + + @PrimaryKeyClass + public static class DefaultKey implements Serializable { + + private static final long serialVersionUID = -1956747638065267667L; + + @PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED) + String stringZero; + + @PrimaryKeyColumn(ordinal = 1) + String stringOne; + } + + @Table + public static class DefaultComposite { + + @PrimaryKey + DefaultKey primaryKey; + + @Column + String aString; + } + + public static final String EXPLICIT_KEY_0 = "TheFirstKeyField"; + public static final String EXPLICIT_KEY_1 = "TheSecondKeyField"; + + @Test + public void testExplicitComposite() { + CassandraPersistentEntity key = context.getPersistentEntity(ExplicitKey.class); + + CassandraPersistentProperty stringZero = key.getPersistentProperty("stringZero"); + CassandraPersistentProperty stringOne = key.getPersistentProperty("stringOne"); + + assertEquals("\"" + EXPLICIT_KEY_0 + "\"", stringZero.getColumnName().toCql()); + assertEquals("\"" + EXPLICIT_KEY_1 + "\"", stringOne.getColumnName().toCql()); + + List names = Arrays.asList(new CqlIdentifier[] { quotedCqlId(EXPLICIT_KEY_0), + quotedCqlId(EXPLICIT_KEY_1) }); + CassandraPersistentEntity entity = context.getPersistentEntity(ExplicitComposite.class); + + assertEquals(names, entity.getPersistentProperty("primaryKey").getColumnNames()); + } + + @PrimaryKeyClass + public static class ExplicitKey implements Serializable { + + private static final long serialVersionUID = -1956747638065267667L; + + @PrimaryKeyColumn(ordinal = 0, name = EXPLICIT_KEY_0, forceQuote = true, type = PrimaryKeyType.PARTITIONED) + String stringZero; + + @PrimaryKeyColumn(ordinal = 1, name = EXPLICIT_KEY_1, forceQuote = true) + String stringOne; + } + + @Table + public static class ExplicitComposite { + + @PrimaryKey(forceQuote = true) + ExplicitKey primaryKey; + + @Column(forceQuote = true) + String aString; + } +} \ No newline at end of file diff --git a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryXmlConfigIntegrationTests-context.xml b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryXmlConfigIntegrationTests-context.xml index 4357dea16..78d9a4893 100644 --- a/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryXmlConfigIntegrationTests-context.xml +++ b/spring-data-cassandra/src/test/resources/org/springframework/data/cassandra/test/integration/forcequote/config/ForceQuotedRepositoryXmlConfigIntegrationTests-context.xml @@ -22,6 +22,19 @@ class="org.springframework.data.cassandra.test.integration.forcequote.config.Explicit"> + + + + + + + + +