diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/AlterKeyspaceSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/AlterKeyspaceSpecification.java new file mode 100644 index 000000000..9898d98a2 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/AlterKeyspaceSpecification.java @@ -0,0 +1,5 @@ +package org.springframework.cassandra.core.keyspace; + +public class AlterKeyspaceSpecification extends KeyspaceSpecification { + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/CreateKeyspaceSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/CreateKeyspaceSpecification.java new file mode 100644 index 000000000..08ca26625 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/CreateKeyspaceSpecification.java @@ -0,0 +1,5 @@ +package org.springframework.cassandra.core.keyspace; + +public class CreateKeyspaceSpecification extends KeyspaceSpecification { + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/DropKeyspaceSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/DropKeyspaceSpecification.java new file mode 100644 index 000000000..020b15c9c --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/DropKeyspaceSpecification.java @@ -0,0 +1,5 @@ +package org.springframework.cassandra.core.keyspace; + +public class DropKeyspaceSpecification extends KeyspaceNameSpecification { + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceDescriptor.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceDescriptor.java new file mode 100644 index 000000000..7ab1280a3 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceDescriptor.java @@ -0,0 +1,50 @@ +/* + * 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.keyspace; + +import java.util.Map; + +/** + * Describes a Keyspace. + * + * @author John McPeek + */ +public interface KeyspaceDescriptor { + + /** + * Returns the name of the table. + */ + String getName(); + + /** + * Returns the name of the table as an identifier or quoted identifier as appropriate. + */ + String getNameAsIdentifier(); + + /** + * Returns the replication strategy. + */ + String getReplicationStrategy(); + + Long getReplicationFactor(); + + Map getDataCenters(); + + /** + * Returns an unmodifiable {@link Map} of keyspace options. + */ + Map getOptions(); +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceNameSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceNameSpecification.java new file mode 100644 index 000000000..0bec92437 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceNameSpecification.java @@ -0,0 +1,39 @@ +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 keyspace specifications. + * + * @author John McPeek + * @param The subtype of the {@link KeyspaceNameSpecification} + */ +public abstract class KeyspaceNameSpecification> { + + /** + * The name of the table. + */ + private String name; + + /** + * Sets the keyspace 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); + } + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOption.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOption.java new file mode 100644 index 000000000..c14ddf04f --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOption.java @@ -0,0 +1,77 @@ +package org.springframework.cassandra.core.keyspace; + +public enum KeyspaceOption implements Option { + REPLICATION_STRATEGY("class", String.class, true, true, true), + + REPLICATION_FACTOR("replication_factor", Long.class, false, false, false); + + private Option delegate; + + private KeyspaceOption(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 Replication Strategy options. + * + * @author John McPeek + * + */ + public enum ReplicationStrategy { + SIMPLE_STRATEGY("SimpleStrategy"), NETWORK_TOPOLOGY_STRATEGY("NetworkTopologyStrategy"); + + private String value; + + private ReplicationStrategy(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public String toString() { + return getValue(); + } + } +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOptionsSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOptionsSpecification.java new file mode 100644 index 000000000..650c384a9 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceOptionsSpecification.java @@ -0,0 +1,92 @@ +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 WITH ... AND .... + *

+ * It is important to note that although this class depends on {@link KeyspaceOption} for convenient and typesafe use, it + * ultimately stores its options in a Map for flexibility. This means that + * {@link #with(KeyspaceOption)} and {@link #with(KeyspaceOption, 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 John McPeek + * @param The subtype of the {@link KeyspaceOptionsSpecification}. + */ +public abstract class KeyspaceOptionsSpecification> extends KeyspaceNameSpecification { + + protected Map options = new LinkedHashMap(); + + public T name(String name) { + return (T) super.name(name); + } + + /** + * Convenience method that calls with(option, null). + * + * @return this + */ + public T with(KeyspaceOption 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 KeyspaceOption} 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 KeyspaceOption}. + * @return this + * @see #with(String, Object, boolean, boolean) + */ + public T with(KeyspaceOption option, Object value) { + option.checkValue(value); + return (T) with(option.getName(), value, option.escapesValue(), option.quotesValue()); + } + + /** + * Adds the given option by name to this keyspaces's options. + *

+ * Options that have null 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 escape and may be single-quoted according to parameter quote. + * + * @param name The name of the option + * @param value The value of the option. If null, 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 getOptions() { + return Collections.unmodifiableMap(options); + } + +} diff --git a/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceSpecification.java b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceSpecification.java new file mode 100644 index 000000000..c1b28dfa8 --- /dev/null +++ b/spring-cassandra/src/main/java/org/springframework/cassandra/core/keyspace/KeyspaceSpecification.java @@ -0,0 +1,75 @@ +/* + * 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.keyspace; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + + +/** + * Builder class to support the construction of keyspace specifications that have columns. This class can also be used as a + * standalone {@link KeyspaceDescriptor}, independent of {@link CreateKeyspaceSpecification}. + * + * @author John McPeek + */ +public class KeyspaceSpecification extends KeyspaceOptionsSpecification> implements KeyspaceDescriptor { + + private String replicationStrategy; + + private Long replicationFactor; + + private Map dataCenters = new HashMap(); + + @Override + public String getReplicationStrategy() { + return replicationStrategy; + } + + /** + * @param replicationStrategy the replicationStrategy to set + */ + public void setReplicationStrategy(String replicationStrategy) { + this.replicationStrategy = replicationStrategy; + } + + /** + * @return the replicationFactor + */ + @Override + public Long getReplicationFactor() { + return replicationFactor; + } + + /** + * @param replicationFactor the replicationFactor to set + */ + public void setReplicationFactor(Long replicationFactor) { + this.replicationFactor = replicationFactor; + } + + @Override + public Map getDataCenters() { + return Collections.unmodifiableMap( dataCenters ); + } + + /** + * @param dataCenters the dataCenters to set + */ + public void setDataCenters(Map dataCenters) { + this.dataCenters = dataCenters; + } +}