package io.ebeaninternal.server.expression;
import io.ebean.Expression;
import io.ebean.Junction;
import io.ebean.event.BeanQueryRequest;
import io.ebeaninternal.api.ManyWhereJoins;
import io.ebeaninternal.api.NaturalKeyQueryData;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.SpiExpressionValidation;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import java.io.IOException;
abstract class LogicExpression implements SpiExpression {
static final String AND = " and ";
static final String OR = " or ";
static class And extends LogicExpression {
And(Expression expOne, Expression expTwo) {
super(true, expOne, expTwo);
}
@Override
public SpiExpression copyForPlanKey() {
return new And(expOne.copyForPlanKey(), expTwo.copyForPlanKey());
}
}
static class Or extends LogicExpression {
Or(Expression expOne, Expression expTwo) {
super(false, expOne, expTwo);
}
@Override
public SpiExpression copyForPlanKey() {
return new Or(expOne.copyForPlanKey(), expTwo.copyForPlanKey());
}
}
SpiExpression expOne;
SpiExpression expTwo;
private final boolean conjunction;
LogicExpression(boolean conjunction, Expression expOne, Expression expTwo) {
this.conjunction = conjunction;
this.expOne = (SpiExpression) expOne;
this.expTwo = (SpiExpression) expTwo;
}
@Override
public boolean naturalKey(NaturalKeyQueryData<?> data) {
return false;
}
@Override
public void simplify() {
}
@Override
public void writeDocQuery(DocQueryContext context) throws IOException {
context.startBool(conjunction ? Junction.Type.AND : Junction.Type.OR);
expOne.writeDocQuery(context);
expTwo.writeDocQuery(context);
context.endBool();
}
@Override
public String nestedPath(BeanDescriptor<?> desc) {
String pathOne = expOne.nestedPath(desc);
String pathTwo = expTwo.nestedPath(desc);
if (pathOne == null && pathTwo == null) {
return null;
}
if (pathOne != null && pathOne.equals(pathTwo)) {
return pathOne;
}
if (pathOne != null) {
expOne = new NestedPathWrapperExpression(pathOne, expOne);
}
if (pathTwo != null) {
expTwo = new NestedPathWrapperExpression(pathTwo, expTwo);
}
return null;
}
@Override
public Object getIdEqualTo(String idName) {
return null;
}
@Override
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
boolean parentOuterJoins = manyWhereJoin.isRequireOuterJoins();
if (!conjunction) {
manyWhereJoin.setRequireOuterJoins(true);
}
expOne.containsMany(desc, manyWhereJoin);
expTwo.containsMany(desc, manyWhereJoin);
if (!conjunction && !parentOuterJoins) {
manyWhereJoin.setRequireOuterJoins(false);
}
}
@Override
public void validate(SpiExpressionValidation validation) {
expOne.validate(validation);
expTwo.validate(validation);
}
@Override
public void addBindValues(SpiExpressionRequest request) {
expOne.addBindValues(request);
expTwo.addBindValues(request);
}
@Override
public void addSql(SpiExpressionRequest request) {
request.append("(");
expOne.addSql(request);
request.append(conjunction ? AND : OR);
expTwo.addSql(request);
request.append(")");
}
@Override
public void prepareExpression(BeanQueryRequest<?> request) {
expOne.prepareExpression(request);
expTwo.prepareExpression(request);
}
@Override
public void queryPlanHash(StringBuilder builder) {
builder.append("Logic").append(conjunction ? AND : OR).append("[");
expOne.queryPlanHash(builder);
builder.append(",");
expTwo.queryPlanHash(builder);
builder.append("]");
}
@Override
public int queryBindHash() {
int hc = expOne.queryBindHash();
hc = hc * 92821 + expTwo.queryBindHash();
return hc;
}
@Override
public boolean isSameByBind(SpiExpression other) {
LogicExpression that = (LogicExpression) other;
return this.expOne.isSameByBind(that.expOne)
&& this.expTwo.isSameByBind(that.expTwo);
}
}