In this blog I sketch a solution for comparing BRFplus rule systems. I’ll discuss the use case and I would be interested in your feedback. Also I would like to know whether other people are working on the same topic and would like to exchange source code. Maybe this could lead to the first open source project in the area of BRFplus.
At first I think that comparison of objects like different rule systems is a value in itself because the concept of equality resp. inequality is one of most profound ones I know in philosophy and mathematics. But there are also more business cases:
Let us look at the first described scenario. I develop rule systems that have be to compliant to legislation and shipped to different organizations as applications of storage type system. These implementations are mostly stable due to compliance reasons and there one is only allowed to change them minimally and only in certain parts. Usually business experts use my rule systems as template and copy and alter it. Later the comparison is useful to control what has been changed:
So please let me summarize: comparison of different rule systems can be part of a usual maintenance and evolution process. It becomes necessary if you have a couple of organizations that have rule systems that are quite similar and evolved from the same template of decision logic. But there are other use cases when comparison of decision logic is useful.
Comparing two rule systems is difficult. BRFplus has only functions for comparing two rule set versions. The transaction FDT_HELPERS contains a report that checks whether two versions are identical. This is useful if you want to check whether a transport was (successfully) imported into a system. But it is not that useful for our purposes.
So we need to develop a solution by ourselves. The challenge is that BRFplus does have an object oriented API but provides no simple textual representation of the rules. But there are more problems: we have to define when two BRFplus artifacts are identical:
This shows the following: the comparison of two BRFplus applications is no trivial task and depends on the scenario i.e. the way that a rule system is copied and changed when working with a template. So I came to the conclusion that it would be useful to have a library with different utility functions.
After some experiments with the BRFplus API it became clear that this is not the right tool for comparisons. I also learned the especially the structure of the rules is very complex and they are hard to compare. Moreover I decided that a need a flexible toolset that would allow different kinds of comparisons.
My solution uses the XML representation of an BRFplus application. This representation is far from being readable. When you look at the structure of an XML document you will see that it contains on different artifacts which can be seen in the picture below. The most important entity is the expression which are grouped as elements FDTNS:EXPRESSION and are identified using IDs. More complex objects like conditions of rules refer to expressions by their IDs.
So f.e. a rule consists of conditions which are in fact expressions. In the XML representation the ID is stored and the expression with this ID is stored somewhere else in the XML document.
If you want to compare two BRFplus entities (f.e. two rules) one approach is to replace each occurrence of its expressions (think of a condition defined by its ID) with the content of the corresponding XML element which is stored in another part of the XML representation. If you do this in recursive way you will “expand” the BRFplus entity to a tree containing all relevant in expressions. This can be done easily using an iteration of the following XSL transformation which can be performed using the CALL TRANSFORMATION command in ABAP:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:FDTNS="http://sap.com/fdt/transport">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="FDTNS:RULES/FDTNS:item/FDTNS:RULE_ID |
FDTNS:EXPRESSION_ID |
FDTNS:CONDITION |
/FDTNS:FDT/FDTNS:RULESET/FDTNS:COND_RANGE/FDTNS:PARAMETER_ID">
<xsl:variable name="id" select="string(.)"/>
<xsl:choose>
<xsl:when test="count(/FDTNS:FDT/FDTNS:EXPRESSION[FDTNS:ADMIN_DATA/FDTNS:ID/text()=$id])>0">
<xsl:copy-of select="/FDTNS:FDT/FDTNS:EXPRESSION[FDTNS:ADMIN_DATA/FDTNS:ID/text()=$id]"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="node() | @*"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:transform>
If you have now a rule that is copied from another rule and both are using the same data elements then you compare them using a simple string compare. But before you have to remove the administration data since timestamps, change user and so will be always different. This can be done using the following transformation:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:FDTNS="http://sap.com/fdt/transport">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="FDTNS:ADMIN_DATA"/> <!-- Don't copy this element -->
</xsl:transform>
Another important operation for the above mentioned string comparison is the extraction. This can be performed also in XML. Here I show how to extract a certain rule in a rule set using XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:FDTNS="http://sap.com/fdt/transport">
<xsl:param name="POSITION"/>
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy-of
select="/FDTNS:RULESET/FDTNS:RULES/FDTNS:item[string(FDTNS:POSITION)=string($POSITION)]"/>
</xsl:template>
</xsl:transform>
Using those transformations you can “expand” two applications, remove administration data, extract parts and compare them using string comparison.
And this is what I implemented and tested successfully.
I discussed some use cases for rule system comparison and described the main ideas of my implementation. Now I have following questions for the BRFplus community:
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
8 | |
7 | |
5 | |
4 | |
4 | |
4 | |
4 | |
3 | |
3 | |
3 |