package io.crate.analyze.symbol;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import io.crate.metadata.FunctionInfo;
import io.crate.types.DataType;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class Function extends Symbol implements Cloneable {
private final List<Symbol> arguments;
private final FunctionInfo info;
public Function(StreamInput in) throws IOException {
info = new FunctionInfo();
info.readFrom(in);
arguments = Symbols.listFromStream(in);
}
public Function(FunctionInfo info, List<Symbol> arguments) {
Preconditions.checkNotNull(info, "function info is null");
Preconditions.checkArgument(arguments.size() == info.ident().argumentTypes().size(),
"number of arguments must match the number of argumentTypes of the FunctionIdent");
this.info = info;
assert arguments.isEmpty() || !(arguments instanceof ImmutableList) :
"must not be an immutable list - would break setArgument";
this.arguments = arguments;
}
public List<Symbol> arguments() {
return arguments;
}
public void setArgument(int index, Symbol symbol) {
arguments.set(index, symbol);
}
public FunctionInfo info() {
return info;
}
@Override
public DataType valueType() {
return info.returnType();
}
@Override
public SymbolType symbolType() {
return SymbolType.FUNCTION;
}
@Override
public <C, R> R accept(SymbolVisitor<C, R> visitor, C context) {
return visitor.visitFunction(this, context);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
info.writeTo(out);
Symbols.toStream(arguments, out);
}
@Override
public String toString() {
return String.format(Locale.ENGLISH, "%s(%s)", info.ident().name(), Joiner.on(",").join(arguments()));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Function function = (Function) o;
if (!arguments.equals(function.arguments)) return false;
return info.equals(function.info);
}
@Override
public int hashCode() {
int result = arguments.hashCode();
result = 31 * result + info.hashCode();
return result;
}
@Override
public Function clone() {
return new Function(this.info, new ArrayList<>(this.arguments));
}
}