Chapter 59. CTL1 vs. CTL2 Comparison

CTL2 is a new version of CloudConnect transformation language. It adds many improvements to the CTL concept.

Table 59.1. CTL Version Comparison

FeatureCTL1CTL2
Strongly typed
no
yes
Interpreted mode
yes
yes
Compiled mode
no
yes
Speedslowerfaster

Typed Language

CTL has been redesigned to be strongly typed in CTL2. With variable declarations already containing type information the introduction of type checking mostly affects container types and functions. In CTL2, container types (lists and maps) must declare the element type and user-defined functions must declare return type as well as types of their arguments.

Naturally, strict typing for functions requires introduction of void type for functions not returning any value. typing also introduces function overloading in local code as well as in the built-in library.

Arbitrary Order of Code Parts

CTL2 allows to declare variables and functions in any place of the code. Only one condition must be fulfilled - each variable and function must be declared before it is used.

CTL2 also allows to define mapping in any place of the transformation and be followed by other code.

Parts of CTL2 code may be interspersed almost arbitrarily.

Compiled Mode

CTL2 code can be transformed into pure Java which greatly increases speed of the transformation. This is called "compiled mode" and CloudConnect can do it for you transparently each time you run a graph with CTL2 code in it. The transformation into compiled form is done internally so you do not need to be Java programmer to use it.

Each time you use a component with CTL2 transform and explicitly set it to work in compiled mode, CloudConnect produces an in-memory Java code from your CTL and runs the Java natively - giving you a great speed increase.

Access to Graph Elements (Lookups, Sequences, ...)

A strict type checking is further extended to validation of lookup tables and sequences access. For lookup tables the actual arguments of lookup operation are validated against lookup table keys, while using the record returned by table in further type checked.

Sequences support three possible return types explicitly set by user: integer, long, and string. In CTL1 records, lookup tables, and sequences were identified by their IDs - in CTL2 they are defined by names. For this reason, names of these graph elements must always be unique in a graph.

Metadata

In CTL2, any metadata is considered to be a data type. This changes the way records are declared in CTL transformation code, as sou can use your metadata names directly in your code to declare a variable:

Employee tmpEmployee;
recordName1 myRecord;

The following table presents an overview of differences between both versions of CTL.

Table 59.2. CTL Version Differences

CTL1CTL2
Header (interpreted mode)
//#TL//#CTL2
//#CTL1
Header (compiled mode)
unavailable//#CTL2:COMPILED
Declaration of primitive variables
intinteger
bytearraybyte
Declaration of container variables
list myList;<element type>[] myList;

Example: integer[] myList;

map myMap;
map[<type of key>, <type of value>] myMap;

Example: map[string,boolean] myMap;

Declaration of records
record (<metadataID>) myRecord;<metadataName> myRecord;
Declaration of functions
function fName(arg1,arg2) {
      <functionBody> }
function <data type> fName(<type1> arg1,<type2> arg2) {
      <functionBody> }
Mapping operator
$0.field1 := $0.field1;(please note ':=' vs '=')$0.field1 = $0.field1;(please note ':=' vs '=')
Accessing input records
@<port No>unavailable, may be replaced with:
$<port No>.*
@<metadata name>unavailable, may be replaced with:
$<metadata name>.*
Accessing field values
@<port No>[<field No>]unavailable, may be replaced with:
$<port No>.<field name>
@<metadata name>[<field No>]unavailable, may be replaced with:
$<metadata name>.<field name>
<record variable name>["<field name>"]
<record variable name>.<field name>
Conditional fail expression (interpreted mode only)
$0.field1 := expr1 : expr2 : ... : exprN;$0.field1 = expr1 : expr2 : ... : exprN;
unavailablemyVar = expr1 : expr2 : ... : exprN;
unavailablemyFunction(expr1 : expr2 : ... : exprN)
Dictionary declaration
need not be definedmust always be defined
Dictionary entry types
string, readable.channel, writable.channelboolean, byte, date, decimal, integer, long, number, string, readable.channel, writable.channel, object
Writing to dictionary
signature:syntax:
void write_dict(string name, string value)
dictionary.<entry name> = value;
example 1:example:
write_dict("customer", "John Smith");
dictionary.customer = "John Smith";
example 2:
string customer;
write_dict(customer, "John Smith");
signature:
boolean dict_put_str(string name, string value);
example 3:
dict_put_str("customer", "John Smith");
example 4:
string customer;
dict_put_str(customer, "John Smith");
Reading from dictionary
signature:syntax:
string read_dict(string name)
value = dictionary.<entry name>;
example 1:example:
string myString;
myString = read_dict("customer");
string myString;
myString = dictionary.customer;
example 2:
string myString;
string customer;
myString = read_dict(customer);
signature:
string dict_get_str(string name)
example 3:
string myString;
myString = dict_get_str("customer");
example 4:
string myString;
string customer;
dict_get_str(customer);
Lookup table functions
lookup_admin(<lookup ID>,init)1)unavailable
lookup(<lookup ID>,keyValue)lookup(<lookup name>).get(keyValue)
lookup_next(<lookup ID>)lookup(<lookup name>).next()
lookup_found(<lookup ID>)lookup(<lookup name>).count(keyValue)
lookup_admin(<lookup ID>,free)1)unavailable
Sequence functions
sequence(<sequence ID>).currentsequence(<sequence name>).current()
sequence(<sequence ID>).nextsequence(<sequence name>).next()
sequence(<sequence ID>).resetsequence(<sequence name>).reset()
Switch statement
switch (Expr) {
      case (Expr1) : { StatementA StatementB }
      case (Expr2) : { StatementC StatementD }
      [default : { StatementE StatementF }]
}
switch (Expr) {
      case Const1 : StatementA StatementB break;
      case Const2 : StatementC StatementD break;
      [default : StatementE StatementF]
}
For loop
int myInt;
for(Initialization;Condition,Iteration)

(Initialization, Condition and Iteration are required)

for(integer myInt;Condition;Iteration)

(Initialization, Condition and Iteration are optional)

Foreach loop
int myInt;
list myList;
foreach(myInt : myList) Statement
integer[] myList; 
foreach(integer myInt : myList) Statement
Error handling
string MyException;
try Statement1 catch(MyException) 
[Statement2]
unavailable
following set of optional functions can be used in both CTL1 and CTL2:
<required template function>OnError() (e.g. transformOnError(), etc.)
Jump statements
breakbreak;
continuecontinue;
return Expressionreturn Expression;
Contained-in operator
myVar .in. myContainerin(myVar,myContainer)
or
myVar.in(myContainer)
Eval functions
eval()unavailable
eval_exp()unavailable
Ternary operator

unavailable

but

iif(Condition,ExprIfTrue,ExprIfFalse)
can be used instead
Condition ? ExprIfTrue : ExprIfFalse

but

iif(Condition,ExprIfTrue,ExprIfFalse)
also exists

Legend:

1) These functions do nothing since version 3.0 of CloudConnect and can be removed from the code.