0

Given a collection of BMSContract objects in memory of two or more, I need to match specific patterns using the BMSContract.status field. My rule should resolve to Success if in such collection exactly ONE and ONLY ONE BMSContract has a status of ACTIVE. Any other combination of objects and status codes should resolve to Fail. Again this rule is for a collection of 2 or more objects only and there could be any number of them: 2, 5, 10, 15 or more. There is a slightly different set of rules governing single BMSContract records. These rules are specific just to the multiple records scenarios such as these:

Case1 - Success
BMSContract(status=ACTIVE)
BMSContract(status=PENDING)
Reason:  only one Active in the collection

Case2 - Success
BMSContract(status=ACTIVE)
BMSContract(status=PENDING)
BMSContract(status=HOLD)
Reason: only one Active in the coll

Case3 - Success
BMSContract(status=ACTIVE)
BMSContract(status=PENDING)
BMSContract(status=HOLD)
BMSContract(status=CANCEL)
Reason:  only one Active in the coll

Case4 - Failure
BMSContract(status=ACTIVE)
BMSContract(status=ACTIVE)
Reason:  too many Active records in coll

Case5 - Failure
BMSContract(status=ACTIVE)
BMSContract(status=ACTIVE)
BMSContract(status=ACTIVE)
Reason:  too many Active records in coll

Case6 - Failure
BMSContract(status=ACTIVE)
BMSContract(status=ACTIVE)
BMSContract(status=ACTIVE)
BMSContract(status=ACTIVE)
BMSContract(status=ACTIVE)
Reason:  too many Active records in coll

Case7 - Failure
BMSContract(status=PENDING)
BMSContract(status=HOLD)
BMSContract(status=OTHER)
Reason:  No Active records in coll
JamesD
  • 679
  • 10
  • 36

1 Answers1

0

Given that you have a number of BMSContract facts, the following rules would be enough:

rule OK
when
  $ac: BMSContract( status == "ACTIVE" )
  not BMSContract( this != $ac, status == "ACTIVE" )
then
  // there is exactly one ACTIVE
end

rule not_OK_1
when
  not BMSContract( status == "ACTIVE" )
then
  // there is no ACTIVE
end

rule not_OK_2
when
  $ac: BMSContract( status == "ACTIVE" )
  exists BMSContract( this != $ac, status == "ACTIVE" )
then
  // there is more than one ACTIVE
end

Variants are possible and may be required if you need to identify the facts that cause trouble:

rule not_OK_2a
when
  $ac1: BMSContract( status == "ACTIVE" )
  $ac2: BMSContract( this != $ac, status == "ACTIVE" )
then
  // log and retract $ac2
end
laune
  • 31,114
  • 3
  • 29
  • 42
  • q1: not understanding this syntax: not BMSContract( this != $ac, status == "ACTIVE" ) q2: Should I assert BMSContract objects into working memory as individual objects or as a Collection? – JamesD Nov 10 '17 at 14:37
  • The CE `not` is syntax for the negated existential quantifier, ∄. -- If you do not insert all `BMSContract` objects as individual facts, matters are complicated as you'll have to have a container with a `List` and use `from` to expand the list for each pattern. I do not recommend doing this unless there are cogent reasons. – laune Nov 10 '17 at 19:29
  • I still don't get the meaning of : this != $ac. What does this != $ac mean? Does it mean this instance is not the same as the one bound to $ac variable? – JamesD Nov 10 '17 at 19:51
  • I'm sorry - I need to change my original question. I have more information now and the scenario is a bit different. – JamesD Nov 10 '17 at 19:55
  • Using ` this != $ac` avoids a match of the same fact for the second pattern. -- I still uphold that my set of rules detects all failures as given in your question. – laune Nov 11 '17 at 14:17
  • Thanks for that clarification. Makes sense. How can I assert how many instances of BMSContract object there are in working memory?! I'd like to use that as a predicate in some of my logic for individual BMSContract scenarios?! When BMSContract instance in memory == 1... – JamesD Nov 13 '17 at 02:30
  • Maybe like this: rule OK when $ac: BMSContract( status == "ACTIVE" ) not BMSContract( this != $ac ) then // there is exactly one and it's ACTIVE end – JamesD Nov 13 '17 at 02:32
  • I need to make an improvement to the rule not_OK_1 in your example. As it stands this rule doesn't take into account multiple records. For example, it traps and fails when single record scenarios contains "suspended" which by itself happens to be valid. This rule needs to say: when not BMSContract( status == "ACTIVE" ) AND there are multiple records.... How can I write that predicate? – JamesD Nov 18 '17 at 00:17