package net.sourceforge.mayfly.evaluation.expression;
import net.sourceforge.mayfly.MayflyException;
import net.sourceforge.mayfly.MayflyInternalException;
import net.sourceforge.mayfly.Options;
import net.sourceforge.mayfly.datastore.Cell;
import net.sourceforge.mayfly.datastore.Column;
import net.sourceforge.mayfly.evaluation.Expression;
import net.sourceforge.mayfly.evaluation.ResultRow;
import net.sourceforge.mayfly.evaluation.ResultRows;
import net.sourceforge.mayfly.evaluation.select.Evaluator;
import net.sourceforge.mayfly.parser.Location;
public class SingleColumn extends Expression {
private final String tableOrAlias;
public final String originalTableOrAlias;
private final String columnName;
public final Options options;
public SingleColumn(String columnName) {
this(null, columnName);
}
public SingleColumn(String columnName, Location location, Options options) {
this(null, columnName, location, options);
}
public SingleColumn(String tableOrAlias, String columnName) {
this(tableOrAlias, columnName, new Options());
}
public SingleColumn(String tableOrAlias, String columnName, Options options) {
this(tableOrAlias, columnName, Location.UNKNOWN, options);
}
public SingleColumn(String tableOrAlias, String columnName,
Location location, Options options) {
this(tableOrAlias, tableOrAlias, columnName, location, options);
}
private SingleColumn(String tableOrAlias, String originalTableOrAlias,
String columnName, Location location, Options options) {
super(location);
this.tableOrAlias = tableOrAlias;
this.originalTableOrAlias = originalTableOrAlias;
this.columnName = columnName;
this.options = options;
}
@Override
public Cell evaluate(ResultRow row, Evaluator evaluator) {
return evaluator.lookup(row, tableOrAlias, originalTableOrAlias, columnName, location);
}
@Override
public Cell evaluate(ResultRow row) {
Expression found = lookup(row);
return row.findValue(found);
}
public SingleColumn lookup(ResultRow row) {
return row.findColumn(
tableOrAlias, originalTableOrAlias, columnName, location);
}
@Override
public Cell aggregate(ResultRows rows) {
throw new MayflyInternalException(
"shouldn't combine aggregate and column expressions");
}
@Override
public String firstColumn() {
return displayName();
}
@Override
public String displayName() {
return Column.displayName(originalTableOrAlias, columnName);
}
@Override
public String debugName() {
return Column.displayName(tableOrAlias, columnName);
}
@Override
public boolean matches(String target) {
return matches(null, target);
}
public boolean matches(String tableOrAlias, String target) {
if (target.indexOf('.') != -1) {
throw new MayflyException("column name " + target + " should not contain a period");
}
if (tableOrAlias != null && !matchesAliasOrTable(tableOrAlias)) {
return false;
}
return this.columnName.equalsIgnoreCase(target);
}
public boolean matchesAliasOrTable(String tableOrAlias) {
return options.tableNamesEqual(tableOrAlias, this.tableOrAlias);
}
@Override
public boolean sameExpression(Expression other) {
if (other instanceof SingleColumn) {
SingleColumn column = (SingleColumn) other;
return possiblyNullTablesEqual(tableOrAlias, column.tableOrAlias) &&
columnName.equalsIgnoreCase(column.columnName);
}
else {
return false;
}
}
boolean possiblyNullTablesEqual(String one, String two) {
if (one == null) {
return two == null;
}
else {
return options.tableNamesEqual(one, two);
}
}
@Override
public Expression resolve(ResultRow row, Evaluator evaluator) {
if (tableOrAlias == null) {
Expression lookedUp = evaluator.lookupName(row, columnName, location);
if (lookedUp != null) {
return lookedUp;
}
SingleColumn column = lookup(row);
// if (column.tableOrAlias() == null) {
// throw new NullPointerException();
// }
return new SingleColumn(column.tableOrAlias(),
originalTableOrAlias, columnName, location, options);
}
else {
return this;
}
}
/**
* @internal
* Low-level helper for {@link #resolve(ResultRow, Evaluator)} and
* related machinery.
*/
public SingleColumn asResultOfResolution(String spellingOfColumnName,
Location location2) {
if (!spellingOfColumnName.equalsIgnoreCase(columnName)) {
throw new MayflyInternalException(
"expected " + spellingOfColumnName + " and " + columnName +
" to differ only in case");
}
return new SingleColumn(tableOrAlias, null,
spellingOfColumnName, location2, options);
}
@Override
public void check(ResultRow row) {
lookup(row);
}
public String tableOrAlias() {
return tableOrAlias;
}
public String columnName() {
return columnName;
}
public void assertIsResolved() {
if (tableOrAlias == null) {
throw new MayflyInternalException(
"column " + displayName() +
" should have been resolved to a table/alias");
}
}
}