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

fr.ird.observe.dto.referential.FormulaHelper Maven / Gradle / Ivy

There is a newer version: 4.34
Show newest version
package fr.ird.observe.dto.referential;

/*-
 * #%L
 * ObServe Toolkit :: Common Dto
 * %%
 * Copyright (C) 2017 - 2020 IRD, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nuiton.util.NumberUtil;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created on 05/11/16.
 *
 * @author Tony Chemit - [email protected]
 * @since 6.0
 */
public class FormulaHelper {

    /** Logger */
    private static final Logger log = LogManager.getLogger(FormulaHelper.class);

    private static final Pattern COEFFICIENTS_PATTERN = Pattern.compile("(.+)=(.+)");

    /** variable weight à utiliser dans la relation taille */
    public static final String VARIABLE_WEIGHT = "P";

    /** variable taille à utiliser dans la relation weight */
    public static final String VARIABLE_LENGTH = "L";

    private static final String VARIABLE_X = "x";
    public static final String VARIABLE_INPUT = "I";

    public static final String VARIABLE_OUTPUT = "O";

    public static final String COEFFICIENT_A = "a";

    public static final String COEFFICIENT_B = "b";

    /** moteur d'évaluation d'expression */
    private static ScriptEngine scriptEngine;


    private static ScriptEngine getScriptEngine() {
        if (scriptEngine == null) {
            ScriptEngineManager factory = new ScriptEngineManager();

            scriptEngine = factory.getEngineByExtension("js");
        }
        return scriptEngine;
    }

    public static Map getCoefficientValues(WithFormula parametrage) {

        Map result = new TreeMap<>();
        String coefficients = parametrage.getCoefficients();
        if (coefficients != null) {
            for (String coefficientDef : coefficients.split(":")) {
                Matcher matcher = COEFFICIENTS_PATTERN.matcher(coefficientDef.trim());
                if (log.isDebugEnabled()) {
                    log.debug("constant to test = " + coefficientDef);
                }
                if (matcher.matches()) {

                    String key = matcher.group(1);
                    String val = matcher.group(2);
                    try {
                        Double d = Double.valueOf(val);
                        result.put(key, d);
                        if (log.isDebugEnabled()) {
                            log.debug("detects coefficient " + key + '=' + val);
                        }
                    } catch (NumberFormatException e) {
                        // pas pu recupere le count...
                        if (log.isWarnEnabled()) {
                            log.warn("could not parse double " + val + " for coefficient " + key);
                        }
                    }
                }
            }
        }
        return result;
    }

    public static boolean validateRelation(WithFormula parametrage, String relation, String variable) {
        boolean result = false;
        if (!StringUtils.isEmpty(relation)) {

            Map coeffs = parametrage.getCoefficientValues();

            ScriptEngine engine = getScriptEngine();
            Bindings bindings = engine.createBindings();
            addBindings(coeffs, bindings, variable, 1);

            try {
                engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
                Double o = (Double) engine.eval("parseFloat(" + relation + ")");
                if (log.isDebugEnabled()) {
                    log.debug("evaluation ok : " + relation + " (" + variable + "=1) = " + o);
                }
                result = true;
            } catch (Exception e) {
                if (log.isDebugEnabled()) {
                    log.debug("evaluation ko : " + relation + ", reason : " + e.getMessage());
                }
            }
        }
        return result;
    }

    public static boolean validateObjectMaterialValidation(String relation, Object value) {
        boolean result = false;
        if (!StringUtils.isEmpty(relation)) {

            ScriptEngine engine = getScriptEngine();
            Bindings bindings = engine.createBindings();
            bindings.put(FormulaHelper.VARIABLE_X, value);

            try {
                engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
                Boolean o = (Boolean) engine.eval(relation);
                if (log.isDebugEnabled()) {
                    log.debug(String.format("evaluation ok : %s (%s=%s) = %s", relation, FormulaHelper.VARIABLE_X, value, o));
                }
                result = o != null && o;
            } catch (Exception e) {
                if (log.isDebugEnabled()) {
                    log.debug("evaluation ko : " + relation + ", reason : " + e.getMessage());
                }
            }
        }
        return result;
    }

    public static boolean validateObjectMaterialValidationSyntax(String relation, Object value) {
        if (!StringUtils.isEmpty(relation)) {
            ScriptEngine engine = getScriptEngine();
            Bindings bindings = engine.createBindings();
            bindings.put(FormulaHelper.VARIABLE_X, value);
            try {
                engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
                Boolean o = (Boolean) engine.eval(relation);
                log.debug(String.format("evaluation ok : %s (%s=%s) = %s", relation, FormulaHelper.VARIABLE_X, value, o));
                return true;
            } catch (Exception e) {
                log.debug(String.format("evaluation ko : %s, reason : %s", relation, e.getMessage()));
                return false;
            }
        }
        return false;
    }

    public static Float computeValue(WithFormula parametrage, String formula, String coefficientName, String variableName, float data) {
        if (coefficientName != null) {
            Double b = parametrage.getCoefficientValue(coefficientName);
            if (b == 0) {

                // ce cas limite ne permet pas de calculer la taille a partir du weight
                return null;
            }
        }
        Float o = computeValue(parametrage, formula, variableName, data);

        if (o != null) {
            o = NumberUtil.roundOneDigit(o);
        }
        return o;
    }

    private static Float computeValue(WithFormula parametrage, String relation, String variable, float taille) {
        Map coeffs = parametrage.getCoefficientValues();
        ScriptEngine engine = getScriptEngine();
        Bindings bindings = engine.createBindings();
        addBindings(coeffs, bindings, variable, taille);

        engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
        Double o = null;
        try {
            o = (Double) engine.eval("parseFloat(" + relation + ")");
        } catch (ScriptException e) {
            if (log.isErrorEnabled()) {
                log.error("Could not compute value from " + relation);
            }
        }
        return o == null ? null : o.floatValue();
    }

    private static void addBindings(Map coeffs, Bindings bindings, String variable, float taille) {
        for (Map.Entry entry : coeffs.entrySet()) {
            String key = entry.getKey();
            Double value = entry.getValue();
            bindings.put(key, value);

            if (log.isDebugEnabled()) {
                log.debug("add constant " + key + '=' + value);
            }
        }
        bindings.put(variable, taille);
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy