Project

General

Profile

Cruximplement » History » Version 44

Kaushal Alate, 13/10/2023 01:06 PM

1 4 Shuvam Misra
*(For a conceptual overview and design of Crux, see [[cruxdesign|this page]] if you haven't already.)*
2
3 35 Shuvam Misra
# Algorithms and data structures for the Crux BRE
4 1 Shuvam Misra
5
{{>toc}}
6 35 Shuvam Misra
7
This page documents the rules engine. It does not cover the flow engine.
8 1 Shuvam Misra
9
A rules engine implementation must include the following:
10
* **RULE SCHEMA**. A notation to specify the list of valid terms in a rule. This list will be separate for each class of entities. For instance, for items in inventory, the list of attributes may be:
11
  * Price
12
  * Full name
13
  * Age in stock
14
  * Quantity in inventory
15
16
    For vendors, the list could include:
17
  * Amount outstanding
18
  * Total value of business done  in the last financial year
19
20
* **RULE NOTATION**. A notation to specify the pattern and actions of a rule.
21
* **THE MATCHING ENGINE**. Something which will take an entity with all its attributes, apply each rule to it, and follow the trail of rules to come up with a list of actions which will emerge.
22
23
So, if these three can be designed and then implemented, the core of a rules engine or a flow engine can be built.
24
25 2 Shuvam Misra
## Representing the schema of patterns
26 1 Shuvam Misra
27
If using JSON, the schema of all valid patterns may be represented in structures of this form:
28
29
``` json
30
"patternschema": {
31
    "class": "inventoryitems",
32
    "attr": [{
33
        "name": "cat",
34
        "type": "enum",
35
        "vals": [ "textbook", "notebook", "stationery", "refbooks" ]
36
    },{
37
        "name": "mrp",
38
        "type": "float"
39
    },{
40
        "name": "fullname",
41
        "type": "str",
42
    },{
43
        "name": "ageinstock",
44
        "type": "int"
45
    },{
46
        "name": "inventoryqty",
47
        "type": "int"
48
    }]
49
}
50
```
51
52 41 Kaushal Alate
In this example, the object `patternschema` is the schema for one class of entities. This schema says that for rules which work on entities of class `inventoryitems`, there are five attributes available which may be used to make patterns. Each attribute has a type. Boolean, enum types, integers, floating point numbers, timestamps (`ts`) and strings are supported. The example above does not have any attribute of type `ts` or  `bool`.
53 1 Shuvam Misra
54
So, the full schema of the rules engine will be an array of `patternschema` blocks. Initial examples have discussed inventory items and vendors. The `patternschema` block above is for inventory items. If the schema of patterns for vendors needed to be specified, there would be a second `patternschema` with `“class”: “vendors”`
55
56 5 Shuvam Misra
While the fields in the example above are adequate from a purely functional point of view, it may be necessary to have some additional metadata to allow the building of a good UI which will allow users to manage these schema objects. So, an augmented data structure may look like this:
57
58
``` json
59
"patternschema": {
60
    "class": "inventoryitems",
61
    "attr": [{
62
        "name": "cat",
63
        "shortdesc": "Category of item",
64
        "longdesc": "Each item can belong to one of the following categories: textbooks, notebooks, stationery, or reference books.",
65
        "type": "enum",
66
        "vals": [ "textbook", "notebook", "stationery", "refbooks" ],
67
        "enumdesc": [ "Text books", "Notebooks", "Stationery and miscellaneous items", "Reference books, library books" ]
68
    },{
69
        "name": "mrp",
70
        "shortdesc": "Maximum retail price",
71
        "longdesc": "The maximum retail price of the item as declared by the manufacturer."
72
        "type": "float",
73
        "valmax": 20000,
74
        "valmin": 0
75
    },{
76
        "name": "fullname",
77
        "shortdesc": "Full name of item",
78
        "longdesc": "The full human-readable name of the item. Not unique, therefore sometimes confusing.",         
79
        "type": "str",
80
        "lenmax": 40,
81
        "lenmin": 5
82
    },{
83
        "name": "ageinstock",
84
        "shortdesc": "Age in stock, in days",
85
        "longdescr": "The age in days that the oldest sample of this item has been lying in stock",
86
        "type": "int",
87
        "valmax": 1000,
88
        "valmin": 1
89
    },{
90
        "name": "inventoryqty",
91
        "shortdesc": "Number of items in inventory",
92
        "longdescr": "How many of these items are currently present in the inventory",
93
        "type": "int",
94
        "valmax": 10000,
95
        "valmin": 0
96
    }]
97
}
98
```
99
100
Here, the `shortdesc` and `longdesc` are useful attributes of each attribute, for displaying labels and help text in any UI which is displayed to the human user who manages the rules for entities of this class. The `valmax`, `valmin`, `lenmax`, `lenmin`, allow the system to enforce some sanity checks on the patterns defined in any rules for this entity.
101
102 2 Shuvam Misra
## Representing the schema of actions
103 1 Shuvam Misra
104 42 Kaushal Alate
The schema of the action section of rules is simpler than patterns. Each rule's action section will contain a set of zero or more words, each denoting a task, and zero or more property assignments. There is no need for any type specification, etc.
105
* An example of a task word: `invitefordiwali`
106
* An example of a property assignment: `discount=7`
107 1 Shuvam Misra
108 42 Kaushal Alate
So, the schema of the actions will just specify the valid task names and the property names for assignments.
109 1 Shuvam Misra
110
``` json
111
"actionschema": {
112
    "class": "inventoryitems",
113 43 Kaushal Alate
    "tasks": [ "invitefordiwali", "allowretailsale", "assigntotrash" ],
114
    "properties": [ "discount", "shipby" ],
115 1 Shuvam Misra
}
116
```
117 43 Kaushal Alate
The schema of actions above indicates that there are three tasks, any or all of which may be present in any rule for this class of entities. There are two properties which may be assigned values by any rule.
118 1 Shuvam Misra
119
Putting the `patternschema` and `actionschema` blocks together, a better representation for the full schema for a class of entities will be:
120
121
``` json
122
"ruleschema": {
123
    "class": "inventoryitems",
124
    "patternschema": {
125
        "attr": [{
126
            "name": "cat",
127
            "type": "enum",
128
            "vals": [ "textbook", "notebook", "stationery", "refbooks" ]
129
        },{
130
            "name": "mrp",
131
            "type": "float"
132
        },{
133
            "name": "fullname",
134
            "type": "str",
135
        },{
136
            "name": "ageinstock",
137
            "type": "int"
138
        },{
139
            "name": "inventoryqty",
140
            "type": "int"
141
        }]
142
    }
143
    "actionschema": {
144 43 Kaushal Alate
        "tasks": [ "invitefordiwali", "allowretailsale", "assigntotrash" ],
145
        "properties": [ "discount", "shipby" ],
146 1 Shuvam Misra
    }
147
}
148
```
149
150
There will need to be one such `ruleschema` block for each class.
151
152 2 Shuvam Misra
## Representing a pattern
153 1 Shuvam Misra
154 6 Shuvam Misra
Below is an example of a pattern of a rule, which conforms to the schema example given above.
155
156 1 Shuvam Misra
``` json
157 44 Kaushal Alate
"rulepattern": [{
158
        "attrName": "cat",
159 1 Shuvam Misra
        "op": "eq",
160 44 Kaushal Alate
        "attrVal": "textbook"
161 1 Shuvam Misra
    },{
162 44 Kaushal Alate
        "attrName": "mrp",
163 1 Shuvam Misra
        "op": "ge",
164 44 Kaushal Alate
        "attrVal": 2000
165 1 Shuvam Misra
    },{
166 44 Kaushal Alate
        "attrName": "ageinstock",
167 1 Shuvam Misra
        "op": "ge",
168 44 Kaushal Alate
        "attrVal": 90
169 1 Shuvam Misra
    },{
170 44 Kaushal Alate
        "attrName": "invitefordiwali",
171 22 Shuvam Misra
        "op": "eq",
172 44 Kaushal Alate
        "attrVal": true
173
    }
174
}]
175 1 Shuvam Misra
```
176
177
If a rule has this pattern, it will match any entity which falls in the class `inventoryitems` which
178
* is of type textbook
179
* has MRP (max retail price) greater than INR 2000
180 25 Shuvam Misra
* has been in stock longer than 89 days 
181 44 Kaushal Alate
* one of the earlier rules matched against this entity has added the task `invitefordiwali` to the action set of this entity
182 22 Shuvam Misra
183
It is important to note that a pattern does not need to have just the attributes listed in `patternschema`. It may also include actions listed in the `ruleschema`. Each such action becomes an implicit attribute of type `bool` for this class.
184 1 Shuvam Misra
185
For attributes which are of type `int`, `float`, `str` and `ts`, the following comparison operators are available:
186
* Greater than or equal to: `ge`
187
* Greater than: `gt`
188
* Less than or equal to: `le`
189
* Less than: `lt`
190
* Equal to: `eq`
191
* Not equal to: `ne`
192
193
Collation sequences for strings are system dependent, and will need to be standardised so that they work reliably across programming languages and Unicode strings in any language. That's an implementation issue.
194
195 21 Shuvam Misra
For `enum` and `bool` types, only `eq` and `ne` are available.
196 1 Shuvam Misra
197 2 Shuvam Misra
## Representing an action
198 1 Shuvam Misra
199
A rule has a set of one or more actions. The following are all examples of the action section of rules:
200
* `invitefordiwali`
201
* `discount=7`
202
* `shipwithoutpo`
203
* `CALL=intlbiz`
204
205
The terms which identify actions, *e.g.* `invitefordiwali`, will automatically be converted to lower-case and stored in the system. Reserved attribute names like `CALL`, `RETURN`, `EXIT`, will always be in uppercase. For an attribute assignment, the value of the attribute will be everything after the first `=` character till the end of the string, thus supporting multi-word values, *e.g.*
206
* `reprimand=This cannot go on any longer`
207
208
The action portion of a rule can have zero or one occurrence of a `CALL` term, a `RETURN` term, and an `EXIT` term. If it contains both a `RETURN` and an `EXIT`, then the `RETURN` will be ignored.
209
210
The action portion of a rule will have the following structure, shown here as an example:
211
``` json
212
"ruleactions": {
213
    "actions": [ "christmassale", "vipsupport" ],
214
    "attribs": [ "shipby=fedex" ],
215
    "call": "internationalrules",
216
    "return": true,
217
    "exit": false
218
}
219
```
220
This example shows all five attributes of `ruleactions`, but in reality, some of the attributes will typically be missing from most of the rules.
221
222 2 Shuvam Misra
## An entire rule
223 1 Shuvam Misra
224
This is what an entire rule looks like:
225
226
``` json
227
"rule": {
228
    "class": "inventoryitems",
229
    "rulepattern": [{
230
        "attr": "cat",
231
        "op": "eq",
232
        "val": "textbook"
233
    },{
234
        "attr": "mrp",
235
        "op": "ge",
236
        "val": 5000
237
    }],
238
    "ruleactions": {
239
        "actions": [ "christmassale" ],
240
        "attribs": [ "shipby=fedex" ]
241
    }
242
}
243
```
244
245
This structure represents one rule. The rule applies to entities of class `inventoryitems`. It has a pattern section which tries to match two attributes and an action section which throws up one action and one assignment.
246
247
A rule has a version number, which is incremented whenever the rule is updated. This number is for internal logging and rule engine debugging.
248
249
An array of such structures is a set of rules, and will be traversed in the order in which the rules appear in the array. Named rulesets will be represented thus:
250
``` json
251
"ruleset": {
252 40 Shuvam Misra
    "ver": 5,
253 1 Shuvam Misra
    "class": "inventoryitems",
254
    "setname": "overseaspo",
255
    "rules": [{
256
        "rulepattern": {
257
            :
258
            :
259
        },
260
        "ruleactions": {
261
            :
262
            :
263
        }
264
    }, {
265
        "rulepattern": {
266
            :
267
            :
268
        },
269
        "ruleactions": {
270
            :
271
            :
272
        }
273
    }]
274
}
275
```
276
The example above shows a ruleset named `overseaspo` for class `inventoryitems` which has two rules. This ruleset may be invoked from any other rule with the action `CALL=overseaspo`.
277
278 2 Shuvam Misra
## The schema manager
279 1 Shuvam Misra
280 7 Shuvam Misra
The schema for each class of entities may be written by hand using a text editor. JSON or YAML files are easy to write. If the schema of one class has less than a dozen attributes, it may be short enough to edit or audit by hand. However, a tool to manage and maintain the schema eliminates typos and enforces various types of consistency, and a second-level implementation of a schema manager may also enforce authorisation policies.
281 1 Shuvam Misra
282
A schema manager will have the following features:
283
* It will allow the user to create new instances of `ruleschema`
284
* It will sharply restrict editing of, and prevent deletion of any `patternschema` block or `actionschema` block if there are rules defined in the rules engine for this class of entities. In other words, schema are editable only as long as there are no rules for the class. The only kind of editing it will permit for “live” schema are
285
  * the addition of additional attributes in a `patternschema` or
286
  * additional attributes, action names or tags in an `actionschema`.
287
* It will ensure that there is no scope for typos when defining the schema.
288
289 3 Shuvam Misra
## The rule manager
290 1 Shuvam Misra
291
The rule manager will allow a user to manage rules. Core functionality:
292
* It will provide a user interface to let the user edit rules.
293
* It will check each rule against the schema for the class, and will not give the user the opportunity to define any rule inconsistent with the schema.
294
* It will allow the user to move a rule up or down in the sequence, since ordering is important.
295
* If a rule is being defined with a `CALL` action, then the rule manager will ensure that a ruleset with that target name exists.
296
* Most important: it will provide a testing facility by which sample entities may be submitted to the rule engine for testing, and the rule manager will display a full trace showing which rules were attempted to match, which rules actually matched, and how the result set of actions, attributes, *etc* grew with each step. This feature will be provided without having to save the rule changes.
297
* Finally, when the editing session is complete and all rulesets need to be saved, it will perform a detailed cross-validation of all rules across each other to ensure consistency. If there is any inconsistency, it will give readable explanations of the problems and not permit saving of the updates.
298
299 2 Shuvam Misra
## The matching engine
300 1 Shuvam Misra
301
The matching engine has a one-line job. It will take a full set of attributes of one entity, apply all the rules which apply to its class, and return with the list of actions, attributes, *etc* from all the matching rules.
302
303 11 Shuvam Misra
The operation of the engine, in a highly simplified notation, is:
304
```
305
for each rule in the ruleset do
306
    match the pattern of the rule with the entity
307
    if the pattern matches, then
308
        collect the actions from the rule into the actionset
309
    endif
310
endfor
311
```
312 1 Shuvam Misra
313 2 Shuvam Misra
### Matching one rule's pattern
314 1 Shuvam Misra
315 18 Shuvam Misra
The algorithm for the matching of one rule's pattern is shown below. Here, it is assumed that the object being matched is in `entity` and pattern of the rule being matched is in `rulepattern`. It is assumed that the matching engine  may have proceeded some distance in its matching process, and may have collected zero or more actions in its `actionset`.
316 1 Shuvam Misra
```
317
func matchOnePattern()
318 18 Shuvam Misra
    input parameters: entity, rulepattern, actionset
319 1 Shuvam Misra
    returns patternmatch: boolean
320
321 16 Shuvam Misra
#
322
# In this loop we iterate through terms from our pattern array
323
# one by one
324 1 Shuvam Misra
#
325
for patternterm in rulepattern do
326 18 Shuvam Misra
    #
327
    # We get into a loop, stepping through the attributes of this
328
    # entity to pull out the value of the attribute
329
    # we will now be matching against the term we have selected
330
    # for this iteration of the outer loop, i.e. patternterm
331
    #
332 19 Shuvam Misra
    entitytermval = null
333 18 Shuvam Misra
    for entityoneterm in entity.attrs do
334
        if entityoneterm.attr == patternterm.attr then
335
            entitytermval = entityoneterm.val
336
        endif
337 1 Shuvam Misra
    endfor
338 19 Shuvam Misra
339
    if entitytermval == null then
340
        #
341
        # We reach here if none of the attributes in the entity
342
        # has a name matching the term in the pattern array. This
343
        # can only mean one thing: this is a pattern clause which
344 26 Shuvam Misra
        # will match a tag with which this entity has been tagged.
345
        # A tag is an action clause which has already been collected
346
        # against this entity from matching a previous rule.
347 19 Shuvam Misra
        #
348
        # So we will now cycle through the action clauses in the
349
        # actionset to see if any of those matches this patternterm.
350
        #
351
        for oneactionclause in actionset.actions do
352
            if oneactionclause == patternterm.attr then
353
                #
354
                # Bingo! We have found an action clause which matches
355
                # the name of an entry in the pattern array.
356
                #
357
                entitytermval = "true"
358 18 Shuvam Misra
            endif
359 19 Shuvam Misra
        endfor
360 18 Shuvam Misra
    endif
361
362 19 Shuvam Misra
    if entitytermval == null then
363
        #
364
        # If we reach here, it means that we have a term of the entity which
365
        # is not listed in the pattern at all. Every entity has all the
366
        # attributes listed against its class in the schema, but rule patterns
367
        # may have just one or two terms, so it's likely that many of the
368
        # attributes of an entity may not match any term in the pattern array.
369
        #
370
        # In that case we just loop to the next term in the pattern array.
371
        #
372
        continue
373
    endif
374
375 1 Shuvam Misra
    case patternterm.op in
376
    "eq":
377
        if entitytermval != patternterm.val then
378
            return false
379
        endif
380
    "ne":
381
        if entitytermval == patternterm.val then
382
            return false
383
        endif
384
    endcase
385
    if patternterm.type in [ "int", "float", "ts", "str" ] then
386
        case patternterm.op in
387
        "le":
388
            if entitytermval > patternterm.val then
389
                return false
390
            endif
391
        "lt":
392
            if entitytermval >= patternterm.val then
393
                return false
394
            endif
395
        "ge":
396
            if entitytermval < patternterm.val then
397
                return false
398
            endif
399
        "gt":
400
            if entitytermval <= patternterm.val then
401
                return false
402
            endif
403
        default:
404
            log error with priority = CRITICAL: "system inconsistency with BRE rule terms"
405
        endcase
406
    endif
407
endfor
408
409
return true
410 2 Shuvam Misra
```
411 1 Shuvam Misra
412 39 Shuvam Misra
Note how the algorithm cycles through the `actionset` of the entity, trying to see of any of the actions in `actionset` matches the `patternterm. This aspect of the matching algorithm has been discussed in [[Cruxdesign#Tags|the explanation of the idea of actions as tags]].
413
414 1 Shuvam Misra
### Collecting the actions from one rule
415
416
If the pattern for one rule matches the entity being processed, then the actions of that rule will need to be added to the result set for that entity. Here we assume that the result of the action-collection function will return an object of the following structure. This object will be passed as input to the action-collecting function, and a (possibly extended) object will be returned, after merging the input object with the action terms from the rule just matched. The object structure will be:
417
``` json
418
"actionset": {
419
    "actions": [ "dodiscount", "yearendsale" ],
420
    "attribs": [ "shipby=fedex" ],
421
    "call": "overseaspo",
422
    "return": true,
423
    "exit": false
424 8 Shuvam Misra
}
425 1 Shuvam Misra
```
426
These five attributes will always be present in the object. The `actions` and `attribs` attributes will carry an array of strings, which will be a union set of all the action terms and attribute assignments collected from rules matched so far. The `call` attribute will either be a zero-length string (signifying that no ruleset needs to be called after this rule returns) or will carry the name of one ruleset to call after the current rule. The `return` and `exit` attributes will carry boolean values.
427
428
Performing a set union of action names is straightforward. Performing a set union of attribute assignments requires choosing one value of an attribute, if there was already the same attribute in the `actionset` and the current rule's actions also assigns a value to that attribute. In that case, the old value of the attribute will be overwritten by the new value.
429
430
```
431
function collectActions()
432
input parameters: actionset, ruleactions
433
    returns actionset
434
435
actionset.actions = actionset.actions UNION ruleactions.actions
436
actionset.attribs = actionset.attribs UNION ruleactions.attribs
437
438
actionset.call = ""
439
actionset.return = false
440
actionset.exit = false
441
if ruleactions.call is defined, then
442
    actionset.call = ruleactions.call
443
endif
444
if ruleactions.return is defined, then
445
    actionset.return = true
446
endif
447
if ruleactions.exit is defined,  then
448 14 Shuvam Misra
    actionset.exit = true
449
endif
450 1 Shuvam Misra
451
return actionset
452
```
453
454 13 Shuvam Misra
The matching engine needs to look at what has emerged from `collectActions()` and then take action. The flow of the matching engine will change based on the values of the `call`, `return` and `exit` attributes.
455
456 1 Shuvam Misra
### Representing one entity
457 14 Shuvam Misra
458 1 Shuvam Misra
The matching engine matches all the rules of a ruleset against one instance of a class, like one instance of `vendor` or `inventoryitem`. How do we represent this object instance, when the type and the fields are all dynamically determined at runtime and varies from invocation to invocation? Here is one example:
459
``` json
460
"inputentity": {
461 14 Shuvam Misra
    "class": "inventoryitems",
462
    "attribs": [{
463
        "name": "cat",
464
        "val": "refbook"
465
    },{
466
        "name": "mrp",
467
        "val": "1350"
468
    },{
469
        "name": "fullname",
470
        "val": "Advanced Level Physics, 2/ed"
471
    },{
472
        "name": "ageinstock",
473
        "val": "20"
474
    },{
475
        "name": "inventoryqty",
476 1 Shuvam Misra
        "val": "540"
477
    }]
478 14 Shuvam Misra
}
479 1 Shuvam Misra
```
480 14 Shuvam Misra
As this example highlights, all the values are supplied of type string, so that they may be converted from strings to their respective types later. This allows the data structure for specifying an object instance to be strongly typed and still allow attributes of all types to be captured. One more point illustrated is that **all attributes in the `patternschema` of the class must be present** in each object instance of that class.
481
482 1 Shuvam Misra
This is the way the entity will be submitted to the matching engine for processing.
483 13 Shuvam Misra
484 27 Shuvam Misra
### `doMatch()`: the matching function
485 13 Shuvam Misra
486 14 Shuvam Misra
This engine will go through rules one after another, and for each rule, it will call `matchOnePattern()`. If `matchOnePattern()` returns `true`, it will call `collectActions()`. And then it will inspect the result obtained from `collectActions()` and decide what to do next.
487
488
This engine will be implemented by the `getRules()` function, which will occasionally call itself recursively. It will be called with three parameters:
489
* an `inputentity`, which will be matched against the ruleset
490 1 Shuvam Misra
* a `ruleset` which will be traversed by the engine
491 14 Shuvam Misra
* an `actionset`, which collects the result of the action matching
492 1 Shuvam Misra
493
The pseudocode has been written with the assumption that parameters are all pass-by-value.
494
495
So, the `doMatch()` engine will work in the following way:
496 14 Shuvam Misra
```
497 1 Shuvam Misra
function doMatch()
498
input parameters: inputentity, ruleset, actionset
499 14 Shuvam Misra
    returns actionset
500
501
for each onerule in ruleset do
502 23 Shuvam Misra
    if matchOnePattern(inputentity, onerule.pattern, actionset) == true then
503 14 Shuvam Misra
        actionset = collectActions(actionset, onerule.actions)
504
        #
505
        # now check if the actions just collected includes an EXIT clause
506
        #
507
        if actionset.exit == true then
508
            return actionset
509
        endif
510
        #
511
        # If there was no EXIT clause, check if there was a RETURN clause
512
        #
513
        if actionset.return == true then
514
            actionset.return = false
515
            return actionset
516
        endif
517
        #
518
        # If there was no EXIT or RETURN, check if there was a CALL clause
519
        #
520 15 Shuvam Misra
        if actionset.call is not null then
521
            settocall = actionset.call
522
            if settocall.class != inputentity.class then
523
                log error with priority = CRITICAL:
524 14 Shuvam Misra
                       "system inconsistency with BRE rule terms, attempting to call ", settocall, " from ", ruleset, "!"
525
            endif
526
            actionset.call = null
527
            doMatch(inputentity, settocall, actionset)
528
            #
529
            # If the called ruleset has set EXIT to true, then we too need to
530
            # exit, and our caller too needs to exit, ad infinitum
531
            #
532
            if actionset.exit == true then
533
                return actionset
534
            endif
535
        endif
536
    endif
537
    #
538
    # We come here because we've done one rule and we've neither been thrown
539
    # out by an EXIT nor a RETURN clause. So we now loop to the next rule in
540
    # our ruleset.
541 13 Shuvam Misra
    #
542 14 Shuvam Misra
endfor
543 10 Shuvam Misra
544 14 Shuvam Misra
return actionset
545
```
546 1 Shuvam Misra
547 24 Shuvam Misra
This matching engine will be able to traverse all rulesets, make "subroutine calls" from one ruleset to another, and finally come up with a consolidated `actionset`.
548
549
The outermost calling code which calls the outermost layer of `doMatch()` for a given entity will initialise an empty `actionset` and pass it in. After all the ruleset traversals, `doMatch()` will return with a loaded `actionset`, which will then be returned to the client of the BRE.
550 1 Shuvam Misra
551 36 Shuvam Misra
## Operations supported by the BRE
552 1 Shuvam Misra
553 29 Shuvam Misra
The BRE must support the following set of operations:
554 32 Shuvam Misra
* Schema management:
555
  * `schemaAdd()`: add a new rule schema, for a new class
556
  * `schemaUpdate()`: update an existing schema
557
  * `schemaDelete()`: delete an existing schema
558
  * `schemaList()`: list all the schema for all classes
559
  * `schemaGet()`: get the full schema for one class, given the class name
560
* Ruleset management:
561
  * `rulesetAdd()`: add a new ruleset for a class, with one or more rules
562
  * `rulesetUpdate()`: update an existing ruleset
563
  * `rulesetDelete()`: delete a ruleset
564
  * `rulesetList()`: list all rulesets for a class
565
  * `rulesetGet()`: get the full ruleset, given the class name and the ruleset name
566
* Query the BRE and get the list of actions and attributes for an entity:
567 38 Shuvam Misra
  * `getBR()`: submit an entity and pull out the final set of actions and attributes. This call will fail unless the `inputentity` carries all the attributes listed in the schema of its class.
568 32 Shuvam Misra
  * `getAttrSet()`: take a class name, pull out from the `patternschema` all the attributes listed against that class, with full details. This is useful to let the caller know what attributes are to be specified when calling `doMatch()`.
569 33 Shuvam Misra
* Rule engine management:
570
  * `setConfig()`: set one or more global configuration parameters of the engine
571
  * `getConfig()`: get values of one or more global config parameters of the engine
572
  * `setAuth()`: set authorization rules to allow access to the engine
573
  * `getAuth()`: get authorization rules which control access to the engine
574
  * `shutdown()`: shut down the engine
575 36 Shuvam Misra
  * `sysReset()`: the equivalent of a factory reset. All configuration reverts to that which is present in a fresh install, all currently active processing threads are aborted and all schema, rulesets and other information is lost.
576 37 Shuvam Misra
577
The actual API specs will be on [[cruxapi|a separate page]], but the list of operations have been listed here in the typical syntax of API calls just to indicate the operations which the BRE will support. Only when we look at a complete list of operations do we see the entire scope of this system.