Refer to the javax.baja.hierarchy API.
Hierarchies provide a dynamic navigation layer to the Niagara Framework. By using neql to query tags and relations, they allow for the creation navigation trees that are not based on the station’s config.bog tree structure.
Hierarchies are defined under the BHierarchyService and the resulting hierarchy is shown in the BHierarchySpace.
The HierarchyService
contains the definitions for each hierarchy in the system. These are the sets of rules for creating navigational hierarchies. Each hierarchy is defined by a BHierarchy and one or more BLevelDefs. The ordering of the BLevelDef
s under a BHierarchy
define the order in which they’re used to create the hierarchy. Each BLevelDef
defines a level of a hierarchy where each node at that level uses the same rules for creation and determining its children.
The Niagara Framework provides four BLevelDef
s for creating hierarchies. These are divided into two basic types: grouping and entity. The two grouping definitions, BListLevelDef and BGroupLevelDef implement the BIGroupingLevelDef marker interface. These create virtual groups or folders of entities in the navigational hierarchy. They are not typically used for leafs in the tree so they will not typically be the last BLevelDef
under a BHierarchy
.
BGroupLevelDef
uses Tag values to create groupings in a hierarchy. For each unique value of the given BGroupLevelDef.groupBy
Tag
in the system, a node will be created in the hierarchy. It is important to note that BGroupLevelDef.groupBy
is a single Tag.id
and not a neql query.
BListLevelDef
also creates groupings in a hierarchy. Unlike BGroupLevelDef
where the groupings are dynamic, BListLevelDef
creates a static list of groups using BNamedGroupDefs. Each BNamedGroupDef
creates a node in the resulting hierarchy and filters the entities under it based on the the defined query.
The two entity level definitions, BQueryLevelDef and BRelationLevelDef, populate the hierarchy with entity nodes. Typically these are BComponents. BQueryLevelDef
uses a neql query to determine which entities to display in the hierarchy. By default, the results are filtered against any preceding BIGroupingLevelDef
s in the hierarchy definition. If this is not desired, the includeGroupingQueries
property can be set to false
.
BRelationLevelDef
uses Relation traversal to determine the displayed entities. Starting from the previous entity in the hierarchy, the relations specified by the relationId
are traversed and the entities at the endpoints
of those Relation
s are displayed in the hierarchy. Given this, a BRelationLevelDef
will always be preceded by a BQueryLevelDef
in the BHierarchy
in order to define the Entity being traversed from. By default, inbound relations with the given relationId
are followed. Outbound relations can be used instead by setting inbound
to false
. The set of returned entities can be further filtered by setting a neql expression in the filterExpression
property. If repeatRelation
is true
, additional levels will be created in the hierarchy each time that defined relation is able to be traversed from the endpoint of the previous relation - a typical use of this is to traverse n:child
relations to the end of the component tree.
Several properties are common to all BLevelDef
s. The use of the queryContext
property is discussed in the Doc Hierarchies Guide. sort
, a BLevelSort, can be set to either BLevelSort.ascending
or BLevelSort.descending
. hierarchyTags
are currently reserved for future use.
A useful tool when working with hierarchies is to turn on logging. Setting the hierarchy
log to FINE
under the DebugService
will log the neql query that is run to produce each level of a hierarchy when that level is expanded under the HierarchySpace
.
Hierarchies have a scope. What this means is that the queries used to produce a hierarchy can be run against one or more BSpaces. As of Niagara 4.0, the only supported space is the Station space. To add additional spaces in the future, one or more BHierarchyScopes can be added to the BHierarchyScopeContainer in the BHierarchy
. The scopeOrd
is simply the BOrdScheme for the desired space.
In order for users to be able to view a hierarchy, they need permissions to do so. When the BHierarchyService
is added to a station, the BRoleHierarchies BIMixIn is added to each BRole as the viewableHierarchies
property. BRoleHierarchies.hierarchyNames
is a comma separated list of the BHierarchyDef
names that the BRole
has permissions to view.
Hierarchies are displayed under the HierarchySpace
. Each BHierarchyDef
results in a child of the BHierarchySpace
. These children of the Hierarchy Space, and the their children, are BLevelElems. BLevelElem
s implement BINavNode and are traversed using BINavNode.getNavChildren()
and BINavNode.getNavParent()
.
The HierarchyOrdScheme defines hierarchy:
as the BOrdScheme for resolving BLevelElem
s in a hierarchy. A HierarchyQuery is used for the body of the BOrd.
Note that since each part of a HierarchyQuery
may result in a neql query being executed, hierarchy: Ord resolution may be very expensive. If hierarchy: Ords need to be resolved, developers should consider caching the results for improved performance.
The following code samples assume that you have hierarchies defined with given names and are provided as a getting started point.
BHierarchySpace hierarchySpace = (BHierarchySpace)BOrd.make("hierarchy:").get(rootComponent);
BLevelElem sampleHierarchy = (BLevelElem)BOrd.make("hierarchy:SampleHierarchy").get(rootComponent);
Even though hierarchy definitions exist in the station, the resulting hierarchies only exist in the client environment. Given this, Ord resolutions will only work in the client environment. To resolve hierarchy: Ord in the station, we need to use an alternative method. BHierarchyService.resolveHierarchyLevelElem()
allows us to resolve HierarchiesQueries in the station VM.
BHierarchyService hierarchyService = (BHierarchyService)BOrd.make("service:hierarchy:HierarchyService").get(rootComponent);
BLevelElem sampleHierarchy = hierarchyService.resolveHierarchyLevelElem(new HierarchyQuery("/sampleHierarchy"));
Hierarchy traversal is best accomplished by treating BLevelElem
s as BINavNode
s.
BLevelElem sampleHierarchy = (BLevelElem)BOrd.make("hierarchy:SampleHierarchy").get(rootComponent);
BINavNode[] firstLevelChildren = sampleHierarchy.getNavChildren();
for (int i=0; i<firstLevelChildren.length; i++)
{
System.out.println(firstLevelChildren[i].getNavDisplayName(null));
}
Copyright © 2000-2019 Tridium Inc. All rights reserved.