Reputation: 61695
We are going to be implementing a rules engine using Drools for a customer, and one of the requirements is to be able to say that a rule is associated with a particular legal requirement.
For instance, the law says that a driving licence can only be issued to someone 18 or over, so we have:
rule "Driving Licence: Age >= 18"
when
$applicant: Applicant(age < 18)
$application: Application()
then
$application.setValid(false);
end
or for the calculation of a tax total
rule "Tax: Top bracket"
when
$return: Return(income > 44000)
then
$application.setTopBracket(true);
end
or similar.
One solution would be to have the legal requirement in the name:
rule "Driving Licence: Age >= 18: Section 103 RTA 1988"
The question: what would be the best way of achieving this? Is the name the only way? Is there a way to add a custom attribute to a rule? If so, can it be mandatory? I could also use comments, but I would prefer to avoid that.
It would be nice if in the rule trace we could see the trace of these attributes as well, but that isn't vital.
Please note that I don't want to change the rule logic, I just want to be able to say 'This rule comes from this law'. The decision of the rule is not important. I do not wish to change the setValid setter.
Upvotes: 3
Views: 5972
Reputation: 983
You could use rule metadata for this. Metadata doesn't affect your rule, unless you want to, you can use it in the LHS or the RHS. You can also access metadata while debugging, for example you can print the metadata with AgendaFilter and see what rules are firing and what legal requirements they have.
If you want to force the metadata for each rule, you need to write the check up codes for that yourself.
@metadata_key( metadata_value1, metadata_value2, ... )
rule "Driving Licence: Age >= 18"
@LegalRequirement("Section 103 RTA 1988")
when
$applicant: Applicant(age < 18)
$application: Application()
then
$application.setValid(false);
end
Here is an example of the AgendaFilter. If you return false it will prevent the rule from firing. I'm just using it to print the legal requirement:
StatefulKnowledgeSession ksession= createKSession();
ksession.fireAllRules(new AgendaFilter() {
public boolean accept(Activation activation) {
Map<String, Object> metaData = activation.getRule().getMetaData();
if (metaData.containsKey("LegalRequirement")) {
System.out.println(metaData.get("LegalRequirement"));
}
return true;
}
});
Or if you want to use it in the RHS:
rule.getMetaData().get("LegalRequirement");
If you are using Guvnor to manage your rules you can also use the category setting. Category is a mandatory for each asset stored in Guvnor.
Upvotes: 10
Reputation: 12770
I agree with Guillaume Alvarez, but also keep in mind that (probably in your system) an application could be refused for several reasons, therefore you may have a method like:
application.addInvalidReason(SomeType)
This method may be called by several rules for the same application...
Upvotes: 0
Reputation: 5555
You could modify the method Application.setValid(false)
to take an other parameter, that would be the legal requirement. That way you could present it to your customer.
Upvotes: 1