Menu tree construction¶
Menu tree construction builds and maintains the two-level hierarchy that the presentation layer renders as the application menu: clsMenuPage records group toolbar buttons and links under an application, and clsMenuItem records are the individual tree nodes assigned to a page and a category. Both objects follow the standard BOF CRUD lifecycle — retrieve by key or in full, insert with a sequence-generated key, update, and delete — each governed by the row-count contention check.
| Field | Value |
|---|---|
| Operation ID | OP-MNU-01 |
| Trigger | Caller requests clsMenuItem/clsMenuItemCollection or clsMenuPage/clsMenuPageCollection by key or in full, or calls Save() after Create()/retrieve |
| Inputs | MenuItemSeqNum / MenuPageSeqNum (key lookups); for insert/update — page/category association, tooltip text, visibility flag, page order, application code, page link, and toolbar-button flags/tooltips |
| Outputs | Populated clsMenuItem/clsMenuItemCollection or clsMenuPage/clsMenuPageCollection; on save, a new sequence-generated key or updated row; error messages on DML contention |
| Primary components | clsMenuItem, clsMenuItemCollection, clsMenuPage, clsMenuPageCollection |
| Entry point | Business\SAIF.Business.Menu\clsMenuItem.vb, Business\SAIF.Business.Menu\clsMenuPage.vb |
Steps¶
- Retrieve a single menu item.
clsMenuItem.GetMenuItemcreates aCriteriawith the requestedMenuItemSeqNumand invokes the data portal, which runsBeforeRetrieveto bind:MenuItemSeqNumand executeRetrieveSQL(SQL-022, MENU_ITEM).AfterRetrievefills the object from the reader and marks it old. MenuPageandMenuCategoryare lazy-loaded read-only properties: the first access triggersclsMenuPage.GetMenuPage(SQL-024) orclsMenuCategoryCode.GetMenuCategoryCoderespectively.SecurityGroupsis likewise lazy-loaded viaclsMenuSecurityCollection.GetMenuSecuritiesForItem(SQL-027).- Retrieve the full item collection.
clsMenuItemCollection.GetAllMenuItemsexecutes the unfilteredRetrieveSQL(SQL-023, MENU_ITEM) and loads oneclsMenuItemper row viaAfterRetrieve. - Retrieve a single page or the full page collection.
clsMenuPage.GetMenuPageandclsMenuPageCollection.GetAllMenuPagesfollow the identical by-key (SQL-024) and all-rows (SQL-025) pattern against MENU_PAGE. - Create a new menu item.
clsMenuItem.NewMenuItemcallsCreate(), which invokesBeforeCreate/AfterCreate: a scalar request executesSELECT MENU_ITEM_SEQ.NEXTVAL FROM DUAL(SQL-002, DUAL), and the returned value seedsMenuItemSeqNumon both the object and its criteria before the object is marked new and clean. - Save (insert) the new item.
IsValidchecksMyBase.IsValidand the validity of the lazily-loadedSecurityGroupschild collection beforeSave()/SaveChild()proceeds.BeforeInsertbinds the page, category, visible flag, page order, tooltip, and the acting user (DataPortalInfo.UserID, upper-cased), then executesInsertSQL(SQL-008, MENU_ITEM). - On success (
RowsAffected = 1):AfterInsertcallsMarkOld()and, ifSecurityGroups.IsDirty,SaveChildObject(SecurityGroups)cascades the save to the child security collection (BR-MNU-02). - On failure (
RowsAffected <> 1):Me.AddErrorMessage("InsertError", "Insert Failed")is added; the save is rejected. - Save (insert) a new menu page.
clsMenuPage.NewMenuPage/AfterCreateobtainsMENU_PAGE_SEQ.NEXTVAL(SQL-003, DUAL);BeforeInsertassembles the insert withStringBuilderacross all page fields (page name, link, application code, favorite name, and every toolbar flag/tooltip) and executesInsertSQL(SQL-009, MENU_PAGE). - On a rows-affected value other than
1:AddErrorMessage("InsertError", ...)(BR-MNU-02). - Update an existing item or page.
BeforeUpdaterebinds all mutable fields plus the primary key and executesUpdateSQL(SQL-034 for items, SQL-035 for pages).AfterUpdateapplies the same row-count contention check, callingMarkOld()on success orAddErrorMessage("UpdateError", BOC.Messages.DBContentionError)on failure (BR-MNU-02). - Delete an item or page.
BeforeDeletebinds the key and executesDeleteSQL(SQL-041 for items, SQL-042 for pages).AfterDeletecallsMarkNew()on a rows-affected value of1, or adds aDeleteErrorotherwise (BR-MNU-02). - Assemble the tree. The presentation layer combines the retrieved item and page collections — joining items to their parent page via
MenuPageSeqNumand to their category viaMenuCategoryCode— to render the hierarchical menu. This assembly step is performed by the consuming presentation layer, not within this library.*
Process flow¶
The following diagram visualizes the retrieve/save control flow shared by clsMenuItem and clsMenuPage.
flowchart TD
Start([Caller requests item/page<br>by key, all, or new]) --> Which{Operation?}
Which -->|Retrieve by key| RetKey[Execute RetrieveSQL<br>with key parameter]
RetKey --> Fill[Fill object from reader;<br>MarkOld]
Which -->|Retrieve all| RetAll[Execute unfiltered RetrieveSQL]
RetAll --> FillEach[Load one object per row]
Which -->|Create new| Seq[Obtain NEXTVAL from<br>MENU_ITEM_SEQ / MENU_PAGE_SEQ]
Seq --> MarkNewClean[Seed key; MarkNew; MarkClean]
MarkNewClean --> SaveCall{Save called?}
SaveCall -->|Yes| Insert[Execute InsertSQL]
Insert --> Rows{RowsAffected = 1?}
Rows -->|Yes| Ok([MarkOld; cascade child save])
Rows -->|No| Err([AddErrorMessage: InsertError])
Failure and edge-case behavior¶
- Every insert, update, and delete on
clsMenuItemandclsMenuPageenforces a strict rows-affected-equals-1 check; any other value raisesInsertError,UpdateError, orDeleteErrorand the object is not marked clean (BR-MNU-02). clsMenuItem.IsValidandIsDirtyboth cascade into the lazily-loadedSecurityGroupschild collection, so a dirty or invalid security-group child blocks or flags the parent item even if the item's own fields are unchanged.- The child
SecurityGroupscollection is only saved whenSecurityGroups.IsDirtyis true and the parent insert/update succeeded; if the parent DML fails, the child save is skipped entirely. clsMenuPage's insert/update SQL is assembled withStringBuilderacross roughly twenty columns; a mismatch between the assembled parameter list and the bound parameters would surface only at execution time, not through compile-time checking.*- Presentation-layer tree assembly (joining items to pages and categories) is not implemented in this library; if the page or category referenced by an item's foreign key is deleted independently, the tree assembly step must handle the resulting orphaned reference.*
Related documentation¶
Note: Statements marked with
*were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.
Sources¶
Business\SAIF.Business.Menu\clsMenuItem.vbBusiness\SAIF.Business.Menu\clsMenuItemCollection.vbBusiness\SAIF.Business.Menu\clsMenuPage.vbBusiness\SAIF.Business.Menu\clsMenuPageCollection.vb