next up previous contents
Next: 6. Summary Up: Großer Beleg XML Query Previous: 4. Resulting Requirements   Contents

Subsections


5. Evaluation of XSLT

This chapter shows, that the type information component as described in the chapters before can be implemented using XSLT. It will be shown, that XSLT fulfills the requirements described in the previous chapter.

This section will not produce an implementation working together with the OCL compiler. Instead it will discuss the critical points and possible solutions. I will develop code fragments in XSLT, without integrating them into the compiler.

5.1 Adapting XSLT to Java

This section designs the adaption mechanism beetween Java interface introduced in section 3.1.1 and XSLT. In fact, this adaption mechanism will work with any query language. This adapter will not be implemented, but we have to think about it.

At first, XSLT like any other query language cannot handle anything else than strings. Thus we have to transform all types and classes to strings.

ModelFacade.
This class represents the whole model. There is only one instance at a time, so we don't have to care about it.
Type.
This class represents a basic datatype, a class or a association class. All these entities are represented by corresponding elements in XMI, and each of these elements carries a unique and mandatory xmi.id attribute. The value of this attribute can be used to identify each instance of Type.
Any.
Any is derived from Type without adding any further features, so the same arguments apply.
Boolean.
This is needed as return type of Type.conformsTo. It is represented by a string being either empty for false or having the value ``TRUE'' for true.
Applying these transformations to the interface, the operations of the model facade are adapted as follows:
ModelFacade.getClassifier
has the signature Any getClassifier(String name). The input parameter name is a already a string, and the implicit parameter this is the ModelFacade itself, and can be ignored. The corresponding XSLT script results in the xmi.id attribute value of the XMI element representing the queried instance of Any.
Type.conformsTo
has the signature boolean conformsTo(Type type). The input parameter type is represented by its xmi.id value, the same goes for this. The XSLT script returns a string representing the boolean value as describes above.
Type.navigateQualified
has the signature Type navigateQualified(String name, Type[] qualifiers). Parameter name is a string already, qualifiers and this are given as their xmi.id values. The script results in the xmi.id value of the queried type.
Type.navigateParameterized
is adapted exactly like navigateQualified.
Given this adaption mechanism we will do some scripting in XSLT.

5.2 Order of Instance Nodes

This section shows, that XSLT is able to query the order of nodes in the document instance. Therefore the operation Type.navigateParameterized is partially implemented in XSLT.

For the test case I slightly extended the example model from section 4.1. The script queries for operation(String y, int x) and correctly produces Return2.

class someClass
{
  Return1 operation(int x, String y);
  Return2 operation(String y, int x);
  Return3 operation(int x);
  Return4 otherOperation(String y, int x);
}
The problem of node order is easily solved in XSLT using node number qualifiers. As shown below, the first parameter of an operation is accessed by writing parameter[1].
<xsl:template match="Operation[name='operation']">
  <xsl:apply-templates select="parameter[1]"/>
</xsl:template>
The entire script is included in appendix A.1. For the resulting output see A.2.

5.2.1 Parameter Polymorphism.

The script does not care about parameter polymorphism, since this chapter does not intend to develop a fully functional XSLT version of navigateParameterized. The script simply tests the parameter types on equality.

Note, that this cannot be solved by simply invoking the XSLT script for conformsTo, which is explained in the next section. Instead, the java implementation must be called, since basic types and collections are handled there. At the very end of my work, I discovered a new requirement for XML query languages: the possibility to call java methods from the script.

5.3 Transitive Closure

This section shows, that XSLT is able to query the transitive closure of a given relation. Therefore the operation Type.conformsTo is implemented in XSLT.

5.3.1 Algorithm

At first some definitions. The function conformsTo is represented by the circle operator:


\begin{displaymath} A.conformsTo(B)=A\circ B\end{displaymath}

Function sup and sub retrieve all supertypes/subtypes of a given type:


\begin{displaymath} sup:Type\rightarrow P(Type)\end{displaymath}


\begin{displaymath} sub:Type\rightarrow P(Type)\end{displaymath}

Of course we use recursion. The first try is


\begin{displaymath} A\circ B=(A=B)\: \vee \: \exists t\in sup(A):t\circ B.\end{displaymath}

This traverses from subtypes to supertypes. We could go the other direction:


\begin{displaymath} A\circ B=(A=B)\: \vee \: \exists t\in sub(B):A\circ t.\end{displaymath}

Usually a generalization relation is more often branched in top-down direction, so traversing down-top should be faster.

During implementation I found, that a variation of the algorithm is easier to write in XSLT. I split it up into two parts:


\begin{displaymath} A\circ B=(A=B)\: \vee \: A\bullet B\end{displaymath}


\begin{displaymath} A\bullet B=\exists t\in sup(A):(t=B)\: \vee \: t\bullet B\end{displaymath}

The first part is implemented very efficiently in the java wrapper. The second part featuring the recursion is implemented in XSLT. This is explained in the next section.

5.3.2 Implementation

This chapter explains the implementation. For the complete source see appendix A.3.

The implementation is a cascade of ``procedure calls'', descending into the depth of the DOM tree. For example, the following rule descends into all Model elements nested into the XMI.content element. The currently queried subtype and supertype are stored in parameters ``sub'' and ``super''.

<xsl:template match="XMI.content">
  <xsl:param name="sub"   />
  <xsl:param name="super" />
  <xsl:apply-templates select="Model">
    <xsl:with-param name="sub">
      <xsl:value-of select="$sub"/>
    </xsl:with-param>
    <xsl:with-param name="super">
      <xsl:value-of select="$super"/>
    </xsl:with-param>
  </xsl:apply-templates>
</xsl:template>
Eventually there is a generalizationship found with the subtype in question. This rule branches to the rule for supertypes.
<xsl:template 
  match="Generalization[subtype[
    XMI.reference[@target=$sub]]]" 
  priority="2">
  <xsl:param name="sub"   />
  <xsl:param name="super" />
  <xsl:apply-templates select="supertype" 
    mode="supertype">
    <xsl:with-param name="super">
      <xsl:value-of select="$super" />
    </xsl:with-param>
  </xsl:apply-templates>
</xsl:template>
Eventually the supertype of the generalizationship is the supertype in question. The following rule matches this and generates a ``TRUE'', which is evaluated by the java wrapper.
<xsl:template 
  match="supertype[XMI.reference[@target=$super]]" 
  priority="2" 
  mode="supertype">
  <supertype super="{$super}">
    <xsl:text>[TRUE]</xsl:text>
  </supertype>
</xsl:template>
Note that the rule above as an increased priority. If the supertype does not match, there are another two rules for the recursion.
<xsl:template match="supertype" mode="supertype">
  <xsl:param name="super" />
  <xsl:apply-templates select="XMI.reference" 
    mode="supertype">
    <xsl:with-param name="super">
      <xsl:value-of select="$super"/>
    </xsl:with-param>
  </xsl:apply-templates>
</xsl:template>
 
<xsl:template match="XMI.reference" mode="supertype">
  <xsl:param name="super" />
  <xsl:variable name="nextsub" select="@target" />
  <xsl:apply-templates select="/XMI/XMI.content">
    <xsl:with-param name="sub">
      <xsl:value-of select="$nextsub"/>
    </xsl:with-param>
    <xsl:with-param name="super">
      <xsl:value-of select="$super"/>
    </xsl:with-param>
  </xsl:apply-templates>
</xsl:template>
Actually, the recursion is performed in the second rule above. The apply-templates element branches (nearly) to the top of the DOM tree. The subtype is not the same of the current query. Instead the subtype of the current generalizationship is used. This shortens the generalization distance by 1.

5.3.3 Test

This sections tests the XSLT script performing the conformsTo operation. Therefore I developed a test case featuring some kind of worst-case generalizationship. See figure 5.1.

Figure 5.1: Test Case for conformsTo in XSLT

For the test I queried the generalizationship from class C1 to class A3. Note, that there are two paths from C1 to A3, one via B2 and another via B3. Accordingly, the XSLT script produces the [TRUE] twice, once for each path.

Additionally the XSLT script produces debugging output. The output of the test query is available in appendix A.4, which can be used to trace the recursion path through the DOM tree.

For the test I used the Lotus XSLT processor version 0.18.5.


next up previous contents
Next: 6. Summary Up: Großer Beleg XML Query Previous: 4. Resulting Requirements   Contents
Ralf Wiebicke 2005-11-25