/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.queries.visitors;
import org.whole.lang.bindings.BindingManagerFactory;
import org.whole.lang.exceptions.WholeIllegalArgumentException;
import org.whole.lang.model.IEntity;
import org.whole.lang.operations.DynamicCompilerOperation;
import org.whole.lang.queries.model.Addition;
import org.whole.lang.queries.model.AdditionStep;
import org.whole.lang.queries.model.BooleanLiteral;
import org.whole.lang.queries.model.ByteLiteral;
import org.whole.lang.queries.model.CharLiteral;
import org.whole.lang.queries.model.DateLiteral;
import org.whole.lang.queries.model.Division;
import org.whole.lang.queries.model.DivisionStep;
import org.whole.lang.queries.model.DoubleLiteral;
import org.whole.lang.queries.model.Equals;
import org.whole.lang.queries.model.EqualsStep;
import org.whole.lang.queries.model.Expression;
import org.whole.lang.queries.model.FeatureStep;
import org.whole.lang.queries.model.FloatLiteral;
import org.whole.lang.queries.model.GreaterOrEquals;
import org.whole.lang.queries.model.GreaterOrEqualsStep;
import org.whole.lang.queries.model.GreaterThan;
import org.whole.lang.queries.model.GreaterThanStep;
import org.whole.lang.queries.model.IntLiteral;
import org.whole.lang.queries.model.LessOrEquals;
import org.whole.lang.queries.model.LessOrEqualsStep;
import org.whole.lang.queries.model.LessThan;
import org.whole.lang.queries.model.LessThanStep;
import org.whole.lang.queries.model.LongLiteral;
import org.whole.lang.queries.model.Multiplication;
import org.whole.lang.queries.model.MultiplicationStep;
import org.whole.lang.queries.model.NotEquals;
import org.whole.lang.queries.model.NotEqualsStep;
import org.whole.lang.queries.model.PathExpression;
import org.whole.lang.queries.model.Predicate;
import org.whole.lang.queries.model.Remainder;
import org.whole.lang.queries.model.RemainderStep;
import org.whole.lang.queries.model.SelfStep;
import org.whole.lang.queries.model.ShortLiteral;
import org.whole.lang.queries.model.Singleton;
import org.whole.lang.queries.model.StringLiteral;
import org.whole.lang.queries.model.Subtraction;
import org.whole.lang.queries.model.SubtractionStep;
import org.whole.lang.queries.model.VariableRefStep;
import org.whole.lang.queries.model.VoidLiteral;
import org.whole.lang.queries.util.MathUtils;
import org.whole.lang.reflect.FeatureDescriptor;
import org.whole.lang.util.BehaviorUtils;
import org.whole.lang.util.BindingUtils;
import org.whole.lang.util.WholeMessages;
import org.whole.lang.visitors.MissingVariableException;
/**
* @author Riccardo Solmi
*/
public class QueriesInterpreterVisitor extends QueriesIdentityDefaultVisitor {
@Override
public void visit(PathExpression entity) {
DynamicCompilerOperation.compile(entity, getBindings());
}
@Override
public void visit(Predicate entity) {
DynamicCompilerOperation.compile(entity, getBindings());
}
protected IEntity evaluateOptional(Expression entity) {
entity.accept(this);
return getResult();
}
protected IEntity evaluate(Expression entity) {
IEntity result = evaluateOptional(entity);
if (result == null)
throw new WholeIllegalArgumentException(WholeMessages.null_value_argument).withSourceEntity(entity).withBindings(getBindings());
return result;
}
protected final boolean booleanValue(Expression exp) {
return evaluate(exp).wBooleanValue();
}
protected final int intValue(Expression exp) {
return evaluate(exp).wIntValue();
}
protected final String stringValue(Expression exp) {
return evaluate(exp).wStringValue();
}
protected final IEntity getSelfEntity(IEntity sourceEntity) {
IEntity self = getBindings().wGet("self");
if (self == null)
throw new MissingVariableException("self").withSourceEntity(sourceEntity).withBindings(getBindings());
return self;
}
@Override
public void visit(SelfStep entity) {
withSourceEntity(entity);
setResult(getSelfEntity(entity));
}
@Override
public void visit(VariableRefStep entity) {
String varName = entity.getValue();
IEntity value = BindingUtils.wGet(getBindings(), varName);
if (value == null)
throw new MissingVariableException(varName).withSourceEntity(entity).withBindings(getBindings());
setResult(value);
}
@Override
public void visit(FeatureStep entity) {
IEntity self = getSelfEntity(entity);
String featureName = entity.getValue();
FeatureDescriptor fd = self.wGetLanguageKit().getFeatureDescriptorEnum().valueOf(featureName);
if (fd == null || !self.wContains(fd))
visit((PathExpression) entity);
else
setResult(self.wGet(fd));
}
@Override
public void visit(BooleanLiteral entity) {
setResult(BindingManagerFactory.instance.createValue(entity.wBooleanValue()));
}
@Override
public void visit(ByteLiteral entity) {
setResult(BindingManagerFactory.instance.createValue(entity.wByteValue()));
}
@Override
public void visit(CharLiteral entity) {
setResult(BindingManagerFactory.instance.createValue(entity.wCharValue()));
}
@Override
public void visit(DoubleLiteral entity) {
setResult(BindingManagerFactory.instance.createValue(entity.wDoubleValue()));
}
@Override
public void visit(FloatLiteral entity) {
setResult(BindingManagerFactory.instance.createValue(entity.wFloatValue()));
}
@Override
public void visit(IntLiteral entity) {
setResult(BindingManagerFactory.instance.createSpecificValue(entity.wIntValue()));
}
@Override
public void visit(LongLiteral entity) {
setResult(BindingManagerFactory.instance.createSpecificValue(entity.wLongValue()));
}
@Override
public void visit(ShortLiteral entity) {
setResult(BindingManagerFactory.instance.createSpecificValue(entity.wShortValue()));
}
@Override
public void visit(DateLiteral entity) {
setResult(BindingManagerFactory.instance.createSpecificValue(entity.wDateValue()));
}
@Override
public void visit(StringLiteral entity) {
setResult(BindingManagerFactory.instance.createSpecificValue(entity.wStringValue()));
}
@Override
public void visit(VoidLiteral entity) {
setResult(BindingManagerFactory.instance.createVoid());
}
@Override
public void visit(AdditionStep entity) {
setResult(MathUtils.addition(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(SubtractionStep entity) {
setResult(MathUtils.subtraction(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(MultiplicationStep entity) {
setResult(MathUtils.multiplication(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(DivisionStep entity) {
setResult(MathUtils.division(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(RemainderStep entity) {
setResult(MathUtils.remainder(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(EqualsStep entity) {
setResult(MathUtils.equals(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(NotEqualsStep entity) {
setResult(MathUtils.notEquals(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(LessThanStep entity) {
setResult(MathUtils.lessThan(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(LessOrEqualsStep entity) {
setResult(MathUtils.lessOrEquals(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(GreaterThanStep entity) {
setResult(MathUtils.greaterThan(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(GreaterOrEqualsStep entity) {
setResult(MathUtils.greaterOrEquals(getSelfEntity(entity), evaluate(entity.getExpression())));
}
@Override
public void visit(Addition entity) {
setResult(MathUtils.addition(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(Subtraction entity) {
setResult(MathUtils.subtraction(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(Multiplication entity) {
setResult(MathUtils.multiplication(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(Division entity) {
setResult(MathUtils.division(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(Remainder entity) {
setResult(MathUtils.remainder(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(Equals entity) {
setResult(MathUtils.equals(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(NotEquals entity) {
setResult(MathUtils.notEquals(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(LessThan entity) {
setResult(MathUtils.lessThan(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(LessOrEquals entity) {
setResult(MathUtils.lessOrEquals(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(GreaterThan entity) {
setResult(MathUtils.greaterThan(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(GreaterOrEquals entity) {
setResult(MathUtils.greaterOrEquals(evaluate(entity.getExp1()), evaluate(entity.getExp2())));
}
@Override
public void visit(Singleton entity) {
entity.getExpression().accept(this);
BehaviorUtils.evaluateSingletonResult(getBindings());
}
}