All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.cambio.cds.util.ExpressionUtil Maven / Gradle / Ivy

package se.cambio.cds.util;

import org.apache.commons.lang.StringUtils;
import org.slf4j.LoggerFactory;
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 java.util.Map;
import java.util.Set;

import static java.lang.String.format;
import static org.springframework.util.StringUtils.capitalize;

public class ExpressionUtil {

    public static final String CODE_FUNCTION_SEPARATOR = "#";

    public static String getArithmeticExpressionStr(
            Map elementMap,
            ExpressionItem expressionItem, Map> stats) {
        return getArithmeticExpressionStr(elementMap, expressionItem, stats, null);
    }

    private static String getArithmeticExpressionStr(
            Map elementMap,
            ExpressionItem expressionItem, Map> stats,
            ExpressionItem parentExpressionItem) {
        StringBuilder sb = new StringBuilder();
        if (expressionItem instanceof BinaryExpression) {
            BinaryExpression binaryExpression = (BinaryExpression) expressionItem;
            if (OperatorKind.EXPONENT.equals(binaryExpression.getOperator())) {
                sb.append("(double) Math.pow(");
                sb.append(getArithmeticExpressionStr(elementMap,
                        binaryExpression.getLeft(), stats, binaryExpression));
                sb.append(",");
                sb.append(getArithmeticExpressionStr(elementMap,
                        binaryExpression.getRight(), stats, binaryExpression));
                sb.append(")");
            } else {
                sb.append("(")
                        .append(getArithmeticExpressionStr(elementMap, binaryExpression.getLeft(), stats, binaryExpression));
                sb.append(binaryExpression.getOperator().getSymbol());
                sb.append(getArithmeticExpressionStr(elementMap, binaryExpression.getRight(), stats, binaryExpression))
                        .append(")");
            }
        } else if (expressionItem instanceof Variable) {
            Variable var = (Variable) expressionItem;
            String rmName = getRMName(elementMap, var);
            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(elementMap, (ConstantExpression) expressionItem, parentExpressionItem));
        } else if (expressionItem instanceof FunctionalExpression) {
            FunctionalExpression fe = (FunctionalExpression) expressionItem;
            sb.append("(double)Math.")
                    .append(fe.getFunction().toString())
                    .append("(");
            String postfix = "";
            for (ExpressionItem feItem : fe.getItems()) {
                sb.append(postfix);
                sb.append(getArithmeticExpressionStr(elementMap, feItem, stats, expressionItem));
                postfix = ", ";
            }
            sb.append(")");
        } else {
            throw new RuntimeException(format("Unknown expression '%s'", expressionItem.getClass().getName()));
        }
        return sb.toString();
    }

    private static String getRMName(Map elementMap, Variable var) {
        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 && !isFunction(var.getAttribute())) {
                throw new RuntimeException(format("Archetype element not found for gtcode '%s'", var.getCode()));
            }
            if (aeVO != null) {
                rmName = aeVO.getType();
            }
        }
        return rmName;
    }


    /*
     * Parse for units of hr and convert value to milliseconds
     */
    private static String formatConstantValue(
            Map elementMap,
            ConstantExpression exp,
            ExpressionItem parentExpressionItem) {
        String value = exp.getValue();
        if (value.contains(",")) {
            String units = StringUtils.substringAfter(value, ",");
            if (isUcumTime(units)) {
                OperatorKind operatorKind = getOperatorKind(parentExpressionItem);
                if (operatorKind == null) {
                    throw new RuntimeException(format("Operator kind not defined in expression : %s", parentExpressionItem));
                }
                if (hasLeftVariableName(parentExpressionItem)) {
                    String temporalVariableName = getLeftVariableNameFromExpression(elementMap, parentExpressionItem);
                    value = format("DVUtil.calculateDuration(\"%s\",%s,\"%s\")", value, temporalVariableName, operatorKind.getSymbol());
                } else {
                    value = format("DVUtil.calculateDuration(\"%s\",\"%s\")", value, operatorKind.getSymbol());
                }
            } else {
                throw new IllegalArgumentException(format("Unknown time units in value '%s'", value));
            }
        } else if (exp instanceof MathConstant) {
            if (Constant.E.equals(((MathConstant) exp).getConstant())) {
                value = "(double) " + Math.E;
            }
        }
        return "(" + value + ")";
    }

    private static OperatorKind getOperatorKind(ExpressionItem parentExpressionItem) {
        if (parentExpressionItem instanceof BinaryExpression) {
            return ((BinaryExpression) parentExpressionItem).getOperator();
        } else {
            return null;
        }
    }

    private static boolean hasLeftVariableName(
            ExpressionItem parentExpressionItem) {
        return (parentExpressionItem instanceof BinaryExpression)
                && ((BinaryExpression) parentExpressionItem).getLeft() instanceof Variable;
    }

    private static String getLeftVariableNameFromExpression(
            Map elementMap,
            ExpressionItem parentExpressionItem) {
        if (parentExpressionItem instanceof BinaryExpression) {
            ExpressionItem left = ((BinaryExpression) parentExpressionItem).getLeft();
            if (left instanceof Variable) {
                return getLeftVariable(elementMap, (Variable) left);
            }
        }
        throw new RuntimeException(format("Invalid expression %s", parentExpressionItem));
    }

    private static String getLeftVariable(Map elementMap, Variable leftVariable) {
        String code = leftVariable.getCode();
        if (OpenEHRConst.CURRENT_DATE_TIME_ID.equals(code)) {
            return "$" + OpenEHRConst.CURRENT_DATE_TIME_ID;
        } else {
            String rmName = getRMName(elementMap, leftVariable);
            String dvClassName = DVDefSerializer.getDVClassName(rmName);
            String variableExp = "$" + code + ".getDataValue()";
            if (leftVariable.getAttribute() != null) {
                variableExp = "((" + dvClassName + ")$" + leftVariable.getCode()
                        + getDataValueMethod(leftVariable.getCode()) + ").get"
                        + capitalize(leftVariable.getAttribute()) + "()";
            }
            return variableExp;
        }
    }

    private static boolean isUcumTime(String ucumUnits) {
        return ucumUnits.equals("a")
                || ucumUnits.equals("mo")
                || ucumUnits.equals("wk")
                || ucumUnits.equals("d")
                || ucumUnits.equals("h")
                || ucumUnits.equals("min")
                || ucumUnits.equals("s")
                || ucumUnits.equals("S");
    }

    public static String getVariableWithAttributeStr(String rmName, Variable var) {
        LoggerFactory.getLogger(DVUtil.class).debug("Var.code: " + var.getCode() + ", attr: " + var.getAttribute());
        String ret = null;
        String dvClassName = null;
        if (rmName != null) {
            dvClassName = DVDefSerializer.getDVClassName(rmName);
        }
        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 {
                if (var.getAttribute() != null) {
                    //Attribute
                    ret = "((" + dvClassName + ")$" + var.getCode()
                            + getDataValueMethod(var.getCode()) + ").get"
                            + StringUtils.capitalize(var.getAttribute()) + "()";
                } else {
                    ret = "DVUtil.ucumToMilliseconds((" + dvClassName + ")$" + var.getCode()
                            + getDataValueMethod(var.getCode()) + ")";
                }
            }
        }
        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);
    }
}

/*
 *  ***** BEGIN LICENSE BLOCK *****
 *  Version: MPL 2.0/GPL 2.0/LGPL 2.1
 *
 *  The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/
 *
 *  Software distributed under the License is distributed on an 'AS IS' basis,
 *  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 *  for the specific language governing rights and limitations under the
 *  License.
 *
 *
 *  The Initial Developers of the Original Code are Iago Corbal and Rong Chen.
 *  Portions created by the Initial Developer are Copyright (C) 2012-2013
 *  the Initial Developer. All Rights Reserved.
 *
 *  Contributor(s):
 *
 * Software distributed under the License is distributed on an 'AS IS' basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 *  ***** END LICENSE BLOCK *****
 */




© 2015 - 2025 Weber Informatics LLC | Privacy Policy