All Downloads are FREE. Search and download functionalities are using the official Maven repository.

info.archinnov.achilles.table.CQLTableBuilder Maven / Gradle / Ivy

/**
 *
 * Copyright (C) 2012-2013 DuyHai DOAN
 *
 * 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 info.archinnov.achilles.table;

import static com.datastax.driver.core.DataType.Name.*;
import static info.archinnov.achilles.cql.CQLTypeMapper.*;
import static info.archinnov.achilles.table.TableCreator.*;
import static info.archinnov.achilles.table.TableNameNormalizer.*;
import info.archinnov.achilles.validation.Validator;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.cassandra.utils.Pair;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CQLTableBuilder {

	private static final Logger log = LoggerFactory.getLogger(ACHILLES_DDL_SCRIPT);

	private String tableName;
	private String comment;
	private List partitionComponents = new ArrayList();
	private List clusteringComponents = new ArrayList();
	private Map columns = new LinkedHashMap();
	private Map lists = new LinkedHashMap();
	private Map sets = new LinkedHashMap();
	private Map> maps = new LinkedHashMap>();

	private boolean counter;

	public static CQLTableBuilder createTable(String tableName) {
		return new CQLTableBuilder(tableName, false);
	}

	public static CQLTableBuilder createCounterTable(String tableName) {
		return new CQLTableBuilder(tableName, true);
	}

	private CQLTableBuilder(String tableName, boolean counter) {
		this.counter = counter;
		this.tableName = normalizerAndValidateColumnFamilyName(tableName);
	}

	public CQLTableBuilder addColumn(String columnName, Class javaType) {
		columns.put(columnName, toCQLType(javaType).toString());
		return this;
	}

	public CQLTableBuilder addList(String listName, Class javaValueType) {
		lists.put(listName, toCQLType(javaValueType).toString());
		return this;
	}

	public CQLTableBuilder addSet(String setName, Class javaValueType) {
		sets.put(setName, toCQLType(javaValueType).toString());
		return this;
	}

	public CQLTableBuilder addMap(String mapName, Class javaKeyType, Class javaValueType) {
		maps.put(mapName, Pair.create(toCQLType(javaKeyType).toString(), toCQLType(javaValueType).toString()));
		return this;
	}

	public CQLTableBuilder addPartitionComponent(String columnName) {
		Validator.validateFalse(lists.containsKey(columnName),
				"Partition component '%s' for table '%s' cannot be of list type", columnName, tableName);
		Validator.validateFalse(sets.containsKey(columnName),
				"Partition component '%s' for table '%s' cannot be of set type", columnName, tableName);
		Validator.validateFalse(maps.containsKey(columnName),
				"Partition component '%s' for table '%s' cannot be of map type", columnName, tableName);

		Validator.validateTrue(columns.containsKey(columnName),
				"Property '%s' for table '%s' cannot be found. Did you forget to declare it as column first ?",
				columnName, tableName);

		partitionComponents.add(columnName);

		return this;
	}

	public CQLTableBuilder addClusteringComponent(String columnName) {
		Validator.validateFalse(lists.containsKey(columnName),
				"Clustering component '%s' for table '%s' cannot be of list type", columnName, tableName);
		Validator.validateFalse(sets.containsKey(columnName),
				"Clustering component '%s' for table '%s' cannot be of set type", columnName, tableName);
		Validator.validateFalse(maps.containsKey(columnName),
				"Clustering component '%s' for table '%s' cannot be of map type", columnName, tableName);

		Validator.validateTrue(columns.containsKey(columnName),
				"Property '%s' for table '%s' cannot be found. Did you forget to declare it as column first ?",
				columnName, tableName);

		clusteringComponents.add(columnName);

		return this;
	}

	public CQLTableBuilder addComment(String comment) {
		Validator.validateNotBlank(comment, "Comment for table '%s' should not be blank", tableName);
		this.comment = comment.replaceAll("'", "\"");
		return this;
	}

	public String generateDDLScript() {

		String ddlScript;
		if (counter) {
			ddlScript = generateCounterTable();
		} else {
			ddlScript = generateTable();
		}

		log.debug(ddlScript);

		return ddlScript;
	}

	private String generateTable() {
		StringBuilder ddl = new StringBuilder();

		ddl.append("\n");
		ddl.append("\tCREATE TABLE ");
		ddl.append(tableName).append("(\n");

		for (Entry columnEntry : columns.entrySet()) {
			ddl.append("\t\t");
			ddl.append(columnEntry.getKey());
			ddl.append(" ");
			ddl.append(columnEntry.getValue());
			ddl.append(",\n");
		}
		for (Entry listEntry : lists.entrySet()) {
			ddl.append("\t\t");
			ddl.append(listEntry.getKey());
			ddl.append(" list<");
			ddl.append(listEntry.getValue());
			ddl.append(">");
			ddl.append(",\n");
		}
		for (Entry setEntry : sets.entrySet()) {
			ddl.append("\t\t");
			ddl.append(setEntry.getKey());
			ddl.append(" set<");
			ddl.append(setEntry.getValue());
			ddl.append(">");
			ddl.append(",\n");
		}
		for (Entry> mapEntry : maps.entrySet()) {
			ddl.append("\t\t");
			ddl.append(mapEntry.getKey());
			ddl.append(" map<");
			ddl.append(mapEntry.getValue().left);
			ddl.append(",");
			ddl.append(mapEntry.getValue().right);
			ddl.append(">");
			ddl.append(",\n");
			;
		}

		ddl.append("\t\t");
		ddl.append("PRIMARY KEY(");

		if (partitionComponents.size() > 1)
			ddl.append("(").append(StringUtils.join(partitionComponents, ", ")).append(")");
		else
			ddl.append(partitionComponents.get(0));

		if (clusteringComponents.size() > 0) {
			ddl.append(", ");
			ddl.append(StringUtils.join(clusteringComponents, ", "));
		}
		ddl.append(")\n");

		ddl.append("\t)");

		// Add comments
		ddl.append(" WITH COMMENT = '").append(comment).append("'");
		return ddl.toString();
	}

	private String generateCounterTable() {

		Validator.validateTrue(columns.size() == partitionComponents.size() + clusteringComponents.size() + 1,
				"Counter table '%s' should contain only one counter column and primary keys", tableName);

		StringBuilder ddl = new StringBuilder();

		ddl.append("\n");
		ddl.append("\tCREATE TABLE ");
		ddl.append(tableName).append("(\n");

		for (Entry columnEntry : columns.entrySet()) {
			String columnName = columnEntry.getKey();
			String valueType = columnEntry.getValue();

			ddl.append("\t\t");
			ddl.append(columnName);
			ddl.append(" ");
			if (partitionComponents.contains(columnName) || clusteringComponents.contains(columnName)) {
				ddl.append(valueType);
			} else {
				Validator.validateTrue(StringUtils.equals(valueType, COUNTER.toString()),
						"Column '%s' of table '%s' should be of type 'counter'", columnName, tableName);
				ddl.append("counter");
			}
			ddl.append(",\n");
		}

		ddl.append("\t\t");
		ddl.append("PRIMARY KEY(");

		if (partitionComponents.size() > 1)
			ddl.append("(").append(StringUtils.join(partitionComponents, ", ")).append(")");
		else
			ddl.append(partitionComponents.get(0));

		if (clusteringComponents.size() > 0) {
			ddl.append(", ");
			ddl.append(StringUtils.join(clusteringComponents, ", "));
		}

		ddl.append(")\n");

		ddl.append("\t)");

		// Add comments
		ddl.append(" WITH COMMENT = '").append(comment).append("'");
		return ddl.toString();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy