package se.cambio.cds.util;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import se.cambio.cds.gdl.model.expression.*;
import se.cambio.cds.util.export.DVDefSerializer;
import se.cambio.cm.model.archetype.vo.ArchetypeElementVO;
import se.cambio.openehr.util.OpenEHRConst;
import se.cambio.openehr.util.OpenEHRDataValues;
import se.cambio.openehr.util.OpenEHRDataValuesUI;
import se.cambio.openehr.util.exceptions.InternalErrorException;
import java.util.Map;
import java.util.Set;
/**
* User: iago.corbal
* Date: 2013-12-11
* Time: 17:23
*/
public class ExpressionUtil {
public static String CODE_FUNCTION_SEPARATOR = "#";
public static String getArithmeticExpressionStr(
Map<String, ArchetypeElementVO> elementMap,
ExpressionItem expressionItem, Map<RefStat, Set<String>> stats) throws InternalErrorException {
StringBuffer sb = new StringBuffer();
if (expressionItem instanceof BinaryExpression) {
BinaryExpression binaryExpression = (BinaryExpression) expressionItem;
if (OperatorKind.EXPONENT.equals(binaryExpression.getOperator())) {
sb.append("Math.pow(");
sb.append(getArithmeticExpressionStr(elementMap,
binaryExpression.getLeft(), stats));
sb.append(",");
sb.append(getArithmeticExpressionStr(elementMap,
binaryExpression.getRight(), stats));
sb.append(")");
} else {
sb.append("("
+ getArithmeticExpressionStr(elementMap,
binaryExpression.getLeft(), stats));
sb.append(binaryExpression.getOperator().getSymbol());
sb.append(getArithmeticExpressionStr(elementMap,
binaryExpression.getRight(), stats) + ")");
}
} else if (expressionItem instanceof Variable) {
Variable var = (Variable) expressionItem;
String rmName = null;
if (OpenEHRConst.CURRENT_DATE_TIME_ID.equals(var.getCode())){
rmName = OpenEHRDataValues.DV_DATE_TIME;
}else{
ArchetypeElementVO aeVO = elementMap.get(var.getCode());
if (aeVO==null){
throw new InternalErrorException(new Exception("Archetype element not found for gtcode '"+var.getCode()+"'"));
}
rmName = aeVO.getRMType();
}
sb.append(getVariableWithAttributeStr(rmName, var));
if (stats!=null){
if (isFunction(var.getAttribute())){
stats.get(RefStat.ATT_FUNCTIONS).add(var.getCode()+CODE_FUNCTION_SEPARATOR+var.getAttribute());
stats.get(RefStat.ATT_FUNCTIONS_REF).add(var.getCode());
}else{
stats.get(RefStat.REFERENCE).add(var.getCode());
}
}
} else if (expressionItem instanceof StringConstant) {
String stringValue = expressionItem.toString();
if (stringValue.startsWith("'") && stringValue.endsWith("'") && stringValue.length() > 1){
stringValue = "\"" + stringValue.substring(1, stringValue.length()-1) + "\"";
}
sb.append(stringValue);
} else if (expressionItem instanceof ConstantExpression) {
sb.append(formatConstantValue((ConstantExpression) expressionItem));
} else {
throw new InternalErrorException(new Exception(
"Unknown expression '"
+ expressionItem.getClass().getName() + "'"));
}
return sb.toString();
}
/*
* Parse for units of hr and convert value to milliseconds
*/
public static String formatConstantValue(ConstantExpression exp) throws InternalErrorException {
String value = exp.getValue();
int i = value.indexOf(",");
if(i > 0 ){
//Convert time units to milliseconds
String units = value.substring(i+1).trim();
if (units.equals("a")) {
double d = Double.parseDouble(value.substring(0, i));
value = "31556926000L*" + d;
}else if (units.equals("mo")) {
double d = Double.parseDouble(value.substring(0, i));
value = "2629743830L*" + d;
}else if (units.equals("wk")) {
double d = Double.parseDouble(value.substring(0, i));
value = "604800000L*" + d;
}else if (units.equals("d")) {
double d = Double.parseDouble(value.substring(0, i));
value = "86400000L*" + d;
}else if (units.equals("h")) {
double d = Double.parseDouble(value.substring(0, i));
value = "3600000L*" + d;
}else if (units.equals("min")) {
double d = Double.parseDouble(value.substring(0, i));
value = "60000L*" + d;
}else if (units.equals("s")) {
double d = Double.parseDouble(value.substring(0, i));
value = "1000L*" + d;
} else if (units.equals("S")) {
double d = Double.parseDouble(value.substring(0, i));
value = "" + d;
}else{
throw new InternalErrorException(new Exception("Unknown time units '"+units+"'"));
}
}
return value;
}
public static String getVariableWithAttributeStr(String rmName, Variable var) {
Logger.getLogger(DVUtil.class).debug("Var.code: " + var.getCode() + ", attr: " + var.getAttribute());
String dvClassName = DVDefSerializer.getDVClassName(rmName);
String ret = null;
// TODO fix setting currentDateTime
if(OpenEHRConst.CURRENT_DATE_TIME_ID.equals(var.getCode()) && (var.getAttribute()==null||var.getAttribute().equals("value"))) {
ret = "$"+OpenEHRConst.CURRENT_DATE_TIME_ID+".getDateTime().getMillis()";
} else if("value".equals(var.getAttribute()) &&("DvDateTime".equals(dvClassName)
|| "DvDate".equals(dvClassName))) {
ret = "((" + dvClassName + ")$" + var.getCode() +
getDataValueMethod(var.getCode()) +
").getDateTime().getMillis()";
} else {
if (isFunction(var.getAttribute())){
//Function (Only working for count yet)
if (OpenEHRDataValues.FUNCTION_COUNT.equals(var.getAttribute())){
ret = "$"+var.getCode()+var.getAttribute();
}
}else{
//Attribute
ret = "((" + dvClassName + ")$" + var.getCode()
+ getDataValueMethod(var.getCode()) + ").get"
+ StringUtils.capitalize(var.getAttribute()) + "()";
}
}
return ret;
}
public static String getDataValueMethod(String gtCode) {
if (!OpenEHRConst.CURRENT_DATE_TIME_ID.equals(gtCode)) {
return ".getDataValue()";
} else {
return "";
}
}
public static boolean isFunction(String attribute){
return OpenEHRDataValuesUI.getFunctionNames().contains(attribute);
}
}