Contents > 9 Extending the Metrics and Rule Engine > 9.3 Rule Procedures

9.3 Rule Procedures

To illustrate the definition of custom rule procedures, consider the following scenario. We wish to implement a rule that checks adherence to a particular naming convention. The naming convention states that the names of certain elements (such as actions) must be constructed according to the pattern "<verb> <object>", for example "create account" or "update customer". Both verbs and objects must be chosen from a predefined list (maybe "create, read, update, delete, validate" for verbs, and "account, customer, credit, debit" for objects). The rule should check that the name of each action adheres to this pattern and uses only verbs and objects from the approved list.

To define the contents of the approved list of verbs and objects, we will use word lists (see Section 8.3.5 "Word lists"). The definition of the rule including the word lists could look something like this:

<wordlist name="VerbList">
	<entry word="create"/>
	<entry word="read"/>
	<entry word="update"/>
	<entry word="delete"/>
</wordlist>

<wordlist name="ObjectList">
	<entry word="bank account"/>
	<entry word="customer"/>
	<entry word="credit"/>
</wordlist>

<rule name="ActionNames" domain="action">
   <description>Checks that action names contain only approved verbs 
      and objects.</description>
   <verbobject 
      term="name" 
      condition="!(_verb onlist VerbList) or !(_object onlist ObjectList)" 
      value="'Illegal name: '+name" />
</rule>
Attribute term is a metric expression that yields the string to be checked. The attribute can be optional, when omitted, the procedure will check the name of the model element.

The procedure then has to extract the verb and object part from the result of the term expression, and pass the values as variables _verb and _object to the condition expression. If the expression evaluates to true, the procedure reports a violation, the value of the violation, as usual, given by the value expression.

Here is a possible implementation of such a rule procedure:

import com.sdmetrics.math.ExpressionNode;
import com.sdmetrics.metrics.*;
import com.sdmetrics.model.ModelElement;

01 public class RuleProcedureVerbObject extends RuleProcedure {

   @Override
02 public void checkRule(ModelElement element, Rule rule) throws SDMetricsException {

03    String name = element.getName();

04    ProcedureAttributes attributes = rule.getAttributes();
05    ExpressionNode term = attributes.getExpression("term");
06    Variables vars = new Variables(element);
07    if (term != null)
08       name = evalExpression(element, term, vars).toString();

09    int boundary = name.indexOf(' ');
10    if (boundary < 0) {
11       reportViolation(element, rule, "Element does not specify an object.");
12       return;
      }

13    String verb = name.substring(0, boundary);
14    String object = name.substring(boundary + 1);
15    vars.setVariable("_verb", verb);
16    vars.setVariable("_object", object);

17    ExpressionNode condition = attributes.getRequiredExpression("condition");
18    if (evalBooleanExpression(element, condition, vars)) {
19       Object value = getRuleValue(element, attributes, vars);
20       reportViolation(element, rule, value);
      }
   }
}
The example illustrates a number of new features of the metrics and rule engine API: To register the rule procedure with the rule engine, we deploy the class file of the procedure class in the "bin" folder of our SDMetrics installation (path com/acme/RuleProcedureVerbObject.class), and add the following definition to our metric definition file:
<ruleprocedure name="verbobject" 
	class="com.acme.RuleProcedureVerbObject" />
After that, we can define rules using our new rule procedure, such as rule "ActionNames" from above.