From adb8d4dde95ec0cf833a82320b21697d70282215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Fri, 3 Nov 2023 14:17:19 +0100 Subject: [PATCH] Re-introduce preorder rank (#290) --- vocabularies/Hierarchy.json | 11 +++++- vocabularies/Hierarchy.md | 74 +++++++++++++++++++------------------ vocabularies/Hierarchy.xml | 11 ++++++ 3 files changed, 59 insertions(+), 37 deletions(-) diff --git a/vocabularies/Hierarchy.json b/vocabularies/Hierarchy.json index 394b2540..b2035e65 100644 --- a/vocabularies/Hierarchy.json +++ b/vocabularies/Hierarchy.json @@ -9,6 +9,9 @@ }, "https://sap.github.io/odata-vocabularies/vocabularies/Common.json": { "$Include": [{ "$Namespace": "com.sap.vocabularies.Common.v1", "$Alias": "Common" }] + }, + "https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Validation.V1.json": { + "$Include": [{ "$Namespace": "Org.OData.Validation.V1", "$Alias": "Validation" }] } }, "com.sap.vocabularies.Hierarchy.v1": { @@ -33,7 +36,7 @@ "RecursiveHierarchyType": { "$Kind": "ComplexType", "@Common.Experimental": true, - "@Core.LongDescription": "The properties in this complex type contain information about\na node in the result set of a hierarchical request. If the same node occurs multiple times\nwith different parents, certain properties may differ between the occurrences.\nThe properties are derived when hierarchical transformations\nare applied whose first parameter has the annotated entity type\nand whose second parameter is the annotation qualifier.\n\nFor requests like\n```\nSalesOrganizations?$apply=\ndescendants(..., ID, filter(ID eq 'US'), keep start)\n/ancestors(..., ID, filter(contains(Name, 'New York')), keep start)\n/Hierarchy.TopLevels(..., NodeProperty='ID', Levels=2)\n&$top=10\n```\nor\n```\nSalesOrganizations?$apply=groupby((rolluprecursive(..., ID,\n descendants(..., ID, filter(ID eq 'US')),\n ancestors(..., ID, filter(contains(Name, 'New York')), keep start))), aggregate(...))\n/Hierarchy.TopLevels(..., NodeProperty='ID', Levels=2)\n&$top=10\n```\n(where `...,` stands for hierarchy nodes and hierarchy qualifier)\nthe following collections of hierarchy nodes are distinguished:\n|Collection|Definition|Value|Where in request|\n|----------|----------|-----|----------------|\n|sub-hierarchy|output set of a `descendants` transformation, possibly embedded in a `rolluprecursive` transformation, that is not preceded by an `ancestors` or `descendants` transformation|US sales organizations|rows 1–2|\n|matching nodes|see [`MatchCount`](#MatchCount)|US sales organizations with \"New York\" in their name|output set of `filter` transformation in row 3|\n|unlimited hierarchy|output set of the last `ancestors`, `descendants` or `traverse` transformation, possibly embedded in a `rolluprecursive` transformation, disregarding numeric fifth parameters|US sales organizations with leaves containing \"New York\"|rows 1–3|\n|limited hierarchy|output set of the last `ancestors`, `descendants`, `traverse` or [`Hierarchy.TopLevels`](#TopLevels) transformation, possibly embedded in a `rolluprecursive` transformation|2 levels of US sales organizations with leaves containing \"New York\"|rows 1–4|\n", + "@Core.LongDescription": "The properties in this complex type contain information about\na node in the result set of a hierarchical request. If the same node occurs multiple times\nwith different parents, certain properties may differ between the occurrences.\nThe properties are derived when hierarchical transformations\nare applied whose first parameter has the annotated entity type\nand whose second parameter is the annotation qualifier.\n\nFor requests like\n```\nSalesOrganizations?$apply=\ndescendants(..., ID, filter(ID eq 'US'), keep start)\n/ancestors(..., ID, filter(contains(Name, 'New York')), keep start)\n/Hierarchy.TopLevels(..., NodeProperty='ID', Levels=2)\n&$top=10\n```\nor\n```\nSalesOrganizations?$apply=groupby((rolluprecursive(..., ID,\n descendants(..., ID, filter(ID eq 'US')),\n ancestors(..., ID, filter(contains(Name, 'New York')), keep start))), aggregate(...))\n/Hierarchy.TopLevels(..., NodeProperty='ID', Levels=2)\n&$top=10\n```\n(where `...,` stands for hierarchy nodes and hierarchy qualifier)\nthe following collections of hierarchy nodes are distinguished:\n\n|Collection|Definition|Value|Where in request|\n|----------|----------|-----|----------------|\n|sub-hierarchy|output set of a `descendants` transformation, possibly embedded in a `rolluprecursive` transformation, that is not preceded by an `ancestors` or `descendants` transformation|US sales organizations|rows 1–2|\n|matching nodes|see [`MatchCount`](#MatchCount)|US sales organizations with \"New York\" in their name|output set of `filter` transformation in row 3|\n|unlimited hierarchy|output set of the last `ancestors`, `descendants` or `traverse` transformation, possibly embedded in a `rolluprecursive` transformation, disregarding numeric fifth parameters|US sales organizations with leaves containing \"New York\"|rows 1–3|\n|limited hierarchy|output set of the last `ancestors`, `descendants`, `traverse` or [`Hierarchy.TopLevels`](#TopLevels) transformation, possibly embedded in a `rolluprecursive` transformation|2 levels of US sales organizations with leaves containing \"New York\"|rows 1–4|\n", "ExternalKey": { "$Nullable": true, "@Core.Description": "Human-readable key value for a node", @@ -70,6 +73,12 @@ "@Core.Description": "Number of ancestors an occurrence of a node has in the limited hierarchy", "@Core.LongDescription": "This equals the number of ancestors in the sub-hierarchy, if the request involves a sub-hierarchy." }, + "LimitedRank": { + "$Type": "Edm.Int64", + "$Nullable": true, + "@Core.Description": "Rank of a node in the limited hierarchy in preorder or postorder", + "@Core.LongDescription": "The rank of a node is the index of the node in the sequence of nodes\n created from a preorder or postorder traversal of the limited hierarchy. The first node in the traversal has rank 0." + }, "SiblingRank": { "$Type": "Edm.Int64", "$Nullable": true, diff --git a/vocabularies/Hierarchy.md b/vocabularies/Hierarchy.md index 52609d98..b092ab03 100644 --- a/vocabularies/Hierarchy.md +++ b/vocabularies/Hierarchy.md @@ -8,27 +8,27 @@ Terms for Hierarchies Term|Type|Description :---|:---|:---------- -[RecursiveHierarchy](./Hierarchy.xml#L38:~:text=Hierarchy-specific information in the result set of a hierarchical request
The [base term](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.html#RecursiveHierarchy) governs what are the nodes and parents in the hierarchy, whereas this term defines derived information. -[RecursiveHierarchyActions](./Hierarchy.xml#L143:~:text=Actions for maintaining the recursive hierarchy defined by the [base term](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.html#RecursiveHierarchy)
When an annotation with this term is present, the [`ParentNavigationProperty`](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.html#RecursiveHierarchyType) in the base term must not have a collection-valued segment prior to its last segment. -[MatchCount](./Hierarchy.xml#L175:~:text=Instance annotation on the result of an `$apply` query option containing the number of matching nodes after hierarchical transformations
The service MAY designate a subset of the `$apply` result as "matching nodes". For requests following the pattern described [here](#RecursiveHierarchyType), this subset is the output set of the `filter` or `search` transformation that occurs as the fourth parameter of the last `ancestors` transformation or occurs nested into it.
For requests not following this pattern, the subset NEED NOT be defined.
This instance annotation is available if [`RecursiveHierarchy/Matched`](#RecursiveHierarchyType) and [`RecursiveHierarchy/MatchedDescendantCount`](#RecursiveHierarchyType) are also available. -[RecursiveHierarchySupported](./Hierarchy.xml#L257:~:text=Whether the annotated collection acts as a [`RecursiveHierarchy`](#RecursiveHierarchy) with the given qualifier
This tag is applied to a collection with the same qualifier as the [`RecursiveHierarchy`](#RecursiveHierarchy) term which is applied to its entity type. The recursive hierarchy can then only be addressed through a collection where this tag is true. +[RecursiveHierarchy](./Hierarchy.xml#L41:~:text=Hierarchy-specific information in the result set of a hierarchical request
The [base term](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.html#RecursiveHierarchy) governs what are the nodes and parents in the hierarchy, whereas this term defines derived information. +[RecursiveHierarchyActions](./Hierarchy.xml#L154:~:text=Actions for maintaining the recursive hierarchy defined by the [base term](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.html#RecursiveHierarchy)
When an annotation with this term is present, the [`ParentNavigationProperty`](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.html#RecursiveHierarchyType) in the base term must not have a collection-valued segment prior to its last segment. +[MatchCount](./Hierarchy.xml#L186:~:text=Instance annotation on the result of an `$apply` query option containing the number of matching nodes after hierarchical transformations
The service MAY designate a subset of the `$apply` result as "matching nodes". For requests following the pattern described [here](#RecursiveHierarchyType), this subset is the output set of the `filter` or `search` transformation that occurs as the fourth parameter of the last `ancestors` transformation or occurs nested into it.
For requests not following this pattern, the subset NEED NOT be defined.
This instance annotation is available if [`RecursiveHierarchy/Matched`](#RecursiveHierarchyType) and [`RecursiveHierarchy/MatchedDescendantCount`](#RecursiveHierarchyType) are also available. +[RecursiveHierarchySupported](./Hierarchy.xml#L268:~:text=Whether the annotated collection acts as a [`RecursiveHierarchy`](#RecursiveHierarchy) with the given qualifier
This tag is applied to a collection with the same qualifier as the [`RecursiveHierarchy`](#RecursiveHierarchy) term which is applied to its entity type. The recursive hierarchy can then only be addressed through a collection where this tag is true. ## Actions -### [Template_ChangeNextSiblingAction](./Hierarchy.xml#L267:~:text=This parameter has properties with the same names as the key properties of the entity type. next(T) = S after the action. If R is a node with next(R) = S before the action, then next(R) = T after the action, even if S = null. It is an error if S has a different parent than T. +**[Node](./Hierarchy.xml#L281:~:text=This parameter has properties with the same names as the key properties of the entity type. next(T) = S after the action. If R is a node with next(R) = S before the action, then next(R) = T after the action, even if S = null. It is an error if S has a different parent than T. -### [Template_CopyAction](./Hierarchy.xml#L301:~:text= -### [TopLevels](./Hierarchy.xml#L203:~:text= -## [RecursiveHierarchyType](./Hierarchy.xml#L47:~:text=If a `NodeType` exists, the external key is unique only in combination with it. Or the external key can coincide with the [`Aggregation.RecursiveHierarchy/NodeProperty`](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.html#RecursiveHierarchyType). -[NodeType](./Hierarchy.xml#L90:~:text=In a recursive hierarchy with mixed types, nodes can
- have a type-specific (navigation) property whose name is the node type or
- be represented by entities of different subtypes of a common entity type that is annotated with the `RecursiveHierarchy` annotation. The qualified name of the subtype is the node type. -[ChildCount](./Hierarchy.xml#L99:~:text=Possible drill states are:
- `expanded` if a node has children in the limited hierarchy
- `collapsed` if a node has children in the unlimited hierarchy but not in the limited hierarchy
- `leaf` if a node has no children in the unlimited hierarchy -[DistanceFromRoot](./Hierarchy.xml#L117:~:text=This equals the number of ancestors in the sub-hierarchy, if the request involves a sub-hierarchy. -[SiblingRank](./Hierarchy.xml#L123:~:text=The sibling rank of a node is the index of the node in the sequence of all nodes in the unlimited hierarchy with the same parent. The first sibling has rank 0. -[Matched](./Hierarchy.xml#L130:~:text=If a `NodeType` exists, the external key is unique only in combination with it. Or the external key can coincide with the [`Aggregation.RecursiveHierarchy/NodeProperty`](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.html#RecursiveHierarchyType). +[NodeType](./Hierarchy.xml#L94:~:text=In a recursive hierarchy with mixed types, nodes can
- have a type-specific (navigation) property whose name is the node type or
- be represented by entities of different subtypes of a common entity type that is annotated with the `RecursiveHierarchy` annotation. The qualified name of the subtype is the node type. +[ChildCount](./Hierarchy.xml#L103:~:text=Possible drill states are:
- `expanded` if a node has children in the limited hierarchy
- `collapsed` if a node has children in the unlimited hierarchy but not in the limited hierarchy
- `leaf` if a node has no children in the unlimited hierarchy +[DistanceFromRoot](./Hierarchy.xml#L121:~:text=This equals the number of ancestors in the sub-hierarchy, if the request involves a sub-hierarchy. +[LimitedRank](./Hierarchy.xml#L127:~:text=The rank of a node is the index of the node in the sequence of nodes created from a preorder or postorder traversal of the limited hierarchy. The first node in the traversal has rank 0. +[SiblingRank](./Hierarchy.xml#L134:~:text=The sibling rank of a node is the index of the node in the sequence of all nodes in the unlimited hierarchy with the same parent. The first sibling has rank 0. +[Matched](./Hierarchy.xml#L141:~:text= -## [RecursiveHierarchyActionsType](./Hierarchy.xml#L151:~:text= -## [TopLevelsExpandType](./Hierarchy.xml#L246:~:text= + + + @@ -72,6 +75,7 @@ SalesOrganizations?$apply=groupby((rolluprecursive(..., ID, ``` (where `...,` stands for hierarchy nodes and hierarchy qualifier) the following collections of hierarchy nodes are distinguished: + |Collection|Definition|Value|Where in request| |----------|----------|-----|----------------| |sub-hierarchy|output set of a `descendants` transformation, possibly embedded in a `rolluprecursive` transformation, that is not preceded by an `ancestors` or `descendants` transformation|US sales organizations|rows 1–2| @@ -120,6 +124,13 @@ the following collections of hierarchy nodes are distinguished: This equals the number of ancestors in the sub-hierarchy, if the request involves a sub-hierarchy. + + + + The rank of a node is the index of the node in the sequence of nodes + created from a preorder or postorder traversal of the limited hierarchy. The first node in the traversal has rank 0. + +