Migrating existing menu structures to the SmartFramework menu
The SmartFramework menu structure is based on two database tables:
- SmartFunction
- SmartMenu
The SmartFunction table defines the functions that can be launched form the menu. Functions can be of various types as described in this article:
http://confluence.consultingwerkcloud.com/wiki/display/SCL/Using+IFunctionCallParameter
The SmartMenu structure is recursive and each leaf is representing a function to be launched refers to a SmartFunction record. As typically for the SmartDB records, the primary unique key fields (SmartFunction.FunctionGuid and SmartMenu.MenuGuid) are auto assigned using database create triggers (in src/SmartDBtrgs). The recursive relation between the SmartMenu records is defined using the SmartMenu.ParentMenuGuid field matching the SmartMenu.MenuGuid record of it’s parent. The root menu structures (the SmartFramework menu may contain multiple top level menu’s) is referencing the empty (“”) ParentMenuGuid value.
Creating SmartFunction records
The essence of the SmartFunction record is a JSON Serialized (XML on OpenEdge 10) object instance implementing the IFunctionCallParameter interface. In order to create an IFunctionCallParameter it’s recommended to create an appropriate object instance (in our sample an RunProcedureCallParameter), assign the object properties and use it’s Serialize() method to return the JSON String which is stored in the SmartFunction.FunctionCallParameter field.
The SmartFunction.FunctionModuleGuid is an optional reference to a SmartModule record (of a SmartProduct record). Those allow a logical grouping of functions into modules.
/* find the module record */ FIND SmartModule WHERE SmartModule.ModuleName = "legacy" . /* create menu function record */ ASSIGN oCallParameter = NEW RunProcedureCallParameter () oCallParameter:AllowMultiple = FALSE oCallParameter:ProcedureName = "windows/cust.w" oCallParameter:RunPersistent = TRUE oCallParameter:InitializeInternalProcedure = "dispatch" oCallParameter:InitializeInternalProcedureParameter = "initialize" oCallParameter:ReactivateInternalProcedure = "dispatch" oCallParameter:ReactivateInternalProcedureParameter = "view" . CREATE SmartFunction . ASSIGN SmartFunction.FunctionName = "Sample function" SmartFunction.FunctionDescription = "Imported menu function" SmartFunction.FunctionModuleGuid = SmartModule.ModuleGuid SmartFunction.FunctionCallParameter = oCallParameter:Serialize() . FIND CURRENT SmartFunction NO-LOCK .
Creating SmartMenu records
The SmartMenu records build the recursive menu structure. When starting to query or create SmartMenu records you either start from the top (a SmartMenu record with ParentMenuGuid = “”) or an existing record. This existing record can be located using DB queries or in the Menu Function Maintenance. The contextual ribbon of the Menu Function Maintenance allows you to copy the MenuGuid of the currently selected menu item to the Windows clipboard so that you can copy it into your source code.
If you are going to create/import nested menu structures you will have to create child and grandchild records of a root menu structure.
/* Create/find menu structure */ /* root menu structrue */ FIND SmartMenu WHERE SmartMenu.ParentMenuGuid = "" AND SmartMenu.MenuName = "Advantzware" NO-LOCK . ASSIGN cRootMenuGuid = SmartMenu.MenuGuid . /* Find or create "master data" menu */ FIND SmartMenu WHERE SmartMenu.ParentMenuGuid = cRootMenuGuid AND SmartMenu.MenuName = "Master data" NO-ERROR . IF NOT AVAILABLE SmartMenu THEN DO: CREATE SmartMenu. ASSIGN SmartMenu.ParentMenuGuid = cRootMenuGuid SmartMenu.MenuName = "Master data" SmartMenu.MenuStructureType = "Menu" . FIND CURRENT SmartMenu NO-LOCK . END. ASSIGN cParentMenuGuid = SmartMenu.MenuGuid . /* Create an item menu structure under master data */ CREATE SmartMenu. ASSIGN SmartMenu.ParentMenuGuid = cParentMenuGuid SmartMenu.MenuName = "Customer" SmartMenu.MenuStructureType = "Item" SmartMenu.FunctionGuid = SmartFunction.FunctionGuid .
Complete sample code
Here's the complete sample code that creates the following entry in the menu structure:
/* *************************** Definitions ************************** */ USING Consultingwerk.SmartFramework.* FROM PROPATH. DEFINE VARIABLE oCallParameter AS RunProcedureCallParameter NO-UNDO . DEFINE VARIABLE cRootMenuGuid AS CHARACTER NO-UNDO. DEFINE VARIABLE cParentMenuGuid AS CHARACTER NO-UNDO. /* *************************** Main Block *************************** */ /* find the module record */ FIND SmartModule WHERE SmartModule.ModuleName = "legacy" . /* create menu function record */ ASSIGN oCallParameter = NEW RunProcedureCallParameter () oCallParameter:AllowMultiple = FALSE oCallParameter:ProcedureName = "windows/cust.w" oCallParameter:RunPersistent = TRUE oCallParameter:InitializeInternalProcedure = "dispatch" oCallParameter:InitializeInternalProcedureParameter = "initialize" oCallParameter:ReactivateInternalProcedure = "dispatch" oCallParameter:ReactivateInternalProcedureParameter = "view" . CREATE SmartFunction . ASSIGN SmartFunction.FunctionName = "Sample function" SmartFunction.FunctionDescription = "Imported menu function" SmartFunction.FunctionModuleGuid = SmartModule.ModuleGuid SmartFunction.FunctionCallParameter = oCallParameter:Serialize() . FIND CURRENT SmartFunction NO-LOCK . /* Create/find menu structure */ /* root menu structrue */ FIND SmartMenu WHERE SmartMenu.ParentMenuGuid = "" AND SmartMenu.MenuName = "Advantzware" NO-LOCK . ASSIGN cRootMenuGuid = SmartMenu.MenuGuid . /* Find or create "master data" menu */ FIND SmartMenu WHERE SmartMenu.ParentMenuGuid = cRootMenuGuid AND SmartMenu.MenuName = "Master data" NO-ERROR . IF NOT AVAILABLE SmartMenu THEN DO: CREATE SmartMenu. ASSIGN SmartMenu.ParentMenuGuid = cRootMenuGuid SmartMenu.MenuName = "Master data" SmartMenu.MenuStructureType = "Menu" . FIND CURRENT SmartMenu NO-LOCK . END. ASSIGN cParentMenuGuid = SmartMenu.MenuGuid . /* Create an item menu structure under master data */ CREATE SmartMenu. ASSIGN SmartMenu.ParentMenuGuid = cParentMenuGuid SmartMenu.MenuName = "Customer" SmartMenu.MenuStructureType = "Item" SmartMenu.FunctionGuid = SmartFunction.FunctionGuid .