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

org.openl.rules.dt.DecisionTableInvoker Maven / Gradle / Ivy

package org.openl.rules.dt;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openl.base.INamedThing;
import org.openl.binding.MethodUtil;
import org.openl.domain.IIntIterator;
import org.openl.exception.OpenLRuntimeException;
import org.openl.rules.dt.algorithm.FailOnMissException;
import org.openl.rules.dt.element.IAction;
import org.openl.rules.dt.trace.DecisionTableTraceObject;
import org.openl.rules.method.RulesMethodInvoker;
import org.openl.vm.IRuntimeEnv;
import org.openl.vm.trace.Tracer;

/**
 * Invoker for {@link DecisionTable}.
 * 
 * @author DLiauchuk
 *
 */
public class DecisionTableInvoker extends RulesMethodInvoker {
    
    private final Log LOG = LogFactory.getLog(DecisionTableInvoker.class);
    
    public DecisionTableInvoker(DecisionTable decisionTable) {
        super(decisionTable);
    }
    
    @Override
    public DecisionTable getInvokableMethod() {    
        return (DecisionTable)super.getInvokableMethod();
    }
    
    public boolean canInvoke() {
        return getInvokableMethod().getAlgorithm() != null;
    }
    
    private Object invokeOptimized(Object target, Object[] params, IRuntimeEnv env) {

        IIntIterator rules = getInvokableMethod().getAlgorithm().checkedRules(target, params, env);

        Object returnValue = null;
        boolean atLeastOneRuleFired = false;

        while (rules.hasNext()) {
            atLeastOneRuleFired = true;
            int ruleN = rules.nextInt();

            returnValue = getReturn(target, params, env, ruleN);
            if (returnValue != null) {
                return returnValue;
            }
        }

        if (!atLeastOneRuleFired && getInvokableMethod().shouldFailOnMiss()) {

            String method = MethodUtil.printMethodWithParameterValues(getInvokableMethod().getMethod(), params, 
                INamedThing.REGULAR);
            String message = String.format("%s failed to match any rule condition", method);

            throw new FailOnMissException(message, getInvokableMethod(), params);
        }

        return returnValue;
    }
    
    private Object invokeTracedOptimized(Object target, Object[] params, IRuntimeEnv env) {        
        Tracer tracer = Tracer.getTracer();
        
        if (tracer == null) {
            return invokeOptimized(target, params, env);
        }

        Object returnValue = null;

        DecisionTableTraceObject traceObject = (DecisionTableTraceObject)getTraceObject(params);
        tracer.push(traceObject);

        try {
            IIntIterator rules = getInvokableMethod().getAlgorithm().checkedRules(target, params, env);

            while (rules.hasNext()) {

                int ruleN = rules.nextInt();

                try {
                    tracer.push(traceObject.traceRule(ruleN));

                    returnValue = getReturn(target, params, env, ruleN);
                    if (returnValue != null) {
                        traceObject.setResult(returnValue);
                        return returnValue;
                    }
                } finally {
                    tracer.pop();
                }
            }
        } catch (RuntimeException e) {
            addErrorToTrace(traceObject, e);
        } finally {
            tracer.pop();
        }

        return returnValue;
    }

	protected Object getReturn(Object target, Object[] params, IRuntimeEnv env, int ruleN) {
		Object returnValue = null;
		for (int j = 0; j < getInvokableMethod().getActionRows().length; j++) {
			IAction action = getInvokableMethod().getActionRows()[j];
			
		    Object actionResult = action.executeAction(ruleN, target, params, env);

		    if (action.isReturnAction() && returnValue == null && (actionResult != null || (action.getParamValues()!= null
		                    && action.getParamValues()[ruleN] != null))) {
		        returnValue = actionResult;
		    }
		}
		return returnValue;
	}
    
    private void addErrorToTrace(DecisionTableTraceObject traceObject, Throwable e) {
        traceObject.setError(e);
        LOG.error("Error when tracing DT rule", e);
        throw new OpenLRuntimeException(e);
    }
    
    public Object invokeTraced(Object target, Object[] params, IRuntimeEnv env) {
        return invokeTracedOptimized(target, params, env);
    }
    
    public Object invokeSimple(Object target, Object[] params, IRuntimeEnv env) {
        return invokeOptimized(target, params, env);
    }    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy