® IBM Software Group EGL Programming – Conditional Statements and Looping Constructs These slides walk you through terms, concepts and show examples of EGL case, if, try/onException, for and while statements. © 2006 IBM Corporation UNIT Programming in EGL Topics: The EGL Programming Model – Terms/Concepts EGL Data Parts and Assignment Statements EGL Conditional Logic and Looping Statements The EGL Built-in Functions and Date Math 2 More Logic! EGL Conditional and Looping Statements Conditional statements transfer control within a statement-block based on a logic decision. EGL offers the following conditional statements: case if, else try/onException Loop statements test a condition to determine how many times to repeat a set of statements. Some part of the loop must change the initial condition tested. EGL offers the following loop statements: for Loops through a statement block n times – automatically incrementing a counter forEach Loops through a relational cursor fetch – or a file read operation until end-of-file is reached while Loops until a condition is met. Note: For while, you must explicitly ensure the condition happens In addition, there are three EGL statements that are used for navigation within conditional and loop statements: continue exit return 3 EGL Conditional Logic Statements Conditional logic plays a large role in any production business application, and EGL provides all of the standard keywords you’d expect from a mature 4GL: if if-else compound if - two or more if conditions logically connected with and/or operators case statement try/onException - allows your application to recover from certain types of run-time failure conditions In addition, EGL provides many productivity-enhancing extended conditional expressions: in - allows you to search an array or EGL DataTable for a value (DataTables are covered later in this course) like – allows you to use SQL wildcard search characters to test for specific values or patterns in strings matches – allows you to use a set of reserved wildcard characters to do more extensive text search than like is/not – allows you to test for specific categories of conditions in string and char variables is/Not Numeric – tests for legitimate (or not) numeric data in a char field is/Not Blanks – tests for spaces in data 4 Simple if/else Conditional Statement From the example shown, note the following: The reserved word if precedes the condition The condition is enclosed inside parenthesis (…condition…) The condition can include the logical operators covered in the previous topic The condition comparison must resolve to a boolean true/false –If the condition is true any/all statements following the condition are executed – within the if/end scope terminator The if/equals comparison specifies two (double) == signs as the condition If the condition is false, any/all statements following the else path are executed The final else does not participate in an if (thus if both if statements test false, this else is executed) Each if statement block is closed by an end (scope terminator) The else statement block is considered part of the if statement it is associated with – thus, end follows the else portion EGL Conditional Operators Use Content Assist 5 Compound if/else Conditional Statements In the example above, each if statement has two conditions, connected by && Each single condition is enclosed in parenthesis - and the entire compound if statement is enclosed in parenthesis in a second set of parenthesis The same rules about end and else apply to compound if Each if statement must be terminated by an end statement in a matching pair. In this example there are three if statements and three end statements (the fourth and final end statement terminates the entire function). Compound if statements are written with and (&& - or the word AND) and/or (|| - or the word OR) operators separating each condition && (AND) – designate a logical AND connection between two conditions Unless all conditions connected by && test true, the else path is taken || (OR) – designate a logical OR connection between two conditions If any single condition connected by || tests true, the true path is taken 6 case Statement Example, inspect the value returned from an EGL DateTimeLib function (monthOf) on the empRecin.reportTimeStamp value. If the value is 1 – 3, do 1st quarter processing. If the value is 4 – 6, do 2nd quarter processing. If 7 – 9 do 3rd quarter processing. If > 9 its end of year processing (note – this logic assumes values 1 – 12) The EGL case statement marks the start of multiple sets of statements, where at most only one of those sets is run. CASE is equivalent to an RPG SELECT, COBOL EVALUATE, C or Java switch statement that has a break at the end of each case clause. Note that the above statement could have been coded with if/else statements. However, case may be easier to code, test and maintain (for logic such as this), and in some languages (like Java) case can outperform if/else at run-time. You may also code conditions inside each of the when(…) statements As with most EGL statements, use Content Assist to create. 7 *** See Notes: - For additional examples! IN Conditional Operator – Searching Through Arrays in a Single Statement The EGL in keyword allows you to test for the presence of a value in an array or EGL DataTable. Typically you would have to write a for loop to test for this condition. Instead you can code (and maintain) far fewer statements using in . Example: Assume an array of customers, loaded from the database, and a string variable named: srchString – return a message to a control on a .JSP page if (srchString in customers.Last_Name || srchString in customers.First_Name) sysLib.setError("Search String in Array"); else sysLib.setError("Search String NOT in Array"); end Note that in returns an EGL reserved system index value sysVar.arrayIndex. This index value designates either: 0 for not found … > 0 for the array occurrence in which the IN match occurred You can use the sysVar.arrayIndex value to further process the array information. if (srchString in customers.Last_Name ||srchString in customers.First_Name) move customers[sysVar.arrayIndex].Last_Name to temp_name; else sysLib.setError("Search String NOT in Array"); End Finally - note that you can extend in – with “from <start>” – where start <start> is an integer value within the range of the Array. See Notes – on negating an IN condition 8 Like and Matches Conditional Operators – Complex Text Search LIKE Keyword Like allows you to use SQL LIKE wildcards to search for text patterns in a string. % = 0 – n wildcard characters allowed _ (underscore) exactly one wildcard character allowed at this position in the string Matches Keyword Matches are similar to Java “regular expressions” – and extend the capability of doing LIKE text searches with terse patterns. They allow you to setup complex text-search-pattern-masks that can be used to solve the kinds of sophisticated text-matching problems you may find in production specifications. Please read the Product Help on Matches (search on: matches operator) Matches examples: Find non-Alphabetic (upper and lower-case letters) in a string if (strField matches "*[^A-Za-z]*") //tests-true Find non-Numeric (values) in a string if (strField matches "*[^0-9]*") for any non-alphabet character //tests-true for any non-numeric character Test for a valid routing code in a string: ##-##-## if (!(routing_code matches "[0-9][0-9][-][0-9][0-9][-][0-9][0-9]")) 9 IS and ISA Conditional Operators – Categories of Conditions IS Keyword - IS allows you to test for categories of conditions with the following keywords: if (strField is/is not numeric) //tests for fields containing only numeric characters if (strField is/is not blanks) //tests for fields containing only blanks (spaces) if (EGLSQLRecord is noRecordFound) //tests results of last relational database I/O operation against the SQLRecord. Returns true, SQLCode indicates no data returned ISA Keyword ISA allows you to test for data types at run-time if (field isa ___ ) //tests-true for a valid data type Note – isa primarily used to interface with Java class types 10 EGL Loops - FOR Statement The EGL for statement governs a loop that runs until a counter reaches a specified value. You provide an initial value for the counter, a limit for the counter, and an optional amount by which EGL automatically increases or reduces the value of the counter after completing each loop. The keyword end marks the close of the for statement – and the test is done before the code within the statement block is executed. Use Content Assist to create the for statement – and don’t forget to Tab through each of the Content Assist-able options within the parens! 11 EGL Loops - WHILE Statement The EGL keyword while marks the start of a loop that runs as long as a specified logical expression resolves to true. The keyword end marks the close of the while statement . Unlike the FOR statement – which automatically increments the loopcounter, you are responsible for ensuring that a WHILE loop ends. You would typically use WHILE to run until a condition was met – and use FOR to loop through code “n” times. Use Content Assist to create the WHILE statement. 12 “Take it from the top” – continue Statement The EGL continue statement returns control to the start of a statement block controlled by a for, forEach or while statement. EGL evaluates the conditions for continuing the loop at that point, and either continues executing the loop or exits to the next statement. Examples: Add the value in sum to an inputArray[], but only for the 5th through 10th elements: for (i from 1 to 10 by 1) if (i < 5) continue; //sum, only for inputArray[5->10] end //end-if sum = inputArray[i] + sum; end //end-for The following example prints the members of an array, inserting a blank line between each group of ten. Note – continue returns control to the start of the for loop. for (i from 1 to 100 by 1) printReport(myArray[i]); if ((i % 10) != 0) continue; // return to printReport(myArray[i]); end //end-if printReport(blankLine); end //end-for 13 Breaking out of EGL Loops – EXIT Statements The EGL exit statement provides an immediate exit from all or part of a function or of a block of code controlled by a conditional or loop statement. If you do not specify a modifier, exit transfers control out of the most recently entered block of code governed by a case, for, forEach, if, openUI, or while statement. If the exit statement is not inside a loop or condition, it transfers control out of the most recently entered function. If you specify one of the following modifiers, the exit statement passes control out of the most recently entered loop of that type: case for forEach if openUI while Example: for (i from 1 to 10 by 1) if (sum > 1000) exit for; //branches to: sumDisplay = sum; end //end-if sum = inputArray[i] + sum; writeStdOut(sum as string); //Write if sum <= 1,000 end sumDisplay = sum; 14 Ending an EGL Function – return Statement The EGL return statement exits from an EGL function and optionally returns a value to the invoking function. function main() //Do stuff calculateResults(); writeStdOut(msg); //next statement after return end function calculateResults() if (timeDays == 0) msg = "Please enter the timeDays as a number of days. Thanks."; return; //leave this EGL function – and return to writeStdOut(); in main() end if (principal == 0) //additional code inside the function end end 15 Run-time Exception Handling – try/onException EGL refers to program errors as exceptions. An exception can occur when an EGL-generated program does any of the following: Accesses a file, queue, or database Calls another program Invokes a function Performs an assignment, comparison, or calculation try Statement Block Program Exception You can choose to handle certain types of exceptions or for all exceptions. To handle an exception means that you do not allow the current program to terminate – resulting in a run-time error, but provide special processing for the circumstances. The mechanism that EGL uses to handle errors is the try block Any statement that throws an exception inside a try statement block causes the program to look for a matching onException statement block within that same try statement block. If an onException statement block exists that references the exception thrown, control passes to the code within that block. 16 Matching onException? Run-time Error Handle Exception try/onException - Syntax The basic format of try/onException is: try //some EGL functionality onException (<exceptionRecordVar> <exceptionRecordType>) //Do something to trap the error without abending end Notes: If there is no run-time error, execution falls through to the statement after end If an exception occurs that is not accounted for (handled with exceptionRecordType) you will get a run-time error You can put any statements you want in the try block and in the onException block But typically, code in your onException block will transfer control to a page – or something that ends the application gracefully You can wrap your entire application’s logic in a try /onException block, which will handle exceptions no matter how or (more to point) when they occur (in sub-routines, or calls to library functions or services anywhere in the statement call-chain The exceptionRecordType provides the following (in all cases): – Error Code, Error Message There is additional information for specific error conditions with different exceptionRecordTypes You can explicitly throw exceptions as well 17 try/onException – What are the Exception Types and Records When an error occurs the system looks for an exception category first A few Exception Categories IndexOutOfBoundsException J2EESessionRequestAccessException JavaObjectException Failing to find a “category exception” coded, if the error causes a run-time termination Ex. Math Overflow Failing to find a “category exception” coded, or Runtime Exception… RuntimeException AnyException LobProcessingException Program Exception ServiceBindingException ServiceInvocationException SQLException TypeCastException FileIOException 18 *** See Notes: - For additional info on exception handling! OPTIONAL TOPIC – Throwing Your Own (custom) Exception Using an EGL throw statement, you can throw any of the predefined system exceptions. As in exception handling, you must declare a variable based on the record: nullEx NullValueException{}; … throw nullEx; In addition to the exceptions that the system defines, you can create your own exception records. As with other records, you must define a Record part first, and then declare a variable based on it. Record CustomerException type Exception customerNumber INT; end throw new customerException { customerNumber = custNum, message = "Illegal customer number" }; Custom exceptions records like this one automatically include the messageID and message fields, just like the system exception records. 19 Workshop – Conditional Testing and Looping Continue working with payrollprogram. Create a series of EGL functions that exercise the language concepts discussed in this topic. Steps: 1. Create the following set of function calls in the main() function of the program 2. After you’ve coded them • Select all of the function calls you just coded and comment them out Right-click and select Comment You will now add the individual functions and then un-comment calls to them from the main() function, and Debug the statements (next slides ) 20 Workshop – Code the if test Functions Anywhere in the functions section of the source code, add the following two functions (see screen capture below) The simpleIfElse() function tests the 1st array element’s grossPay value against the 2nd array element’s. The compoundIfElse() function calculates ytdGrossPay for the 1st array element, based on a compound AND/OR Steps: 1. 2. 3. Copy the function names down from the main() Use Content Assist EVERYWHERE – to reference the empRecArray records and fields, and for writeStdOut When your syntax checks clean (Ctrl/S) 1. Add breakpoints 2. Debug payrollProgram - step through the code, watch the variables change in the functions 21 Workshop – Code the InTest and whileLoopMatches Functions In the functions section of the source code, add the following functions (shown below): The inTest() function tests to find “Smith” in the lastName field in the array – in one statement The whileLoopMataches() function sees if any employees have a single uppercase letter in position 2 of empId Steps: 1. Copy the function names down from the main() 2. Use Content Assist EVERYWHERE – to reference the empRecArray records and fields, and for writeStdOut 3. When your syntax checks clean (Ctrl/S) 1. Add breakpoints 2. Debug payrollProgram - step through the code, watch the variables change in the functions 22 Workshop – Code the forLoop Function In the functions section source code, add the following function (shown below): The forLoop() function derives a sum, min, max and average from the grossPay values in the empRecArray. Steps: 1. Same as before – especially – use Content Assist everywhere 2. When your syntax checks clean (Ctrl/S) 1. Add breakpoints and debug your logic - step through the code, watch the variables change in the functions 23 Workshop – Code the exceptionRef and continueExitReturn Functions In the functions section of the source code, add the following functions (shown below). The exceptionRef() function causes a run-time error – which trap with an onException routine Be sure to view the exception record values after execution The continueExitReturn() function allows you to see the run-time behavior of continue, exit and return – as they occur while looping and within conditional tests. Follow the Debugging line-by-line instructions carefully here – to see your logic in slowmotion! 24 (OPTIONAL) Using try/onException Creatively – Date Validation You can use try/onException to do things in V7 not possible in V6 – for example testing string fields for valid dates Steps Add the validDation() function (in the Notes section) below to payrollProgram.egl – as a new function, and add a statement to invoke the function. Then debug it. Note the exception record information. Also note how useful this could be to your applications! 25 (OPTIONAL Topic) EGL and ASCII File Escape Sequences These characters originated in the C language when writing to a console device and/or a printer direct from the language to format text. Below is a list of supported codes embedded in a sample program, and the output produced by running the program. PROGRAM: // escapeseq.egl demonstrates escape sequence codes when using writeStdOut() /* This program demonstrates the use of escape sequence codes when using the writeStdOut() EGL function or writing to an error log file. Note: this list originated in the C programming language. The following are supported and demonstrated below: \n Newline - inserts a CRLF (carriage return line feed) \t Horizontal Tab - useful for formatting tabular output \b Backspace - supported but not very useful in EGL \\ Backslash - lets you use a "\" in your text \" Double quote - lets you embed double quotes in your text */ program escapeseq type BasicProgram function main() // use of \t for tabs writeStdOut("Field1\tField2\tField3"); writeStdOut("AAA\tBBB\tCCC"); // use of \n for "newline" writeStdOut("This is on the first line\nAnd this on the next line"); // use of \\ to allow use of the backslash "\" in your text writeStdOut("This allows you to use a backslash \\ in your text"); // use of double quotes in your text \" writeStdOut("Double \"quoted\" words"); end end 26 Topic Summary Now that you have completed this topic, you should be able to: List the different types of EGL conditional statements Describe at least 10 of the EGL conditional operators Define the three EGL looping constructs Define the use and behavior of: Exit Continue Return Describe the use of onException coding and handling of run-time errors Code statements in programs that use EGL conditional and looping expressions 27