In addition to being able to translate CQL to ELM, any given expression of ELM can be represented in CQL. Support for this direction of translation would be useful for applications that produce ELM from another source, and need to display a human-readable representation of the logic.
This bi-directionality means that a given expression of CQL could be translated to ELM, and then back again. However, because ELM is typically a more primitive representation, this process is not necessarily a “round-trip”. For example, consider the following CQL:
A starts within 3 days of start B
This will actually result in the following ELM output:
<expression xsi:type="In">
<operand xsi:type="DurationBetween" precision="Day">
<operand xsi:type="Start">
<operand xsi:type="ExpressionRef" name="A"/>
</operand>
<operand xsi:type="Start">
<operand xsi:type="ExpressionRef" name="B"/>
</operand>
</operand>
<operand xsi:type="Interval">
<low xsi:type="Literal" valueType="xs:int" value="-3"/>
<high xsi:type="Literal" valueType="xs:int" value="3"/>
</operand>
</expression>
The above expression, rendered directly back to CQL would be:
days between start of A and start of B in [-3, 3]
These expressions are semantically equivalent, but not syntactically the same, as the first is targeted at understandability, while the second is targeted at implementation. To preserve “round-trip” capability, an implementation could emit annotations with the ELM using the extension mechanism of the base Element class to provide the original source CQL.
In general, the mapping from ELM to CQL is simply the opposite of the mapping described in the previous section. However, there are several special-purpose operators that are only defined in ELM which are used to simplify query implementation. For completeness, the mappings from those operators to CQL are described here to ensure that any given ELM document could be translated to CQL.
The examples in the following section will make use of the following expression definitions:
<def name="List1">
<expression xsi:type="List">
<element xsi:type="Tuple">
<element name="X">
<value xsi:type="Literal" valueType="xs:int" value="1"/>
</element>
</element>
<element xsi:type="Tuple">
<element name="X">
<value xsi:type="Literal" valueType="xs:int" value="2"/>
</element>
</element>
<element xsi:type="Tuple">
<element name="X">
<value xsi:type="Literal" valueType="xs:int" value="3"/>
</element>
</element>
</expression>
</def>
<def name="List2">
<expression xsi:type="List">
<element xsi:type="Tuple">
<element name="Y">
<value xsi:type="Literal" valueType="xs:int" value="1"/>
</element>
</element>
<element xsi:type="Tuple">
<element name="Y">
<value xsi:type="Literal" valueType="xs:int" value="2"/>
</element>
</element>
<element xsi:type="Tuple">
<element name="Y">
<value xsi:type="Literal" valueType="xs:int" value="3"/>
</element>
</element>
</expression>
</def>
2.1. ForEach
The ForEach operator in ELM takes an argument of type list and returns a list with an element for each source element that is the result of evaluating the element expression. For example:
<expression xsi:type="ForEach">
<source xsi:type="ExpressionRef" name="List1"/>
<element xsi:type="Property" path="X"/>
</expression>
This expression returns the list of integers from the List1 expression. Although there is no direct counterpart in CQL, this expression can be represented using the query construct. The source for the ForEach is used as the primary query source, and the element expression is represented using the return-clause:
2.2. Times
The Times operator in ELM computes the Cartesian-product of two lists. Again, although there is no direct counterpart in CQL, the query construct can be used to produce an equivalent result:
<expression xsi:type="Times">
<source xsi:type="ExpressionRef" name="List1"/>
<source xsi:type="ExpressionRef" name="List2"/>
</expression>
Assuming List1 and List2 are defined as specified above, the equivalent CQL is a multi-source query with a source for each operand in the Times, and a return clause that builds the resulting tuples:
from List1 A, List2 B
return \{ X: A.X, Y: B.Y }
2.3. Filter
The Filter operator in ELM filters the contents of a list, returning only those elements that satisfy the expression defined in the condition element. For example:
<expression xsi:type="Filter">
<source xsi:type="ExpressionRef" name="List1"/>
<condition xsi:type="Equal">
<operand xsi:type="Property" path="X">
<operand xsi:type="Literal" valueType="xs:int" value="1"/>
</condition>
</expression>
Again, although no direct counterpart in CQL exists, the where clause of the query construct provides the equivalent functionality:
2.4. Sort
The Sort operator in ELM sorts the contents of a list. For example:
<expression xsi:type="Sort">
<source xsi:type="ExpressionRef" name="List1"/>
<by xsi:type="ByColumn" path="X" direction="desc"/>
</expression>
Again, the CQL query construct provides the equivalent functionality: