0

I have inherited some Drools code and am trying to understand exactly how it is working. The code in question should go through a number of dates from two different sources, and for one source find the earliest and the other source find the latest.

The code is:

when

    $flags: Properties()
    // these properties contain key/value pairs with dates (as Strings)

    $root: Map()
    Map.Entry( key == "someRequest", $someRequestValue : value) from $root.entrySet()
    $someRequestMap: Map() from $someRequestValue
    // this map contains some timestamps as Strings

$earliestTimestamp: String() from accumulate(
    $value : String(),
    init( String found = null; ),
    action( found = found == null? $value : ($value.compareTo(found) < 0? $value: found); ),
    result( found ) 
)
$latestTimestamp: String() from accumulate(
    $value : String(),
    init( String found = null; ),
    action( found = found == null? $value : ($value.compareTo(found) > 0? $value: found); ),
    result( found ) 
)

then
    log("earliestTimestamp: {}", $earliestTimestamp);

    String latestDate = (String) $flags.get($latestTimestamp);
    log("latestDate: {}", latestDate);
end

The $flags Properties are populated as so:

when
    $flags: Properties()
    $root: Map()
    Map.Entry( key == "someRequest", $someRequestValue : value) from $root.entrySet()
    $someRequestMap: Map() from $someRequestValue 
    Map.Entry( key == "timestamp", $timestampValue: value) from $someRequestMap.entrySet()
    Map.Entry( key == "data", $dataValue: value) from $someRequestMap.entrySet()
    $data: Map() from $dataValue
    Map.Entry( key == "simple", $simpleValue: value) from $data.entrySet()
    $simple: Map() from $simpleValue
    Map.Entry( key == "somedate", $somedateValue: value) from $simple.entrySet()
then
    $someRequestMap.remove("data");
    update($root);
    $flags.put($timestampValue, $somedateValue); 
    insert ($timestampValue);
end

And the JSON which is input to the rules is as so (with the timestamp strings):

{
 "someRequest": {
      "data": {
          "simple": {
            "somedate": "13-01-2016",
          }
    },
    "timestamp": "2016-01-01 12:34:56.789"
  }
}

I can see that it gets all the String facts available in working memory to get earliestTimestamp. I think that for latestTimestamp, since it is called in the RHS on $flags.get, it is actually finding all Strings in $flags. However if I insert log outputs inside the two accumulate action sections, all I see is the timestamp strings from working memory (I don't see the $flags strings).

I am comfortable enough using Drools but this bit of code has confused me in terms of how it works with the Properties.

Any info appreciated, thanks.

Neil
  • 413
  • 4
  • 22
  • You must have omitted some relevant piece(s) of code. What you say that this code should do ("dates from two different sources") is nowhere to be seen. Somwhere lots of String objects containing dates must be inserted; unless we see this, we don't know how this should work. Having them in WM at the same time/for the same rule will mix them unless from is used after `String()` in each `accumulate`. -- Also, extracting all Map.Entry to find one is strange. – laune Feb 13 '17 at 14:26
  • I've added some additional code extracts, hopefully this helps, thanks. Could you expand on the Map.Entry comment? It should just be picking out the map entry it requires each time, is there a more efficient way to do this? – Neil Feb 13 '17 at 15:44
  • In the code doing the population neither `$ruleRequestValue` nor `$rtpm` are bound although they are referenced. It is unclear why just property `data` is removed but the entire request and the other property `timestamp` should remain. Also, writing all of this procedural code - ultimately simple accesses to `somedate` and `timestamp` in unnecessarily complex LHS code - is rather far-fetched. -- So you'll have plenty of String facts with timestamp values in WM, but there's still nothing to indicate "two sources". – laune Feb 13 '17 at 16:18
  • You say that this code is working - I don't see how it can. I suggest that you throw this away, clarify the specs and what input there is and how it arrives, and start from scratch. – laune Feb 13 '17 at 16:19
  • Apologies, I've been tweaking the code extracts and missed some. The code essentially takes the "somedate" entries from the facts and stores them in Properties. The "timestamp" entries are just pulled through from the facts directly. The more I explain this code the more it seems sensible to do as you suggest (like I say this has been inherited and I'm not comfortable continuing with it). I was interested in how the accumulate functions were picking up Strings from the the Properties - assuming Properties contains Strings, does it match on them because it is being called on $flags? – Neil Feb 13 '17 at 16:59
  • 1
    The accumulates work on String objects in WM. If you need min and max computed from the same set, you can use the "new format" accumulate CE where you can compute several functions at the same time. The binding variable `$flags` has no influence on the accumulates in your rule #1. – laune Feb 13 '17 at 21:31
  • Thanks for the info, much appreciated. – Neil Feb 15 '17 at 09:14

0 Answers0