User Tools

Site Tools


rulemanager_abc_template_implementation.htm
Navigation:  ABC Library Reference > RuleManager >====== RuleManager ABC Template Implementation ====== Previous pageReturn to chapter overviewNext page

Three templates support the use of the Rule Manager classes. They are:

·The Global Business Rules Manager, which establishes logical connections between business rules and particular table columns, other fields, and controls.

·The Local Business Rules Manager, which implements global rules wherever relevant items are populated and allows for the addition of local rules having effect in only one procedure. The Local Business Rules Manager is automatically added to every procedure in any application which contains the Global Business Rules Manager.

·A code template, the Error Handler for Business Rules, which provides enhanced functionality where needed.

RuleManager Source Files

The Rule Manager Classes source code is installed by default to the Clarion \LIBSRC folder. The Rule Manager source code and its respective components are contained in:

ABRULE.INC Rule Manager Class declarations
ABRULE.CLW Rule Manager Class method definitions

RuleManager Conceptual Example

The following example shows a typical sequence of statements to declare, instantiate, initialize, use and terminate a RulesCollection and related Rule objects in a standard ABC Window procedure. This example defines several rules and checks them at critical points. Each rule is bound to a specific control (this is optional) and when the rule is checked and found to be broken, a graphic error indicator is displayed next to the associated control. The OK button is disabled when there are broken rules.

Example:

  MEMBER('app.clw')             ! This is a MEMBER module
 INCLUDE('ABRULES.INC'),ONCE
 INCLUDE('ABTOOLBA.INC'),ONCE
 INCLUDE('ABWINDOW.INC'),ONCE
 MAP
  INCLUDE('APP001.INC'),ONCE     !Local module procedure declarations
 END
Main PROCEDURE                    !Generated from procedure template - Window
CusName              STRING(20)
CusAddress           STRING(20)
CusPhone             STRING(10)
CustomerRules &RuleManager        !Rule manager for Rules for the customer
Window WINDOW('Example of using RulesManager'),AT(,,169,124), FONT(,,,,CHARSET:ANSI),|
      GRAY,DOUBLE
       SHEET,AT(3,4,159,116),USE(?Sheet1)
        TAB('Customer Info'),USE(?Tab1)
         SHEET,AT(8,26,149,62),USE(?Sheet2)
          TAB('Name'),USE(?Tab3)
           ENTRY(@s20),AT(51,55,60,10),USE(CusName),IMM
           PROMPT('Cus Name:'),AT(13,55),USE(?CusName:Prompt)
          END
          TAB('Address'),USE(?Tab4)
           PROMPT('Cus Address:'),AT(12,53),USE(?CusAddress:Prompt)
           ENTRY(@s20),AT(69,53,60,10),USE(CusAddress),IMM
          END
          TAB('Phone'),USE(?Tab5)
           PROMPT('Cus Phone:'),AT(12,52),USE(?CusPhone:Prompt)
           ENTRY(@s10),AT(69,50,60,10),USE(CusPhone),IMM
          END
         END
        BUTTON('OK'),AT(118,96,32,14),USE(?Button:OK),STD(STD:Close)
        BUTTON('View Customer Broken Rules'),AT(8,95,101,14),USE(?Button:ListAll)
       END
      END
     END
ThisWindow           CLASS(WindowManager)
Init                   PROCEDURE(),BYTE,PROC,DERIVED
Kill                   PROCEDURE(),BYTE,PROC,DERIVED
TakeAccepted           PROCEDURE(),BYTE,PROC,DERIVED
TakeFieldEvent         PROCEDURE(),BYTE,PROC,DERIVED
TakeNewSelection       PROCEDURE(),BYTE,PROC,DERIVED
                    END
Toolbar              ToolbarClass
 CODE
 GlobalResponse = ThisWindow.Run()
ThisWindow.Init PROCEDURE
ReturnValue          BYTE,AUTO
 CODE
 GlobalErrors.SetProcedureName('Main')
 SELF.Request = GlobalRequest
 ReturnValue = PARENT.Init()
 !Bind the variables used by RulesManager
 BIND('CusName',CusName)                             !RulesManager Hotfield
 BIND('CusAddress',CusAddress)                       !RulesManager Hotfield
 BIND('CusPhone',CusPhone)                           !RulesManager Hotfield
 !Define RulesManager
 CustomerRules &= New(RuleManager)
 CustomerRules.SetErrorImage('~SMCROSS.ICO')
 CustomerRules.SetDescription('Rules for the customer')
 !Defining rules in RulesManager
 CustomerRules.AddRule|
 ('CusNameReq','Customer name is required','len(clip(CusName))>0',?CusName,3)
 CustomerRules.AddRule|
 ('Addreq','Customer address is required','len(Clip(CusAddress))',?CusAddress,3)
 CustomerRules.AddRule('PhoneReq','Phone is required','Len(Clip(CusPhone))>0',?CusPhone,3)
 IF ReturnValue THEN RETURN ReturnValue.
 SELF.FirstField = ?CusName
 SELF.VCRRequest &= VCRRequest
 SELF.Errors &= GlobalErrors
 SELF.AddItem(Toolbar)
 CLEAR(GlobalRequest)
 CLEAR(GlobalResponse)
 OPEN(Window)
 SELF.Opened=True
 !Check all Rules in RulesManager and show error indicators
 CustomerRules.CheckAllRules(1)                      
 SELF.SetAlerts()
 RETURN ReturnValue
ThisWindow.Kill PROCEDURE
ReturnValue          BYTE,AUTO
 CODE
 ReturnValue = PARENT.Kill()
 IF ReturnValue THEN RETURN ReturnValue.
 GlobalErrors.SetProcedureName
 !UnBind the variables used by RulesManager
 UNBIND('CusName')                                   !RulesManager Hotfield
 UNBIND('CusAddress')                                !RulesManager Hotfield
 UNBIND('CusPhone')                                  !RulesManager Hotfield
 Dispose(CustomerRules)
 RETURN ReturnValue
ThisWindow.TakeAccepted PROCEDURE
ReturnValue          BYTE,AUTO
Looped BYTE
 CODE
 !Pass the Accepted control to RulesManager for processing in case
 !the control clicked was an error indicator. If it was an error indicator,
 !a MessageBox containing the description of the broken rule will be displayed
 CustomerRules.TakeAccepted(Accepted())              
 LOOP
   IF Looped
     RETURN Level:Notify
   ELSE
     Looped = 1
   END
 ReturnValue = PARENT.TakeAccepted()
   CASE ACCEPTED()
   OF ?Button:ListAll
    ThisWindow.Update
!This will Cause a window to popup that contains a list of all broken rules, and if
!the user double clicked one of the rules in the list, the relevant control will be selected.
Select(CustomerRules.EnumerateBrokenRules|
(CustomerRules.GetDescription(),CustomerRules.GetErrorImage()))
   END
   RETURN ReturnValue
 END
 ReturnValue = Level:Fatal
 RETURN ReturnValue
ThisWindow.TakeFieldEvent PROCEDURE
ReturnValue          BYTE,AUTO
Looped BYTE
 CODE
 LOOP
   IF Looped
     RETURN Level:Notify
   ELSE
     Looped = 1
   END
   !Disable the save button if there are any broken rules
   ?Button:OK{Prop:Disable} = CustomerRules.BrokenRuleCount()
   !Hide the ListAll button if there are no broken rules
   ?Button:ListAll{Prop:Hide} = Choose(CustomerRules.BrokenRuleCount() = 0)
   ReturnValue = PARENT.TakeFieldEvent()
   RETURN ReturnValue
 END
 ReturnValue = Level:Fatal
 RETURN ReturnValue
ThisWindow.TakeNewSelection PROCEDURE
ReturnValue          BYTE,AUTO
Looped BYTE
 CODE
 LOOP
   IF Looped
     RETURN Level:Notify
   ELSE
     Looped = 1
   END
   ReturnValue = PARENT.TakeNewSelection()
   CASE FIELD()
   OF ?CusName
     UPDATE
     CustomerRules.CheckRule('CusNameReq',1)    !Checking for broken rule in RulesManager
   OF ?CusAddress
     UPDATE
     CustomerRules.CheckRule('AddReq',1)        !Checking for broken rule in RulesManager
   OF ?CusPhone
     UPDATE
     CustomerRules.CheckRule('PhoneReq',1)      !Checking for broken rule in RulesManager
   END
   RETURN ReturnValue
 END
 ReturnValue = Level:Fatal
 RETURN ReturnValue

Implementation Steps using hand code

Although there is a powerful template that is included with Clarion to help you implement the RuleManager, there are times when you may need to hand code its properties and methods into your source. The following are the recommend steps to implementing the RuleManager in your hand coded projects.

1. Identify specific rules and assign each rule a name. For example, if Cus:Name is required, call it CusNameReq.

2. For each rule, write a line of code that returns the value of TRUE when the rule is unbroken. For example, if Cus:Name is required, the corresponding code will be:

LEN(Clip(Cus:Name)) > 0

If Cus:Address is required if Cus:Name <;> “Unknown”, the corresponding code will be

Choose(Upper(Clip(Cus:Name))<;<;>UNKNOWN and len(Clip(Cus:Address))=0,0,1)

3. Bind all of the variables used in each expression.

BIND('Cus:Name',Cus:Name)

BIND('Cus:Address',Cus:Address)

4. Define a RuleManager Object.

CustomerRules &amp;RuleManager

5. Instantiate the RuleManager Object

CustomerRules &amp;= New(RuleManager)

CustomerRules.SetErrorImage('~SMCROSS.ICO')

CustomerRules.SetDescription('Rules for the customer')

6. Define the rules for the RulesManager

CustomerRules.AddRule('CusNameReq','Customer name is required' ,|

'len(clip(CusName))>0',?CusName,3)

!A small button with the icon SMCROSS.ICO' will be displayed 3 pixels to the left of !?CusName when the expression evaluates to false

CustomerRules.AddRule|

('Addreq','Customer address is required if customer name is not “Unknown”',|

'Choose(Upper(Clip(CusName))<;<;>UNKNOWN and | len(Clip(CusAddress))=0,0,1)',?CusAddress,3)

!A small button with the icon SMCROSS.ICO' will be displayed 3 pixels to the left of !?CusAddress when the expression evaluates to false

7. Check the rules.

CustomerRules.CheckAllRules(1)  !Checks all the rules

CustomerRules.CheckRule('CusNameReq',1) !Checks specific rule

8. Trap a mouseclick on the error indicator button.

CustomerRules.TakeAccepted(Accepted())

!If a description is provided with the corresponding error, a message !with the corresponding error will appear

9. Count the Broken Rules.

?OK{Prop:Disable} = CustomerRules.BrokenRuleCount()

!The ?OK button is disabled when there are broken rules

10. View All Broken Rules.

Select(CustomerRules.EnumerateBrokenRules|

(CustomerRules.GetDescription(),CustomerRules.GetErrorImage()))

!Call a popup listbox of broken rules, and use the default RulesManager icon as an icon. !If the user double clicks one of the broken rules, the corresponding control will be !selected.

rulemanager_abc_template_implementation.htm.txt · Last modified: 2021/04/15 15:57 by 127.0.0.1