Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Table of Contents
maxLevel1

Creating Vocabularies

Vocabularies contain all the information which can be used in conditions and updated in actions. For example: The form field and the datasource field values we use in conditions, and the form field and page (tabs) enabled and visible properties we can set in actions.

...

So rules should and in most cases can be placed in the frame rules unless there are cases where the conditions and actions reference fields from multiple frames or ribbons (ribbons are usually in the widow) etc. which are less common (or if there are is only a window and no frames only windows).

In other words, use frames whenever you can and windows when you have to so make sure both the frame and windows vocabularies were generated.

Note: At runtime whenever a field is changed or a record is selected etc. it triggers the rule flow execution for the frame and also the rule flow execution for the window (if there are rule flows for the window and frame) incase the there are rules in the window that are also effected.

...

The Generate Vocabulary window creates a vocabulary file with the same name as the window or frame and the .ecore extension. Currently the file is saved out to the pasoe PASOE temp directory (c:\temp at OSIV). After the vocabulary file is generated, copy the file to your workspace (see file and directory structure).

...

In addition, the layout designer sets the RulesBehaviour and RulesMetadata properties for the window and the frame. These properties contain metadata and advanced options. There's currently no need or use cases to change these properties except when removing a ruleflow rule flow by deleting or setting an empty JSON object "{}".

Files and Directory Structure (Workspace)

There are 4 main rule file types and file extensions -

...

In addition, there are also the generated JavaScript files (minified .js files) used at runtime. The rule files are the only and absolute source of truth for the generated .js files. The .js files should not and cannot be modified manually.

The rules root directory is located in the osiv-customer webui/Rules directory (in the frontend project repository).

The root directory contains a Ruleflows directory for all the rule files. The Ruleflows directory is organized into directories according by module similar to categories similar to the ClientLogic frontend and OSIV3G source backend source directories. For example: Entscheid, Sendung, Stamm etc. directories.

The In addition, the root directory also contains directories for every generated window or frame rule flows (with containing the .js files). The generated directories (with the .js files) These directories are located in the root directory partly because this is the default location in the Corticon Generate Ruleflow dialog-box and it saves the need to change the value developers from changing the directory manually every time.

Guidelines

  • Open the Corticon.js Studio in the root rules directory, in <environment>/osiv-the customer webui/Rules directory.

  • All the rule files for a window or frame should be placed in a single directory with the same name (inside the correct module directory, in the Ruleflows category directory).

  • All the rule files should start with the same name as the window or frame (there is only one vocabulary and one workflow files so they should have the same name as the window or frame).

  • Every rule sheet file should have a different suffix like _IsEnabled, _IsVisible, _Pages etc. (see rule sheet design).
    For example: EntscheidDetailWindow_IsEnabled.ers

  • Rule test files should start with the same name as their rule sheet including the suffix plus _Test or _Test<number> for multiple rule tests (see rule test design).
    For example: EntscheidDetailWindow_isEnabled_Test.ert

  • Generate the .js files directory in the root rules directory which is also the default location of in the Corticon Generate Ruleflow dialog-box.

Git

Currently the .js files are included in the git repository and need to be committed instead of being generated in the build. There is a risk of the rules and .js files not matching in this approach. For example: if the rules were updated and someone forgot to generate the .js files.

Incase the .js files will need to be generated in the build the script files in the akioma corticon-java project can be used to generated the .js files (see the in Corticon integration guide).

Rule Sheet Design

There are advantages and disadvantages to separating unrelated rules with unrelated conditions to separate rule sheets or combining them to a single rule sheet.

...

The general best practices from Progress Software is to use separate rule sheets for complex conditions with many combinations and combine simpler rules into a single rulesheet rule sheet to save on rulesheets rule sheets files and are also where the Check for Conflicts and Check for Completeness is less needed. In other words, it's a balancing act, just like writing code.

...

Taking into account that UI rules are

...

mostly made up of many simple

...

rules and how the rules are mostly divided in the specification, the rules should be divided in the following way -

  • Fixed property settings (for example: The form field ICD is always read-only or disabled).
  • Rules for enabling form fields.
  • Form fields visibility rules.
  • Pages (tabs) visibility rules and enabling or disabling pages.
  • Message rules (errors, warnings and info messages).

With the exception that complicated rules with many conditions fields and many combinations are put in a separate rule sheets.

Guidelines

  • Place rules in the frame rule flow whenever you can and the window rule flow whenever you have to, for the purpose of dividing the rules into many simple frame rule flows instead of one big and complicated window rule flow (see creating vocabularies).

  • Divide the rules into the following rule sheets and rules (which is also the same way the rule specification at OSIV divided the rules) -
    <window>rule sheet names (unless they have no rules. There's no need for empty rule sheets) -

    • <window or frame>_Fixed.ers - Fixed property settings.
    • <window><window or frame>_IsEnabled.ers - Rules for enabling form fields (using the <field>__isEnabled property).<window>
    • <window or frame>_IsVisible.ers - Form fields visiblity rules (using the <field>__isVisible property).<window>visibility rules.
    • <window or frame>_Pages.ers - Pages (tabs) visiblity rules and enabling or disabling pages.
    • <window><window or frame>_Messages.ers - Message rules (errors, warnings and info messages).

  • With the following exception - if there are complicated Complicated rules with conditions containing more than 5 to 10 fields and many combinations then it is recommended to put these rules more than 5 to 10 combinations should be put in a separate rule sheets with a their own descriptive name suffix.
    For example: EntscheidDetailBasisFrame_IsUnUpdatable.
    Unrelated conditions and actions in a single rule sheet should be separated with an empty row for clarityers

  • Use the vocabulary fields not expressions in the condition and action panes unless you have to.
    For example: In the condition pane, do not use EntscheidDSO.Visum_Dat = null. Use EntscheidDSO.Visum_dat and null in the cell value.
    For example: In the action pane, do not use EntscheidDSO.isAvailable = true. Use EntscheidDSO.isAvailable and T in the cell value.

  • Beware of NULL's. Datasource field values are null when the record is not available so you may also want to add isAvailable and T cell value to your condition.
    For example: add EntscheidDSO.isAvailable and T cell value, to EntscheidDSO.Visum_dat and null cell value.

  • A specific property , (like , a form field is enabled property ( or any other property) must be set in one place and one place only. The property must be set in one rule sheet covering all the combinations, and in . In either the frame or window rules but never both. Setting the same property in different rule sheets increases the risk of conflicts.

  • Use the default action column whenever possible to decrease the number of condition combinations and simplify the rulesrule sheets.
    For example: if you set the default for the is enabled property to false then you only need to specify the condition combination when it is true (which in many cases is a single combination).

  • Use an AND condition and in combination with the default the column instead of an OR condition for setting properties to decrease the number of combinations and simplify rule sheets (because AND conditions use a single combination column and while OR conditions use multiple combination columns which helps simplify and shorten rule sheets). 

  • Continuing the guidelines above the The fixed rule sheet should only be used for properties that have a fixed or constant value and should not be used for default values.
    For example: if the specification says this form field is always enabled.

  • The fixed rule sheet can also be used for setting custom properties by calling the custom JavaScript functions to fetch values (see incorporating code).

  • In the message messages rule sheet, place the message text values in the cell action column and use the cellValue in the new message action and place the message in the cell for the action column.

...

  • for the message parameter.
    For example: Message.new[type='info', entity='EntscheidDetailWindow', message=cellValue]

  • Every rule action should have a rule statement with a simple description (the descriptions will not be shown to the user) used internally for debugging and understanding what rules were triggered (see rule tests design). No need to add a rule statement for the default column (column 0).

  • Avoid dependencies - Avoid using calculated values from rule sheets. Only use values coming from the vocabulary.
    With the exception of Custom properties set with JavaScript functions (see incorporating code).

Rule Test (Unit Tests)

Rule tests are the first and best way to debug and track down problems. Every rule sheet should have at least one ruletest a rule test with the exception of the fixed rulesheet. In addition, rule statements should be filled with a description for every combination to help debug what rules were triggered when running ruletests or at runtimerule sheet.

Rule tests are created with a single test sheet (tab). To add another test sheet (tab), open or select a rule test file, open the Ruletest menu, open the Testsheet menu and click the Add Testsheet menu item.

Rule tests also show you the rule statements of the rules that were triggered when running the test sheet to further help debug and understand the output.

You cannot have multiple separate different tests with different conditions in a single rulesheet test sheet and they must be separated to several ruletest files with the _Test<number>.ert suffixinto separate test sheets. Alternatively, use a single ruletest that can combines or triggers multiple rule conditions and actions.When copying entities to the ruletest input column, remove test sheet with conditions that triggers multiple rules.

Rule tests need to be incorporated and run as part of the build and pipeline unit tests.

Guidelines

  • Every rule sheet should have a rule test (except for the fixed rule sheet) with the same name of their rule sheet and a _Test suffix.
    For example: EntscheidDetailWindow_IsEnabled_Test.ert

  • Include the entities used for conditions and actions. If the entities used for condition are not included then you cannot set them. If the entities used for actions are not included then you will not see their changes. Except for entities the action creates new instances, like messages. New instances will be included.

  • Remove unused fields that have no conditions when copying entities to the input column, to keep the

...

  • rule tests simple and readable (keeping in mind that some forms and datasources can have tens or even hundreds of fields

...

Ruletests need to be incorporated and run as part of the build and pipeline unittests.

Ruleflow Design

Image Removed

Copy all the rulesheets to the ruleflow.

Even though the rulesheets have no dependencies except for special cases, the rulesheets should be connected in the following order - 1. fixed rulesheet, 2. is enabled rulesheet, 3. is visible rulesheet, 4. pages rulesheet, 5. messages rulesheet, 6 and above. if there are additional rulesheets (see rulesheet design guidelines).

With the exception if there are special cases with a different dependency or a more complicated ruleflow.

  • ).

  • Check all the rules work including cases when they should not work.

  • Currently only use a single object instance in your test sheet. If you need multiple instances, you most likely need another test sheet (tab).
    For example: do not use multiple instances of EntscheidDSO with different values to test multiple cases. Use multiple test sheets with a single EntscheidDSO in each one.

Note that at runtime Corticon logging can be turned on by setting Corticon.debug = true that will console log the rule triggers, execution, messages (rule statements), payload and result.

Rule Flows

Image Added


Even though the rule sheets have no dependencies by default (except for special cases) and there is no need to connect them, it is still considered a best practice and you should always connect the rule sheets so the order of execution is clear.

Of course, there can be more complicated rule flows but there's currently no need or use case.

Guidelines

  • Make sure all the rule sheets are copied into the rule flow.

  • Connect the rule sheets in the following order (with the exception of complex rule flows and in case a certain dependency and order is needed) -

    1. Fixed rule sheet.
    2. Is enabled rule sheet.
    3. Is visible rule sheet.
    4. Pages rule sheet.
    5. Messages rule sheet.
    6. or above; for any additional rule sheets (see rule sheet design).

Packaging Rules for Deployment (Generating JavaScript Files)

There is currently no need or use case to change the defaults when generating the .js files except for setting the Platform to browser.

Corticon creates a directory in the rules root directory with the same name as the ruleflow rule flow (which is also the name of the window or frame) containing all the required files.

The Corticon runtime looks for the generated file .js files in the same directory so there is no need to copy or manually move files.

The window and frame names are unique so there is no risk of conflicts.

...

DynSelect Settings

Guidelines

  • If there are any related fields that should be updated when a dynSelect value is changed in a form or calculated fields in business entities then they should be added to the dynSelect mapping so the correct values are available for to Corticon.

    This guideline is true when using Corticon as it is when writing TypeScript.

Incorporating Code (Advanced Cases)

Image Added

Using code should only be used as a last resort and if there is no other choice. Whenever possible backend data should be taken from the business entity. If the data does not exist in the business entity, consider adding the fields or even creating another business entity with the required fields.

To run simple synchronous code like fetching data from the UI, Corticon.js supports JavaScript functions calls in rulesheetsrule sheets. You can create custom properties and set their values with JavaScript functions in the fixed rulesheetrule sheet.

To run asynchronous code like backend calls, create a regular TypeScript event handler file that sets custom properties in the screen akEvent payload property and then calls the screen frame or window controller callRules() method to execute the screen rules.

Custom Events

The framework provides several entry points in the Corticon execution process:

  • EventBeforeRuleExecution: will be run before the rules are executed
  • EventAfterRuleExecution: will be run after the rules are executed
  • EventAfterRuleApply: will be run after the rules execution payload is processed
  • EventAfterRuleDisplay: will be run after the messages are displayed

The events can be specified from the Corticon 'RulesBehavior' attribute, using properties with the same name as the event.
The event format itself is identical with the other framework events, with 'self' referencing the rules' main window.
The payload is made accessible through the window's akEvent property. (akEvent.rulesExecution.payload)

Custom Properties

As of SWAT 21.14, the vocabularies will be generated with a new custom screen properties entity. (_CustomData.CustomScreenProperties)
By default the entity will be empty, it won't contain any properties.
To add screen properties, the 'RulesBehavior' attribute now accepts a new property 'CustomPropertyObjects', which will contain a comma-separated list of MATCHES patterns for repository data fields.
(ex. "field1,field2,fields*", which will match objects 'field1', 'field2' and
the window rules).all objects starting with 'fields')
All matching data field objects will be processed and a corresponding property will be added to the custom screen properties entity.
The role of this new entity is to provide an easy and accessible way to add custom properties to a vocabulary without risk of losing them on regeneration. (as it happens now for manually added ones)

The custom properties can be assigned from the Corticon custom events and to facilitate this, the following helper functions have been made available:

Code Block
languagejs
themeMidnight
titleHelper functions
linenumberstrue
/**
 * Gets an entity from a given payload
 * @public
 * @static
 * @memberOf Corticon
 * @param {Object} payload The payload
 * @param {string} entityName The entity name
 * @returns {Object} The entity object from the payload or undefined if not found
 */
Corticon.getCustomScreenPropertiesFromPayload(payload);

/**
 * Gets the 'CustomScreenProperties' entity from a given payload
 * @public
 * @static
 * @memberOf Corticon
 * @param {Object} payload The payload
 * @returns {Object} The entity object from the payload or undefined if not found
 */
Corticon.getEntityFromPayload(payload, entityName);

Resources