Chapter 55-Chapter 56-Clover
Total Page:16
File Type:pdf, Size:1020Kb
CTL This chapter describes the syntax and the use of CTL. For detailed information on language reference or built-in functions see: • Language Reference • Functions Reference Example 55.1. Example of CTL syntax (Rollup) //#CTL string[] customers; integer Length; function void initGroup(VoidMetadata groupAccumulator) { } function boolean updateGroup(VoidMetadata groupAccumulator) { customers = split($0.customers," - "); Length = length(customers); return true; } function boolean finishGroup(VoidMetadata groupAccumulator) { return true; } function integer updateTransform(integer counter, VoidMetadata groupAccumulator) { if (counter >= Length) { clear(customers); return SKIP; } $0.customers = customers[counter]; $0.EmployeeID = $0.EmployeeID; return ALL; } function integer transform(integer counter, VoidMetadata groupAccumulator) { return ALL; } Language Reference This section describes the following areas: • Program Structure • Comments • Import Where? • Data Types in CTL • Literals • Variables • Dictionary in CTL • Operators • Simple Statement and Block of Statements • Control Statements • Functions • Conditional Fail Expression • Accessing Data Records and Fields • Mapping • Parameters Program Structure Each program written in CTL must contain the following parts: ImportStatements VariableDeclarations FunctionDeclarations Statements Mappings All of them may be interspersed, however there are some principles that are valid for them: • If an import statement is defined, it must be situated at the beginning of the code. • Variables and functions must first be declared and only then they can be used. • Declarations of variables and functions, statements, and mappings may also be mutually interspersed. Important In CTL declaration of variables and functions may be in any place of the transformation code and may be preceded by other code. However, remember that each variable and each function must always be declared before it is used. Comments Throughout the program you can use comments. These comments are not processed, they only serve to describe what happens within the program. There are two types of comments. They can be one-line comments or multiline comments. See the following two options: • // This is an one-line comment. • /* This is a multiline comment. */ Data Types in CTL For basic information about data types used in metadata see Data Types and Record Types. What? (see where?) In any program, you can use some variables. Data types in CTL are the following: boolean Its declaration look like this: boolean identifier; byte This data type is an array of bytes of a length that can be up to Integer.MAX_VALUE as a maximum. It behaves similarly to the list data type (see below). Its declaration looks like this: byte identifier; cbyte This data type is a compressed array of bytes of a length that can be up to Integer.MAX_VALUE as a maximum. It behaves similarly to the list data type (see below). Its declaration looks like this: cbyte identifier; date Its declaration look like this: date identifier; decimal Its declaration looks like this: decimal identifier; By default, any decimal may have up to 32 significant digits. If you want to have different Length or Scale, you need to set these properties of decimal field in metadata. Example 55.2. Example of usage of decimal data type in CTL If you assign 100.0 /3 to a decimal variable, its value might for example be 33.333333333333335701809119200333. Assigning it to a decimal field (with default Length and Scale, which are 8 and 2, respectively), it will be converted to 33.33D. You can cast any float number to the decimal data type by apending the d letter to its end. integer Its declaration looks like this: integer identifier; If you apend a l letter to the end of any integer number, you can cast it to the long data type. long Its declaration looks like this: long identifier; Any integer number can be cast to this data type by appending a l letter to its end. number (double) Its declaration looks like this: number identifier; string Its declaration looks like this: string identifier; list Each list is a container of one the following data types: boolean, byte, date, decimal, integer, long, number, string, or record. The list data type is indexed by integers starting from 0. Its declaration can look like this: string[] identifier; Lists cannot be created as a list of lists or maps. The default list is an empty list. Examples: integer[] myIntegerList; myIntegerList[5] = 123; Customer JohnSmith; Customer PeterBrown; Customer[] CompanyCustomers; CompanyCustomers[0] = JohnSmith; CompanyCustomers[1] = PeterBrown Assignments: • myStringList[3] = "abc"; It means that the specified string is put to the fourth position in the string list. The other values are fille with null as follows: myStringList is [null,null,null,"abc"] • myList1 = myList2; It means that both lists reference the same elements. • myList1 = myList1 + myList2; It adds all elements of myList2 to the end of myList1. Both lists must be based on the same primitive data type. • myList1 = myList1 + "abc"; It adds the "abc"string to the myList1 as its new last element. myList1 must be based on string data type. • myList1 = null; It destroys the myList1. Be careful when performing list operations (such as append). See Warning. map This data type is a container of pairs of a key and a value. Its declaration looks like this: map[<type of key>, <type of value>] identifier; Both the Key and the Value can be of the following primitive data types: boolean, byte, date, decimal, integer, long, number, string. Value can be also of record type. Map cannot be created as a map of lists or other maps. The default map is an empty map. Examples: map[string, boolean] map1; map1["abc"]=true; Customer JohnSmith; Customer PeterBrown; map[integer, Customer] CompanyCustomersMap; CompanyCustomersMap[JohnSmith.ID] = JohnSmith; CompanyCustomersMap[PeterBrown.ID] = PeterBrown The assignments are similar to those valid for a list. Literals Literals serve to write values of any data type. Table 55.1. Literals Declaration Literal Description Example syntax digits representing integer integer [0-9]+ 95623 number digits representing integer number with absolute value 257L, or long integer [0-9]+L? even greater than 231, but 9562307813123123 less than 263 digits and letters hexadecimal representing integer number 0x[0-9A-F]+ 0xA7B0 integer in hexadecimal Form digits representing integer octal integer 0[0-7]* 0644 number in octal Form Floating point number number represented by 64bits in [0-9]+.[0-9]+ 456.123 (double) double precision Format Declaration Literal Description Example syntax digits representing a decimal decimal [0-9]+.[0-9]+D 123.456D number string value/literal enclosed double in double quotes; escaped "...anything quoted characters [\n,\r,\t, \\, \", "hello\tworld\n\r" except ["]..." string \b] get translated into corresponding control chars string value/literal enclosed single in single quotes; only one '...anything quoted escaped character [\'] gets 'hello\tworld\n\r' except [']...' string translated into corresponding char ['] list oF literals where [ <any literal> [10, 'hello', "world", list oF literals individual literals can also be (, <any 0x1A, 2008-01-01 ], [ [ other lists/maps/records literal>)* ] 1 , 2 ] ] , [ 3 , 4 ] ] this mask is date date value expected: 2008-01-01 yyyy-MM-dd this mask is expected: datetime datetime value 2008-01-01 18:55:00 yyyy-MM-dd HH:mm:ss Important You cannot use any literal for byte data type. If you want to write a byte value, you must use any of the conversion functions that return byte and aply it on an argument value. For information on these conversion functions see Conversion Functions Important Remember that if you need to assign decimal value to a decimal field, you should use decimal literal. Otherwise, such a number would not be decimal, it would be a double number! For example: 1. Decimal value to a decimal field (correct and accurate) // correct - assign decimal value to decimal field myRecord.decimalField = 123.56d; 2. Double value to a decimal field (possibly inaccurate) // possibly inaccurate - assign double value to decimal field myRecord.decimalField = 123.56; The latter might produce inaccurate results! Variables If you define some variable, you must do it by typing the data type of the variable, white space, the name of the variable, and a semicolon. Such a variable can be initialized later, but it can also be initialized in the declaration itself. Of course, the value of the expression must be of the same data type as the variable. Both cases of variable declaration and initialization are shown below: • dataType variable; ... variable = expression; • dataType variable = expression; Dictionary in CTL If you want to have a dictionary in your graph and access an entry from CTL, you must define it in the graph as shown in What? (no link/table) To access the entries from CTL, use the dot syntax as follows: dictionary.<dictionary entry> This expression can be used to • define the value of the entry: dictionary.customer = "John Smith"; • get the value of the entry: myCustomer = dictionary.customer; • map the value of the entry to an output field: $0.myCustomerField = dictionary.customer; • serve as the argument of a function: myCustomerID = isInteger(dictionary.customer); Operators The operators serve to create more complicated expressions within the program. They can be arithmetic, relational, and logical. The relational and logical operators serve to create expressions with resulting boolean