/*
* OpenClinica is distributed under the
* GNU Lesser General Public License (GNU LGPL).
* For details see: http://www.openclinica.org/license
*
* Copyright 2003-2008 Akaza Research
*/
package org.akaza.openclinica.logic.expressionTree;
import org.akaza.openclinica.exception.OpenClinicaSystemException;
import org.joda.time.DateMidnight;
import org.joda.time.Days;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
/**
* @author Krikor Krumlian
*
*/
public class ArithmeticOpNode extends ExpressionNode {
Operator op;
ExpressionNode left;
ExpressionNode right;
ArithmeticOpNode(Operator op, ExpressionNode left, ExpressionNode right) {
// Construct a BinOpNode containing the specified data.
assert op == Operator.PLUS || op == Operator.MINUS || op == Operator.MULTIPLY || op == Operator.DIVIDE;
assert left != null && right != null;
this.op = op;
this.left = left;
this.right = right;
}
@Override
String testCalculate() throws OpenClinicaSystemException {
String l = left.testValue();
String r = right.testValue();
validate(l, r, left.getNumber(), right.getNumber());
String t = calculateDate(l, r);
if (t != null) {
return t;
}
double x = Double.valueOf(l);
double y = Double.valueOf(r);
return calc(x, y);
}
@Override
Object calculate() throws OpenClinicaSystemException {
String l = (String) left.value();
String r = (String) right.value();
validate(l, r);
String t = calculateDate(l, r);
if (t != null) {
return t;
}
double x = Double.valueOf(l);
double y = Double.valueOf(r);
return calc(x, y);
}
private String calculateDate(String leftValue, String rightValue) {
if (ExpressionTreeHelper.isDateyyyyMMdd(leftValue) && isDouble(rightValue)) {
logger.debug("We determined that leftValue was a date and rightValue a Double");
return calculateGenericDate(leftValue, rightValue);
}
if (isDouble(leftValue) && ExpressionTreeHelper.isDateyyyyMMdd(rightValue)) {
logger.debug("We determined that rightValue was a date and leftValue a Double");
return calculateGenericDate(rightValue, leftValue);
}
if (ExpressionTreeHelper.isDateyyyyMMdd(leftValue) && ExpressionTreeHelper.isDateyyyyMMdd(rightValue)) {
logger.debug("We determined that rightValue was a date and leftValue a Date");
return calculateDaysBetween(rightValue, leftValue);
}
return null;
}
private String calculateDaysBetween(String value1, String value2) {
DateMidnight dm1 = new DateMidnight(ExpressionTreeHelper.getDate(value1).getTime());
DateMidnight dm2 = new DateMidnight(ExpressionTreeHelper.getDate(value2).getTime());
switch (op) {
case MINUS: {
Days d = Days.daysBetween(dm1, dm2);
int days = d.getDays();
return String.valueOf(Math.abs(days));
}
default:
return null; // Bad operator!
}
}
private String calculateGenericDate(String value1, String value2) {
DateMidnight dm = new DateMidnight(ExpressionTreeHelper.getDate(value1).getTime());
DateTimeFormatter fmt = ISODateTimeFormat.date();
switch (op) {
case PLUS: {
dm = dm.plusDays(Double.valueOf(value2).intValue());
return fmt.print(dm);
}
case MINUS: {
dm = dm.minusDays(Double.valueOf(value2).intValue());
return fmt.print(dm);
}
default:
return null; // Bad operator!
}
}
private String calc(double x, double y) throws OpenClinicaSystemException {
switch (op) {
case PLUS:
return String.valueOf(x + y);
case MINUS:
return String.valueOf(x - y);
case MULTIPLY:
return String.valueOf(x * y);
case DIVIDE:
return String.valueOf(x / y);
default:
return null; // Bad operator!
}
}
void validate(String l, String r) throws OpenClinicaSystemException {
String t = calculateDate(l, r);
if (t == null) {
try {
Double.valueOf(l);
Double.valueOf(r);
} catch (NumberFormatException e) {
throw new OpenClinicaSystemException("OCRERR_0001", new Object[] { l, r, op.toString() });
}
}
}
void validate(String l, String r, String ltext, String rtext) throws OpenClinicaSystemException {
String t = calculateDate(l, r);
if (t == null) {
try {
Double.valueOf(l);
Double.valueOf(r);
} catch (NumberFormatException e) {
throw new OpenClinicaSystemException("OCRERR_0001", new Object[] { ltext, rtext, op.toString() });
}
}
}
boolean isInteger(String value) {
try {
Integer.valueOf(value);
return true;
} catch (NumberFormatException e) {
return false;
}
}
boolean isDouble(String value) {
try {
Double.valueOf(value);
return true;
} catch (NumberFormatException e) {
return false;
}
}
@Override
void printStackCommands() {
left.printStackCommands();
right.printStackCommands();
logger.info(" Operator " + op);
}
}