ABAP to ABAP Transformations
ABAP to ABAP transformations are quite easy. As you will surely know converting from an ABAP source means that the transformation works on a canonical XML representation of the given ABAP data. Let me present you small example of the canonical representation an initial BAPIRET2 structure:
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0"> <asx:values> <INPUT> <BAPIRET2> <TYPE/> <ID/> <NUMBER>000</NUMBER> <MESSAGE/> <LOG_NO/> <LOG_MSG_NO>000000</LOG_MSG_NO> <MESSAGE_V1/> <MESSAGE_V2/> <MESSAGE_V3/> <MESSAGE_V4/> <PARAMETER/> <ROW>0</ROW> <FIELD/> <SYSTEM/> </BAPIRET2> </INPUT> </asx:values> </asx:abap>
If the target of an XSL transformation are ABAP data, the transformation has to create an XML document that corresponds to the canonical structure of the target data specified by the RESULT parameter of CALL TRANSFORMATION. So in an ABAP to ABAP transformation we work on serialized ABAP data and have to create serialized ABAP data.
In the following I present a quite simple application of such a transformation: given two internal tables we want to check the foreign key relationship of the CARRID data element. That means for each entry of the SCARR internal table we check whether there is exactly one entry of the SFLIGHT internal table with that specific CARRID value. If this is not the case we create a BAPIRET2 message that is given back as result of the transformation: We call the transformation using the following code.
DATA: lt_sflight TYPE TABLE OF SFLIGHT, lt_scarr TYPE TABLE OF SCARR, lt_bapiret TYPE TABLE OF BAPIRET2. * Fill internal tables lt_sflight and lt_scarr CALL TRANSFORMATION Z_TEST SOURCE input1 = lt_sflight Input2 = lt_scarrid RESULT bapiret = lt_bapiret.
<TYPE>E</TYPE> <ID>Z01</ID> <NUMBER>100</NUMBER> <MESSAGE_V1><xsl:value-of select=”$id”/></MESSAGE_V1> </BAPIRET2> </xsl:if> <xsl:apply-templates/> </xsl:template> </xsl:transform>
Please remark that the template who does the check is quite short: everytime an SCARR element occurs we check whether there is exactly one SPFLI-elements having an CARRID with the same value. If this is not the case we give out an BAPIRET2 element that corresponds to an error message:
<xsl:template match="//SCARR" > <xsl:variable name="id" select="string(CARRID)"/> <xsl:if test="count(//SPFLI/CARRID[string(.) = $id]) != 1"> <BAPIRET2> <TYPE>E</TYPE> <ID>Z01</ID> <NUMBER>100</NUMBER> <MESSAGE_V1><xsl:value-of select="$id"/></MESSAGE_V1> </BAPIRET2> </xsl:if> ...
From Validation to Business Rules
Possible applications of ABAP to ABAP transformations are calculations and tests of ABAP values according to rule sets that are written in XML. In the example above we used XSLT to check ABAP data. But we can do better if we use a schema language. DTDs and W3C XML Schema are not very useful for our purposes: one the one hand they are too weak in terms of expressiveness and on the other hand coding rules in that languages is quite difficult.
To perform domain specific checks domain specific languages (DSLs) are appropriate. A DSL is a programming language designed to be useful for a specific set of tasks: a DSL may contain very sophisticated rules to calculate planned finishing dates of a certain process or may be able to express business rules.
And this is exactly what it is good for: validation of an XML document means to enforce a contract. If we create a schema corresponding to a business rule then validation of ABAP data (coded in its XML representation) means checking a business rule. Business rules can express marketing strategies, pricing policies or customer relationship management practices and lots more.
There are many languages for business rules and most of them are XML based or can be coded in XML. Let me mention CLiX – a language describing constraints in First-order logic and XPath expressions and Business Rule Markup Language .
Implementation of a DSL is a time consuming task. Sometimes it is possible to create an XSLT implementation of a DSL by using other XML based languages. I already introduced two languages that have been designed for checks of XML documents in two weblogs: Schematron (XML Processing in ABAP Part 8 – Using XSLT for Validation) and STV (Streaming Techniques for XML Processing – Part 3). If you have an implementation (i.e. an XSL transformation) that converts a program written in your DSL to one of those languages you already have an implementation of your DSL.
So this is approach could be useful if you already have
- a DSL describing you business rules,
- an transformation from DSL into an XML based language (perhaps CLiX) and
- a possibility to create XSLT programs from your XML based DSL.
Before you stop coding ABAP and start writing DSLs let me warn you:
- Creating and maintaining a DSL for business rules is a time consuming task.
- As I mentioned before there may be a loss of processor-efficiency when compared with hand-coded software: in our case the XSL transformation has to create the DOM tree of the input data structure which is memory consuming. If this the case you may think of an ABAP implementation of your DSL – instead of creating an XSL transformation you use XSLT to generate ABAP code like it is described in Code generation using XSL transformations and Dynamic Proxies in ABAP Part 3: Code Generation.
- Another problem of XSL transformation is that you have to use proprietary extension functions to access data stored in transparent tables or objects that buffer those data in internal tables.