package com.g414.haildb;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
public class TableBuilder {
private final String name;
private final Map<String, ColumnDef> columns;
private final Map<String, List<IndexPart>> indexes;
private volatile AtomicInteger index = new AtomicInteger();
public TableBuilder(String name) {
String[] nameParts = name.split("/");
if (nameParts.length != 2) {
throw new IllegalArgumentException(
"Malformed table name - must include database name followed by slash");
}
this.name = name;
this.columns = new LinkedHashMap<String, ColumnDef>();
this.indexes = new LinkedHashMap<String, List<IndexPart>>();
}
public TableBuilder addColumn(String name, ColumnType type, int length,
ColumnAttribute... attrs) {
ColumnDef def = new ColumnDef(index.getAndIncrement(), name, type,
length, attrs);
this.columns.put(def.getName(), def);
return this;
}
public TableBuilder addIndex(String indexName, String column,
int prefixLen, boolean clustered, boolean unique) {
if (!this.indexes.containsKey(indexName)) {
this.indexes.put(indexName, new ArrayList<IndexPart>());
}
this.indexes.get(indexName).add(
new IndexPart(column, prefixLen, clustered, unique));
return this;
}
public TableDef build() {
String primary = getPrimaryIndex(this.indexes);
Map<String, IndexDef> defs = createIndexDefMap(primary);
return new TableDef(name, columns, defs, defs.get(primary));
}
private Map<String, IndexDef> createIndexDefMap(String primary) {
Map<String, IndexDef> defs = new LinkedHashMap<String, IndexDef>();
for (Map.Entry<String, List<IndexPart>> entry : indexes.entrySet()) {
boolean clustered = false;
boolean unique = false;
Map<String, ColumnDef> indexColumns = new LinkedHashMap<String, ColumnDef>();
Map<String, Integer> prefixLenOverrides = new LinkedHashMap<String, Integer>();
for (IndexPart part : entry.getValue()) {
clustered |= part.isClustered();
unique |= part.isUnique();
if (part.getPrefixLen() != 0) {
prefixLenOverrides.put(part.getColumn(), part
.getPrefixLen());
}
indexColumns.put(part.getColumn(), this.columns.get(part
.getColumn()));
}
for (IndexPart primaryPart : this.indexes.get(primary)) {
String primaryColumn = primaryPart.getColumn();
if (!indexColumns.containsKey(primaryColumn)) {
indexColumns.put(primaryColumn, this.columns
.get(primaryColumn));
}
}
List<ColumnDef> indexColumnList = new ArrayList<ColumnDef>();
indexColumnList.addAll(indexColumns.values());
IndexDef idx = new IndexDef(entry.getKey(), Collections
.unmodifiableList(indexColumnList), Collections
.unmodifiableMap(prefixLenOverrides), clustered, unique);
defs.put(entry.getKey(), idx);
}
return defs;
}
private static String getPrimaryIndex(Map<String, List<IndexPart>> defs) {
for (Map.Entry<String, List<IndexPart>> def : defs.entrySet()) {
if (def.getValue().get(0).isClustered()) {
return def.getKey();
}
}
return null;
}
private static class IndexPart {
private final String column;
private final int prefixLen;
private final boolean clustered;
private final boolean unique;
public IndexPart(String column, int prefixLen, boolean clustered,
boolean unique) {
this.column = column;
this.prefixLen = prefixLen;
this.clustered = clustered;
this.unique = unique;
}
public String getColumn() {
return column;
}
public int getPrefixLen() {
return prefixLen;
}
public boolean isClustered() {
return clustered;
}
public boolean isUnique() {
return unique;
}
}
}