package net.sourceforge.mayfly.datastore;
import net.sourceforge.mayfly.MayflyException;
import net.sourceforge.mayfly.evaluation.NoColumn;
import net.sourceforge.mayfly.parser.Location;
import net.sourceforge.mayfly.util.CaseInsensitiveString;
import net.sourceforge.mayfly.util.ImmutableList;
import net.sourceforge.mayfly.util.ImmutableMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class Columns implements Iterable<Column> {
public static Columns fromColumnNames(Iterable<String> names) {
List<Column> columnList = new ArrayList<Column>();
for (String name : names) {
columnList.add(new Column(name));
}
return new Columns(new ImmutableList(columnList));
}
public static Columns fromColumnNames(String... names) {
List<Column> columnList = new ArrayList<Column>();
for (String name : names) {
columnList.add(new Column(name));
}
return new Columns(new ImmutableList(columnList));
}
public static Columns singleton(Column column) {
return new Columns(
ImmutableList.fromArray(new Column[] { column }));
}
final ImmutableList<CaseInsensitiveString> columnNames;
final ImmutableMap<CaseInsensitiveString, Column> nameToColumn;
public Columns(ImmutableList<Column> columns) {
List names = new ArrayList();
Map map = new HashMap();
for (Column column : columns) {
CaseInsensitiveString name = column.columnName;
names.add(name);
Object oldColumn = map.put(name, column);
if (oldColumn != null) {
throw new MayflyException("duplicate column " + name);
}
}
this.columnNames = new ImmutableList<CaseInsensitiveString>(names);
this.nameToColumn = new ImmutableMap(map);
}
private Columns(ImmutableList<CaseInsensitiveString> names, ImmutableMap map) {
this.columnNames = names;
this.nameToColumn = map;
}
public Iterator iterator() {
return new Iterator() {
Iterator delegate = columnNames.iterator();
public boolean hasNext() {
return delegate.hasNext();
}
public Object next() {
CaseInsensitiveString name = (CaseInsensitiveString)
delegate.next();
return nameToColumn.get(name);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public ImmutableList<String> asNames() {
List<String> names = new ArrayList<String>();
for (CaseInsensitiveString column : columnNames) {
names.add(column.getString());
}
return new ImmutableList<String>(names);
}
public ImmutableList<CaseInsensitiveString> asCaseNames() {
return columnNames;
}
public Column column(int index) {
return nameToColumn.get(columnNames.get(index));
}
public Column columnFromName(String columnName) {
return columnFromName(columnName, Location.UNKNOWN);
}
public Column columnFromName(String columnName, Location location) {
Column found = nameToColumn.get(new CaseInsensitiveString(columnName));
if (found == null) {
throw new NoColumn(columnName, location);
} else {
return found;
}
}
public boolean hasColumn(String name) {
return nameToColumn.containsKey(new CaseInsensitiveString(name));
}
public Columns replace(Column replacement) {
return replace(replacement.columnName(), replacement);
}
public Columns replace(String existingName, Column replacement) {
boolean found = false;
List result = new ArrayList();
for (Iterator iter = iterator(); iter.hasNext(); ) {
Column column = (Column) iter.next();
if (column.matches(existingName)) {
result.add(replacement);
found = true;
}
else {
result.add(column);
}
}
if (!found) {
throw new NoColumn(existingName);
}
return new Columns(new ImmutableList(result));
}
public Columns with(Column newColumn) {
return with(newColumn, Position.LAST);
}
public Columns with(Column newColumn, Position position) {
CaseInsensitiveString newName = newColumn.columnName;
boolean found = false;
List result = new ArrayList();
if (position.isFirst()) {
result.add(newName);
found = true;
}
for (CaseInsensitiveString existing: columnNames) {
result.add(existing);
if (position.isAfter(existing.getString())) {
result.add(newName);
found = true;
}
}
if (position.isLast()) {
result.add(newName);
found = true;
}
if (!found) {
throw new NoColumn(position.afterWhat(), position.location());
}
if (nameToColumn.containsKey(newName)) {
throw new MayflyException("duplicate column " + newName,
position.location());
}
return new Columns(new ImmutableList(result),
nameToColumn.with(newName, newColumn));
}
public Columns without(String target) {
boolean found = false;
List result = new ArrayList();
for (Iterator iter = iterator(); iter.hasNext(); ) {
Column column = (Column) iter.next();
if (column.matches(target)) {
found = true;
}
else {
result.add(column);
}
}
if (found) {
if (result.isEmpty()) {
throw new MayflyException("attempt to drop the last column: " + target);
}
return new Columns(new ImmutableList(result));
}
else {
throw new NoColumn(target);
}
}
public int columnCount() {
return columnNames.size();
}
public String columnName(int index) {
return column(index).columnName();
}
public CaseInsensitiveString columnCase(int index) {
return new CaseInsensitiveString(columnName(index));
}
}