/*
* Copyright (c) 2011-2015 EPFL DATA Laboratory
* Copyright (c) 2014-2015 The Squall Collaboration (see NOTICE)
*
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.epfl.data.squall.thetajoin.predicate_analyser;
import java.util.List;
import ch.epfl.data.squall.expressions.Addition;
import ch.epfl.data.squall.expressions.ColumnReference;
import ch.epfl.data.squall.expressions.Multiplication;
import ch.epfl.data.squall.expressions.Subtraction;
import ch.epfl.data.squall.expressions.ValueExpression;
import ch.epfl.data.squall.expressions.ValueSpecification;
import ch.epfl.data.squall.predicates.AndPredicate;
import ch.epfl.data.squall.predicates.ComparisonPredicate;
import ch.epfl.data.squall.predicates.OrPredicate;
import ch.epfl.data.squall.predicates.Predicate;
import ch.epfl.data.squall.types.DoubleType;
import ch.epfl.data.squall.types.IntegerType;
import ch.epfl.data.squall.types.NumericType;
public class PredicateAnalyser {
NumericType numConv = new DoubleType();
ValueExpression[] CleanPart = new ValueExpression[2];
ValueExpression[] Parameter = new ValueExpression[2];
ValueExpression[] Variable = new ValueExpression[2];
public PredicateAnalyser() {
}
public Predicate analyse(Predicate toAnalyse) {
final List<Predicate> inner = toAnalyse.getInnerPredicates();
if (toAnalyse instanceof AndPredicate)
return new AndPredicate(analyse(inner.get(0)),
analyse(inner.get(1)));
else if (toAnalyse instanceof OrPredicate)
return new OrPredicate(analyse(inner.get(0)), analyse(inner.get(1)));
else if (toAnalyse instanceof ComparisonPredicate)
return comparisonPredAnalyse(toAnalyse);
return toAnalyse;
}
ValueExpression changeToDouble(ValueExpression other) {
if (other instanceof ColumnReference)
return new ColumnReference<Double>(numConv,
((ColumnReference) other).getColumnIndex());
else if (other instanceof ValueSpecification) {
IntegerType change;
if (other.getType() instanceof IntegerType) {
change = (IntegerType) other.getType();
final double temp = change.toDouble(other.eval(null));
final ValueSpecification tempVS = new ValueSpecification<Double>(
numConv, temp);
return tempVS;
} else
return other;
} else if (other instanceof Addition) {
final List<ValueExpression> followUps = other.getInnerExpressions();
return new Addition<Double>(changeToDouble(followUps.get(0)),
changeToDouble(followUps.get(1)));
} else if (other instanceof Subtraction) {
final List<ValueExpression> followUps = other.getInnerExpressions();
return new Subtraction<Double>(changeToDouble(followUps.get(0)),
changeToDouble(followUps.get(1)));
} else if (other instanceof Multiplication) {
final List<ValueExpression> followUps = other.getInnerExpressions();
return new Multiplication<Double>(changeToDouble(followUps.get(0)),
changeToDouble(followUps.get(1)));
}
return null;
}
ValueExpression combine(ValueExpression parent, int index,
ValueExpression expr1) {
if ((expr1 instanceof ColumnReference)
|| (expr1 instanceof ValueSpecification))
return expr1;
else {
final List<ValueExpression> next = expr1.getInnerExpressions();
ValueExpression toCombine1 = combine(expr1, 0, next.get(0));
ValueExpression toCombine2 = combine(expr1, 1, next.get(1));
if ((toCombine1 instanceof ValueSpecification)
&& (toCombine2 instanceof ValueSpecification)) {
final Double result = new Double(expr1.evalString(null));
final ValueExpression newExpr = new ValueSpecification<Double>(
numConv, result);
if (parent != null)
parent.changeValues(index, newExpr);
return newExpr;
} else if ((!(toCombine1 instanceof ValueSpecification) && (toCombine2 instanceof ValueSpecification))
|| // Variable on the First one or the Second one
((toCombine1 instanceof ValueSpecification) && !(toCombine2 instanceof ValueSpecification))) {
// Either way make toCombine1 variable have the Variable
ValueExpression temp;
if ((toCombine1 instanceof ValueSpecification)
&& !(toCombine2 instanceof ValueSpecification)) {
temp = toCombine1;
toCombine1 = toCombine2;
toCombine2 = temp;
}
final List<ValueExpression> toComb1List = toCombine1
.getInnerExpressions();
ValueExpression clean, dirty;
int cleanPartOfInner = 0;
if (expr1 instanceof Multiplication) {
ValueExpression multResult;
if (toCombine1 instanceof Multiplication) {
if (toComb1List.get(0) instanceof ValueSpecification) {
clean = toComb1List.get(0);
dirty = toComb1List.get(1);
} else {
clean = toComb1List.get(1);
dirty = toComb1List.get(0);
cleanPartOfInner = 1;
}
ValueExpression extraClean = new Multiplication<Double>(
toCombine2, clean);
extraClean = combine(null, 0, extraClean);
multResult = new Multiplication<Double>(extraClean,
dirty);
return multResult;
} else if (toCombine1 instanceof Addition) {
if (toComb1List.get(0) instanceof ValueSpecification) {
clean = toComb1List.get(0);
dirty = toComb1List.get(1);
} else {
clean = toComb1List.get(1);
dirty = toComb1List.get(0);
cleanPartOfInner = 1;
}
ValueExpression extraClean = new Multiplication<Double>(
toCombine2, clean);
extraClean = combine(null, 0, extraClean);
final ValueExpression variableCont = new Multiplication<Double>(
toCombine2, dirty);
multResult = new Addition<Double>(extraClean,
variableCont);
return multResult;
} else if (toCombine1 instanceof Subtraction) {
if (toComb1List.get(0) instanceof ValueSpecification) {
clean = toComb1List.get(0);
dirty = toComb1List.get(1);
} else {
clean = toComb1List.get(1);
dirty = toComb1List.get(0);
cleanPartOfInner = 1;
}
ValueExpression extraClean = new Multiplication<Double>(
toCombine2, clean);
extraClean = combine(null, 0, extraClean);
final ValueExpression variableCont = new Multiplication<Double>(
toCombine2, dirty);
if (cleanPartOfInner == 0)
multResult = new Subtraction<Double>(extraClean,
variableCont);
else
multResult = new Subtraction<Double>(variableCont,
extraClean);
return multResult;
} else if (toCombine1 instanceof ColumnReference)
return expr1;
} else if (expr1 instanceof Addition) {
ValueExpression extraClean, finalAdd;
if (toCombine1 instanceof Multiplication) {
if (toComb1List.get(0) instanceof ValueSpecification) {
clean = toComb1List.get(0);
dirty = toComb1List.get(1);
} else {
clean = toComb1List.get(1);
dirty = toComb1List.get(0);
cleanPartOfInner = 1;
}
finalAdd = new Addition<Double>(toCombine1, toCombine2);
return finalAdd;
} else if (toCombine1 instanceof Addition) {
if (toComb1List.get(0) instanceof ValueSpecification) {
clean = toComb1List.get(0);
dirty = toComb1List.get(1);
} else {
clean = toComb1List.get(1);
dirty = toComb1List.get(0);
cleanPartOfInner = 1;
}
extraClean = new Addition<Double>(toCombine2, clean);
extraClean = combine(null, 0, extraClean);
finalAdd = new Addition<Double>(extraClean, dirty);
return finalAdd;
} else if (toCombine1 instanceof Subtraction) {
if (toComb1List.get(0) instanceof ValueSpecification) {
clean = toComb1List.get(0);
dirty = toComb1List.get(1);
} else {
clean = toComb1List.get(1);
dirty = toComb1List.get(0);
cleanPartOfInner = 1;
}
if (cleanPartOfInner == 0) {
extraClean = new Addition<Double>(toCombine2, clean);
extraClean = combine(null, 0, extraClean);
finalAdd = new Subtraction<Double>(extraClean,
dirty);
} else {
extraClean = new Subtraction<Double>(toCombine2,
clean);
extraClean = combine(null, 0, extraClean);
finalAdd = new Addition<Double>(dirty, extraClean);
}
return finalAdd;
} else if (toCombine1 instanceof ColumnReference)
return expr1;
} else if (expr1 instanceof Subtraction) {
ValueExpression finalSub;
if (toCombine1 instanceof Addition) {
if (toComb1List.get(0) instanceof ValueSpecification) {
clean = toComb1List.get(0);
dirty = toComb1List.get(1);
} else {
clean = toComb1List.get(1);
dirty = toComb1List.get(0);
cleanPartOfInner = 1;
}
ValueExpression extraClean = new Subtraction<Double>(
clean, toCombine2);
extraClean = combine(null, 0, extraClean);
finalSub = new Addition<Double>(dirty, extraClean);
return finalSub;
} else if (toCombine1 instanceof Subtraction) {
if (toComb1List.get(0) instanceof ValueSpecification) {
clean = toComb1List.get(0);
dirty = toComb1List.get(1);
} else {
clean = toComb1List.get(1);
dirty = toComb1List.get(0);
cleanPartOfInner = 1;
}
if (cleanPartOfInner == 0) {
ValueExpression extraClean = new Subtraction<Double>(
clean, toCombine2);
extraClean = combine(null, 0, extraClean);
finalSub = new Subtraction<Double>(extraClean,
dirty);
} else {
ValueExpression extraClean = new Subtraction<Double>(
toCombine2, clean);
extraClean = combine(null, 0, extraClean);
finalSub = new Subtraction<Double>(dirty,
extraClean);
}
return finalSub;
} else if (toCombine1 instanceof Multiplication) {
if (toComb1List.get(0) instanceof ValueSpecification) {
clean = toComb1List.get(0);
dirty = toComb1List.get(1);
} else {
clean = toComb1List.get(1);
dirty = toComb1List.get(0);
cleanPartOfInner = 1;
}
ValueExpression extraClean = new Multiplication<Double>(
toCombine2, clean);
extraClean = combine(null, 0, extraClean);
finalSub = new Multiplication<Double>(extraClean, dirty);
return finalSub;
} else if (toCombine1 instanceof ColumnReference)
return expr1;
}
} else if (!(toCombine1 instanceof ValueSpecification)
&& !(toCombine2 instanceof ValueSpecification))// Both Parts
// are
// Something
// weird...
// //
// Chaos...
{
}
}
return null;
}
public Predicate comparisonPredAnalyse(Predicate toAnalyse) {
if (!(toAnalyse instanceof ComparisonPredicate))
return toAnalyse;
// Check if is Double or Integer
ComparisonPredicate compToAnalyse = (ComparisonPredicate) toAnalyse;
List<ValueExpression> followUps = compToAnalyse.getExpressions();
// if one of the previous change to Double
toAnalyse = getSameForDouble(toAnalyse);
compToAnalyse = (ComparisonPredicate) toAnalyse;
followUps = compToAnalyse.getExpressions();
ValueExpression leftPart = null;
try {
leftPart = combine(null, 0, followUps.get(0));
} catch (final Exception e) {
return toAnalyse;
}
ValueExpression rightPart = null;
try {
rightPart = combine(null, 0, followUps.get(1));
} catch (final Exception e) {
return toAnalyse;
}
boolean temp = false;
getInfo(leftPart, temp, 0);
temp = false;
getInfo(rightPart, temp, 1);
if (Parameter[0] == null)
Parameter[0] = new ValueSpecification<Double>(numConv, 1.0);
if (Parameter[1] == null)
Parameter[1] = new ValueSpecification<Double>(numConv, 1.0);
Parameter[0].inverseNumber();
ValueExpression fullClean = null;
if (CleanPart[0] != null) {
if (CleanPart[1] != null)
fullClean = new Subtraction<Double>(CleanPart[1], CleanPart[0]);
else if (CleanPart[1] == null) {
final ValueExpression temp1 = new ValueSpecification<Double>(
numConv, 0.0);
fullClean = new Subtraction<Double>(temp1, CleanPart[0]);
}
} else if (CleanPart[0] == null)
if (CleanPart[1] != null)
fullClean = CleanPart[1];
else
fullClean = new ValueSpecification(numConv, 0.0);
fullClean = combine(null, 0, fullClean);
ValueExpression finalA = new Multiplication<Double>(Parameter[0],
Parameter[1]);
finalA = combine(null, 0, finalA);
ValueExpression finalB = new Multiplication<Double>(Parameter[0],
fullClean);
finalB = combine(null, 0, finalB);
final ValueExpression withVariable = new Multiplication<Double>(finalA,
Variable[1]);
final ValueExpression finalRightPart = new Addition<Double>(
withVariable, finalB);
Predicate finalPred;
if (Parameter[0].isNegative())
finalPred = new ComparisonPredicate(
compToAnalyse.getOperator(true), Variable[0],
finalRightPart);
else
finalPred = new ComparisonPredicate(
compToAnalyse.getOperator(false), Variable[0],
finalRightPart);
return finalPred;
}
void getInfo(ValueExpression expr, boolean param, int leftOrRight) {
if (expr instanceof ColumnReference)
Variable[leftOrRight] = expr;
else if (expr instanceof ValueSpecification) {
if (param)
Parameter[leftOrRight] = expr;
else
CleanPart[leftOrRight] = expr;
} else {
final List<ValueExpression> next = expr.getInnerExpressions();
if (expr instanceof Multiplication)
param = true;
getInfo(next.get(0), param, leftOrRight);
getInfo(next.get(1), param, leftOrRight);
param = false;
}
}
Predicate getSameForDouble(Predicate pred) {
final ComparisonPredicate compPred = (ComparisonPredicate) pred;
final List<ValueExpression> followUps = compPred.getExpressions();
final ValueExpression left = changeToDouble(followUps.get(0));
final ValueExpression right = changeToDouble(followUps.get(1));
final Predicate finalPred = new ComparisonPredicate<Double>(
compPred.getOperator(false), left, right);
return finalPred;
}
}