![JAR search and dependency download from the Maven repository](/logo.png)
de.tsl2.nano.specification.rules.Rule Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tsl2.nano.specification Show documentation
Show all versions of tsl2.nano.specification Show documentation
TSL2 Framework Specification (Pools of descripted and runnable Actions and Rules, Generic Tree)
The newest version!
/*
* File: $HeadURL$
* Id : $Id$
*
* created by: Tom, Thomas Schneider
* created on: 30.11.2013
*
* Copyright: (c) Thomas Schneider 2013, all rights reserved
*/
package de.tsl2.nano.specification.rules;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.simpleframework.xml.core.Commit;
import de.tsl2.nano.core.ENV;
import de.tsl2.nano.core.log.LogFactory;
import de.tsl2.nano.specification.ParType;
import de.tsl2.nano.util.operation.NumericConditionOperator;
import de.tsl2.nano.util.operation.Operator;
/**
* rule engine using operators (see {@link Operator}) for numeric and boolean values. rules can reference other rules
* through using '§' + name.
*
* every rule defines parameters and an operation. the parameters will be checked against the arguments given on
* {@link #execute(Map)}. additionally, there may be constraints for value ranges. Example:
*
*
* rule = new Rule<BigDecimal>("test", "A ? (x1 + 1) : (x2 * 2)", MapUtil.asMap("A",
* ParType.BOOLEAN,
* "x1",
* ParType.NUMBER,
* "x2",
* ParType.NUMBER));
* rule.addConstraint("x1", new Constraint(BigDecimal.class, new BigDecimal(0), new BigDecimal(1)));
* BigDecimal r2 = rule.execute(MapUtil.asMap("A", false, "x1", new BigDecimal(1), "x2", new BigDecimal(2)));
*
* or
*
* Rule ruleWithImport = new Rule("test-import", "A ? 1 + §test : (x2 * 3)", MapUtil.asMap("A",
* Boolean.class,
* "x1",
* BigDecimal.class,
* "x2",
* BigDecimal.class));
*
*
*
*
*
* @author Tom, Thomas Schneider
* @version $Revision$
*/
public class Rule extends AbstractRule {
/** serialVersionUID */
private static final long serialVersionUID = 8557708958880364123L;
private static final Log LOG = LogFactory.getLog(Rule.class);
public static final String KEY_RESULT = Operator.KEY_RESULT;
transient NumericConditionOperator operator;
/**
* constructor only to be used by deserializing
*/
public Rule() {
}
/**
* constructor
*
* @param operation
* @param parameter
*/
public Rule(String name, String operation, LinkedHashMap parameter) {
super(name, operation, parameter);
}
/**
* executes the given rule, checking the given arguments.
* @param arguments rule input
* @return evaluation result
*/
@SuppressWarnings("unchecked")
@Override
public T run(Map arguments, Object... extArgs) {
if (!initialized) {
importSubRules();
}
if (parameter != null)
arguments = checkedArguments(arguments, ENV.get("app.mode.strict", false));
operator.reset();
//in generics it is not possible to cast from Map(String,?) to Map(CharSequence, ?)
Object a = arguments;
//calculate the numeric and boolean operations
LOG.debug("running rule <" + toString() + "> on arguments: " + a);
T result = (T) operator.eval((CharSequence)getOperation(), (Map) a);
checkConstraint(Operator.KEY_RESULT, result);
return result;
}
@Override
@Commit
protected void initDeserializing() {
super.initDeserializing();
//TODO: should we enable configuring the numeric operator through xml?
this.operator = new NumericConditionOperator();
importSubRules();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy