Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra-parent</artifactId>
<version>3.0.0.BUILD-SNAPSHOT</version>
<version>3.0.0.DATACASS-84-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data for Apache Cassandra</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-cassandra-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra-parent</artifactId>
<version>3.0.0.BUILD-SNAPSHOT</version>
<version>3.0.0.DATACASS-84-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-cassandra/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra-parent</artifactId>
<version>3.0.0.BUILD-SNAPSHOT</version>
<version>3.0.0.DATACASS-84-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,

private CqlIdentifier tableName;

private NamingStrategy namingStrategy = NamingStrategy.INSTANCE;

private @Nullable StandardEvaluationContext spelContext;

/**
Expand Down Expand Up @@ -106,13 +108,13 @@ protected CqlIdentifier determineTableName() {
return determineName(annotation.value(), annotation.forceQuote());
}

return IdentifierFactory.create(getType().getSimpleName(), false);
return IdentifierFactory.create(namingStrategy.getTableName(this), false);
}

CqlIdentifier determineName(String value, boolean forceQuote) {

if (!StringUtils.hasText(value)) {
return IdentifierFactory.create(getType().getSimpleName(), forceQuote);
return IdentifierFactory.create(namingStrategy.getTableName(this), forceQuote);
}

String name = Optional.ofNullable(this.spelContext).map(it -> SpelUtils.evaluate(value, it)).orElse(value);
Expand Down Expand Up @@ -199,6 +201,23 @@ public void setTableName(CqlIdentifier tableName) {
this.tableName = tableName;
}

/**
* Set the {@link NamingStrategy} to use.
*
* @param namingStrategy must not be {@literal null}.
* @since 3.0
*/
public void setNamingStrategy(NamingStrategy namingStrategy) {

Assert.notNull(namingStrategy, "NamingStrategy must not be null");

this.namingStrategy = namingStrategy;
}

NamingStrategy getNamingStrategy() {
return namingStrategy;
}

/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity#getTableName()
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
Expand Down Expand Up @@ -62,6 +64,8 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP

private @Nullable CqlIdentifier columnName;

private NamingStrategy namingStrategy = NamingStrategy.INSTANCE;

private @Nullable StandardEvaluationContext spelContext;

/**
Expand Down Expand Up @@ -180,7 +184,7 @@ private CqlIdentifier determineColumnName() {
return null;
}

String defaultName = getName(); // TODO: replace with naming strategy class
Supplier<String> defaultName = () -> namingStrategy.getColumnName(this);
String overriddenName = null;

boolean forceQuote = false;
Expand Down Expand Up @@ -217,12 +221,15 @@ private CqlIdentifier determineColumnName() {
}

@Nullable
private CqlIdentifier createColumnName(String defaultName, @Nullable String overriddenName, boolean forceQuote) {
private CqlIdentifier createColumnName(Supplier<String> defaultName, @Nullable String overriddenName,
boolean forceQuote) {

String name = defaultName;
String name;

if (StringUtils.hasText(overriddenName)) {
name = this.spelContext != null ? SpelUtils.evaluate(overriddenName, this.spelContext) : overriddenName;
} else {
name = defaultName.get();
}

return name != null ? IdentifierFactory.create(name, forceQuote) : null;
Expand All @@ -239,6 +246,19 @@ public void setColumnName(CqlIdentifier columnName) {
this.columnName = columnName;
}

/**
* Set the {@link NamingStrategy} to use.
*
* @param namingStrategy must not be {@literal null}.
* @since 3.0
*/
public void setNamingStrategy(NamingStrategy namingStrategy) {

Assert.notNull(namingStrategy, "NamingStrategy must not be null");

this.namingStrategy = namingStrategy;
}

/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.mapping.CassandraPersistentProperty#setForceQuote(boolean)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public class CassandraMappingContext

private Mapping mapping = new Mapping();

private NamingStrategy namingStrategy = NamingStrategy.INSTANCE;

private @Deprecated @Nullable UserTypeResolver userTypeResolver;

private @Deprecated CodecRegistry codecRegistry = CodecRegistry.DEFAULT;
Expand Down Expand Up @@ -262,6 +264,19 @@ public CodecRegistry getCodecRegistry() {
return this.codecRegistry;
}

/**
* Set the {@link NamingStrategy} to use.
*
* @param namingStrategy must not be {@literal null}.
* @since 3.0
*/
public void setNamingStrategy(NamingStrategy namingStrategy) {

Assert.notNull(namingStrategy, "NamingStrategy must not be null");

this.namingStrategy = namingStrategy;
}

/**
* Sets the {@link TupleTypeFactory}.
*
Expand Down Expand Up @@ -366,6 +381,7 @@ protected <T> BasicCassandraPersistentEntity<T> createPersistentEntity(TypeInfor
: isTuple(typeInformation) ? new BasicCassandraPersistentTupleEntity<>(typeInformation)
: new BasicCassandraPersistentEntity<>(typeInformation, getVerifier());

entity.setNamingStrategy(this.namingStrategy);
Optional.ofNullable(this.applicationContext).ifPresent(entity::setApplicationContext);

return entity;
Expand All @@ -390,6 +406,7 @@ protected CassandraPersistentProperty createPersistentProperty(Property property
? new BasicCassandraPersistentTupleProperty(property, owner, simpleTypeHolder)
: new BasicCassandraPersistentProperty(property, owner, simpleTypeHolder);

persistentProperty.setNamingStrategy(this.namingStrategy);
Optional.ofNullable(this.applicationContext).ifPresent(persistentProperty::setApplicationContext);

return persistentProperty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ protected CqlIdentifier determineTableName() {
return determineName(annotation.value(), annotation.forceQuote());
}

return super.determineTableName();
return IdentifierFactory.create(getNamingStrategy().getUserDefinedTypeName(this), false);
}

/* (non-Javadoc)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2017-2020 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
*
* https://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.mapping;

import java.util.function.UnaryOperator;

import org.springframework.util.Assert;

/**
* Interface and default implementation of a naming strategy. Defaults to table name based on {@link Class} and column
* name based on property names.
* <p>
* NOTE: Can also be used as an adapter. Create a lambda or an anonymous subclass and override any settings to implement
* a different strategy on the fly.
*
* @author Mark Paluch
* @since 3.0
*/
public interface NamingStrategy {

/**
* Empty implementation of the interface utilizing only the default implementation.
* <p>
* Using this avoids creating essentially the same class over and over again.
*/
NamingStrategy INSTANCE = new NamingStrategy() {};

/**
* Naming strategy that renders CamelCase name parts to {@code snake_case}.
*/
NamingStrategy SNAKE_CASE = new SnakeCaseNamingStrategy();

/**
* Create a table name from the given {@link CassandraPersistentEntity}.
*/
default String getTableName(CassandraPersistentEntity<?> type) {

Assert.notNull(type, "CassandraPersistentEntity must not be null!");

return type.getType().getSimpleName();
}

/**
* Create a user-defined type name from the given {@link CassandraPersistentEntity}.
*/
default String getUserDefinedTypeName(CassandraPersistentEntity<?> type) {

Assert.notNull(type, "CassandraPersistentEntity must not be null!");

return type.getType().getSimpleName();
}

/**
* Create a column name from the given {@link CassandraPersistentProperty property}.
*/
default String getColumnName(CassandraPersistentProperty property) {

Assert.notNull(property, "CassandraPersistentProperty must not be null!");

return property.getName();
}

/**
* Apply a {@link UnaryOperator transformation function} to create a new {@link NamingStrategy} that applies the given
* transformation to each name component. Example:
* <p class="code">
* NamingStrategy lower = NamingStrategy.INSTANCE.transform(String::toLowerCase);
* </p>
*
* @param mappingFunction must not be {@literal null}.
* @return the {@link NamingStrategy} that applies the given {@link UnaryOperator transformation function}.
*/
default NamingStrategy transform(UnaryOperator<String> mappingFunction) {

Assert.notNull(mappingFunction, "Mapping function must not be null!");

NamingStrategy previous = this;

return new TransformingNamingStrategy(previous, mappingFunction);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2020 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
*
* https://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.mapping;

import org.springframework.data.util.ParsingUtils;
import org.springframework.util.Assert;

/**
* Naming strategy that renders CamelCase name parts to {@code snake_case}.
*
* @author Mark Paluch
* @since 3.0
*/
public class SnakeCaseNamingStrategy implements NamingStrategy {

public SnakeCaseNamingStrategy() {}

/**
* Uses {@link Class#getSimpleName()} and separates camel case parts with '_'.
*/
public String getTableName(CassandraPersistentEntity<?> type) {

Assert.notNull(type, "CassandraPersistentEntity must not be null!");

return ParsingUtils.reconcatenateCamelCase(type.getType().getSimpleName(), "_");
}

/**
* Uses {@link Class#getSimpleName()} and separates camel case parts with '_'.
*/
public String getUserDefinedTypeName(CassandraPersistentEntity<?> type) {

Assert.notNull(type, "CassandraPersistentEntity must not be null!");

return ParsingUtils.reconcatenateCamelCase(type.getType().getSimpleName(), "_");
}

/**
* Uses {@link CassandraPersistentProperty#getName()} and separates camel case parts with '_'.
*/
public String getColumnName(CassandraPersistentProperty property) {

Assert.notNull(property, "CassandraPersistentProperty must not be null.");

return ParsingUtils.reconcatenateCamelCase(property.getName(), "_");
}
}
Loading