Action and Group Overriding

Suppose you have two different roles, Manager and Employee, for which you are designing a menu system. The menus will look much the same but with a few key differences. For example, you might have a reports folder that contains different versions of the same report depending on the user. You could define the menus like this:

<ModuleUiMetaModel>
<WebInfo>
<WebAction name="PhoneBook">
<URL>/oms/public/phonebook.html</URL>
</WebAction>
 
<WebAction name="PhoneBookForManagers">
<URL>/oms/public/phonebookformanager.html</URL>
</WebAction>
<WebAction name="ReportA">
<!-- omitted -->
</WebAction>
<WebAction name="ReportB">
<!-- omitted -->
</WebAction>
<WebActionGroup name="Reports">
<WebActionRef name="PhoneBook"/> <!-- default version -->
<WebActionRef name="ReportA"/>
<WebActionRef name="ReportB"/>
</WebActionGroup>
<WebActionGroup name="ReportsForManagers">
<WebActionRef name="PhoneBookForManagers"/> <!-- manager version -->
<WebActionRef name="ReportA"/>
<WebActionRef name="ReportB"/>
</WebActionGroup>
<RoleTypeUiConfig>
<RoleTypeRef>
<CustomRoleTypeName>Employee</CustomRoleTypeName>
</RoleTypeRef>
<WebActionGroupRef name="Reports"/>
</RoleTypeUiConfig>
<RoleTypeUiConfig>
<RoleTypeRef>
<CustomRoleTypeName>Manager</CustomRoleTypeName>
</RoleTypeRef>
<WebActionGroupRef name="ReportsForManagers"/>
</RoleTypeUiConfig>
</WebInfo>
</ModuleUiMetaModel>

You can easily see how a situation like this can become difficult to maintain. Currently, the only difference between the two WebActionGroups is one report.

The UI Meta Model allows for you to define an action and then define one or more "variations" for that action which will be resolved based upon the user requesting the menu. As an example, we could define the base "PhoneBook" report and then define a variation that will only be used by the Manager role as in the following example:

<ModuleUiMetaModel>
<WebInfo>
 
<WebAction name="PhoneBook">
<URL>/oms/public/phonebook.html</URL>
</WebAction>
 
<WebAction name="ReportA">
<!-- omitted -->
</WebAction>
 
<WebAction name="ReportB">
<!-- omitted -->
</WebAction>
 
<!-- custom phonebook report for managers -->
<WebActionVariation name="PhoneBook">
<Context property="RoleName" value="Manager"/>
<URL>/oms/public/phonebookformanager.html</URL>
</WebActionVariation>
 
<WebActionGroup name="Reports">
<WebActionRef name="PhoneBook"/>
<WebActionRef name="ReportA"/>
<WebActionRef name="ReportB"/>
</WebActionGroup>
 
<RoleTypeUiConfig>
<RoleTypeRef>
<CustomRoleTypeName>Employee</CustomRoleTypeName>
</RoleTypeRef>
<WebActionGroupRef name="Reports"/>
</RoleTypeUiConfig>
 
<RoleTypeUiConfig>
<RoleTypeRef>
<CustomRoleTypeName>Manager</CustomRoleTypeName>
</RoleTypeRef>
<WebActionGroupRef name="Reports"/>
</RoleTypeUiConfig>
 
</WebInfo>
</ModuleUiMetaModel>

This allows us to maintain a single "Reports" folder which is used in both RoleTypeUiConfig. With this configuration, we could define additional variations based on many different properties (in ascending order of specificity): RoleName, RoleTypeName, EntName, OrgName, or even as specific as ValueChainId.

What if we wanted to add another report that only managers should get? Without any kind of variation at the WebActionGroup level, you would end up with a UI Meta Model which looks like this:

<ModuleUiMetaModel>
<WebInfo>
 
<WebAction name="PhoneBook">
<!-- omitted -->
</WebAction>
 
<WebAction name="ReportA">
<!-- omitted -->
</WebAction>
 
<WebAction name="ReportB">
<!-- omitted -->
</WebAction>
 
<!-- manager-only report -->
<WebAction name="MyEmployeesReport">
<!-- omitted -->
</WebAction>
<!-- custom phonebook report for managers -->
<WebActionVariation name="PhoneBook">
<Context property="RoleName" value="Manager"/>
<URL>/oms/public/phonebookformanager.html</URL>
</WebActionVariation>
<WebActionGroup name="Reports">
<WebActionRef name="PhoneBook"/>
<WebActionRef name="ReportA"/>
<WebActionRef name="ReportB"/>
</WebActionGroup>
 
<WebActionGroup name="ReportsForManagers">
<WebActionRef name="PhoneBook"/>
<WebActionRef name="ReportA"/>
<WebActionRef name="ReportB"/>
<WebActionRef name="MyEmployeesReport"/>
</WebActionGroup>
<RoleTypeUiConfig>
<RoleTypeRef>
<CustomRoleTypeName>Employee</CustomRoleTypeName>
</RoleTypeRef>
<WebActionGroupRef name="Reports"/>
</RoleTypeUiConfig>
 
<RoleTypeUiConfig>
<RoleTypeRef>
<CustomRoleTypeName>Manager</CustomRoleTypeName>
</RoleTypeRef>
<WebActionGroupRef name="ReportsForManagers"/>
</RoleTypeUiConfig>
 
</WebInfo>
</ModuleUiMetaModel>

Again, we are back in a situation where you would need to define a separate WebActionGroup for each role when the only difference is one additional report.

Fortunately, you can also define variation on WebActionGroups, as the next example shows:

<ModuleUiMetaModel>
<WebInfo>
<WebAction name="PhoneBook">
<!-- omitted -->
</WebAction>
 
<WebAction name="ReportA">
<!-- omitted -->
</WebAction>
 
<WebAction name="ReportB">
<!-- omitted -->
</WebAction>
 
<!-- manager-only report -->
<WebAction name="MyEmployeesReport">
<!-- omitted -->
</WebAction>
 
<!-- custom phonebook report for managers -->
<WebActionVariation name="PhoneBook">
<Context property="RoleName" value="Manager"/>
<URL>/oms/public/phonebookformanager.html</URL>
</WebActionVariation>
<WebActionGroup name="Reports">
<WebActionRef name="PhoneBook"/>
<WebActionRef name="ReportA"/>
<WebActionRef name="ReportB"/>
</WebActionGroup>
 
<WebActionGroupVariation name="Reports">
<Context property="RoleName" value="Manager"/>
<WebActionRef name="PhoneBook"/>
<WebActionRef name="ReportA"/>
<WebActionRef name="ReportB"/>
<WebActionRef name="MyEmployeesReport"/>
</WebActionGroupVariation>
 
<RoleTypeUiConfig>
<RoleTypeRef>
<CustomRoleTypeName>Employee</CustomRoleTypeName>
</RoleTypeRef>
<WebActionGroupRef name="Reports"/>
</RoleTypeUiConfig>
 
<RoleTypeUiConfig>
<RoleTypeRef>
<CustomRoleTypeName>Manager</CustomRoleTypeName>
</RoleTypeRef>
<WebActionGroupRef name="Reports"/>
</RoleTypeUiConfig>
 
</WebInfo>
</ModuleUiMetaModel>

Note that when defining WebActionGroupVariations, you can include any child elements you would normally include in a WebActionGroup, including WebActionRefs, WebActionGroups, WebActionGroupRefs, and MenuDividers.

With this new variation, we can have one WebActionGroup which contains different actions based on which user is looking at it. Additionally, you can see that both variations, the default, and the Manager version, contain a WebActionRef to an action that also has a variation. All of these variations will be resolved when the UI requests the menu; all variations will be resolved to the most specific variation. This allows for a high degree of flexibility and reuse when you define your menus.

WebActionGroupInjection

WebActionGroupInjection is a better version of WebActionGroupVariation. Using WebActionGroupInjection, developers can add (inject) menus in existing WebActionGroups:

<WebActionGroupInjection name="Reports">
<Context property="RoleName" value="Manager"/>
<WebActionRef name="MyEmployeesReport"/>
</WebActionGroupInjection>

With this configuration, the MyEmployeesReport will be added as the last menu in the Reports menu group for the Manager role. If a menu needs to be added in between menu lists, then use the following:

<WebActionGroupInjection name="Reports">
<Context property="RoleName" value="Manager"/>
<WebActionRef name="MyEmployeesReport" insertBefore="ReportB"/>
</WebActionGroupInjection>

In the above example, the MyEmployeesReport is added before the ReportB menu.

Unlike WebActionGroupVariation, multiple modules can define WebActionGroupInjection for the same WebActionGroup, and all qualified injections are applied. Qualified injections are WebActionGroupInjection which contain <Context> information that is more specific for the logged-in user.

WebActionGroupVariation and WebActionGroupInjection can be specified in the module that declares the WebActionGroup or can be added in modules depending upon the WebActionGroup the module contains.

The following table lists the supported values for the Property attribute in <Context>:

Value

Description

RoleName

Specifies the name of the role. For example, CarrierTransportationManager.

RoleTypeName

Specifies the role type name. For example, TMS.TRANSPORTATION_MANAGER.

EntName

Specifies the enterprise name of the used role.

OrgName

Specifies the organization name of the used role.

ValueChainId

Specifies the value chain id of the used role.