diff --git a/vocabularies/Analytics.json b/vocabularies/Analytics.json index 350c4876..3f164f8c 100644 --- a/vocabularies/Analytics.json +++ b/vocabularies/Analytics.json @@ -12,6 +12,9 @@ }, "https://sap.github.io/odata-vocabularies/vocabularies/Common.json": { "$Include": [{ "$Namespace": "com.sap.vocabularies.Common.v1", "$Alias": "Common" }] + }, + "https://sap.github.io/odata-vocabularies/vocabularies/Hierarchy.json": { + "$Include": [{ "$Namespace": "com.sap.vocabularies.Hierarchy.v1", "$Alias": "Hierarchy" }] } }, "com.sap.vocabularies.Analytics.v1": { @@ -161,6 +164,107 @@ "@Validation.ApplicableTerms@Core.Description": "Adding a list of other terms that can be annotated to it.", "@Validation.ApplicableTerms": ["Common.Label"] } + }, + "AutoExpand": [ + { + "$Kind": "Function", + "$EntitySetPath": "InputSet", + "$IsBound": true, + "@Common.Experimental": true, + "@Core.Description": "`$apply` transformation that expands an unnamed leveled hierarchy with custom aggregation of certain properties", + "@Core.LongDescription": "Example transformation sequence:\nfilter on columns `Industry`, `Amount` and `Currency`,\norder by `Amount` descending,\nshow 2 levels, with two exceptions\n```\n$apply=filter(Industry in ('IT','AI'))\n/groupby((Country,Region,Segment,Industry),\n filter($these/aggregate(Amount) gt 0 and\n $these/aggregate(Currency) ne null))\n/concat(\n groupby((Country,Region,Segment,Industry))\n /aggregate($count as LeavesCount),\n aggregate(Amount,Currency),\n Analytics.AutoExpand(\n Levels=[{\"D\":[\"Country\"],\"A\":[\"CountryName\"]},\n {\"D\":[\"Region\"],\"A\":[\"RegionName\"]},\n {\"D\":[\"Segment\",\"Industry\"],\"A\":[]}],\n Aggregation=[\"Amount\",\"Currency\"],\n SiblingOrder=[{\"Property\":\"Amount\",\"Descending\":true}],\n ShowLevels=2,\n ExpandEntries=[{\"Entry\":[\"US\"],\"Levels\":0},\n {\"Entry\":[\"DE\",\"BW\"],\"Levels\":1}]\n )/concat(aggregate($count as ResultEntriesCount),\n skip(20)/top(10)))\n```\n", + "$Parameter": [ + { + "$Name": "InputSet", + "$Collection": true, + "$Type": "Edm.EntityType", + "@Core.Description": "Entity set to be processed" + }, + { + "$Name": "Levels", + "$Collection": true, + "$Type": "Analytics.AutoExpandLevel", + "@Core.Description": "Collection of aggregation levels forming a leveled hierarchy", + "@Core.LongDescription": "Each element in the collection defines the properties that constitute one level.\n A property must not referenced by more than one level.\n The first element in the collection defines the property names of the coarsest level,\n the following elements define the property names of consecutively finer-grained aggregation levels.\n The function result is the leveled hierarchy with these levels in preorder,\n entries on the finest-grained level cannot be expanded further.\n All referenced properties must be groupable." + }, + { + "$Name": "Aggregation", + "$Collection": true, + "@Core.Description": "Properties to aggregate for all result entries on all levels", + "@Core.LongDescription": "All properties in this collection must be custom aggregates." + }, + { + "$Name": "SiblingOrder", + "$Collection": true, + "$Type": "Analytics.AutoExpandSiblingOrder", + "@Core.Description": "Sort specification to apply to all direct descendants of a given entry in the resulting leveled hierarchy" + }, + { + "$Name": "ShowLevels", + "$Type": "Edm.Int64", + "@Core.Description": "Number of levels to be shown in the initial expansion (absent means all levels)", + "@Core.OptionalParameter": {} + }, + { + "$Name": "ExpandEntries", + "$Collection": true, + "$Type": "Analytics.AutoExpandEntry", + "@Core.Description": "Entries with exceptional expansion", + "@Core.OptionalParameter": {} + } + ], + "$ReturnType": { + "$Collection": true, + "$Type": "Edm.EntityType", + "@Core.Description": "Output set including the instance annotation [`LevelInformation`](#LevelInformation)" + } + } + ], + "AutoExpandLevel": { + "$Kind": "ComplexType", + "@Common.Experimental": true, + "@Core.Description": "Property names constituting a level in an [unnamed leveled hierarchy](#AutoExpand)", + "@Core.LongDescription": "Properties in `D` must be used to identify entries in [`ExpandEntries/Entry`](#AutoExpandEntry),\n otherwise they have the same effect as properties in `A`.", + "D": { + "$Collection": true, + "@Core.Description": "A non-empty set of property names that define a combination of dimension values" + }, + "A": { + "$Collection": true, + "@Core.Description": "A possibly empty set of names of additional properties of the dimensions that occur in `D`" + } + }, + "AutoExpandSiblingOrder": { + "$Kind": "ComplexType", + "@Common.Experimental": true, + "@Core.Description": "Sibling order in an [unnamed leveled hierarchy](#AutoExpand)", + "Property": { "@Core.Description": "Property by which to sort" }, + "Descending": { + "$Type": "Edm.Boolean", + "$Nullable": true, + "@Core.Description": "Sort direction, ascending if not specified otherwise" + } + }, + "AutoExpandEntry": { + "$Kind": "ComplexType", + "@Common.Experimental": true, + "@Core.Description": "Expansion state of an entry in an [unnamed leveled hierarchy](#AutoExpand)", + "Entry": { + "$Collection": true, + "@Core.Description": "An entry on a given [level](#AutoExpandLevel) is identified by a collection of values for the `D` properties that constitute all levels up to and including the given one" + }, + "Levels": { + "$Type": "Edm.Int64", + "$Nullable": true, + "@Core.Description": "Number of levels to be expanded, null means all levels, 0 means collapsed" + } + }, + "LevelInformation": { + "$Kind": "Term", + "$Type": "Hierarchy.HierarchyType", + "$AppliesTo": ["EntityType"], + "@Common.Experimental": true, + "@Core.Description": "Information about grouping levels in the result set of a request including the [`AutoExpand`](#AutoExpand) transformation" } } } diff --git a/vocabularies/Analytics.md b/vocabularies/Analytics.md index 757ca5b5..a6f1bf1b 100644 --- a/vocabularies/Analytics.md +++ b/vocabularies/Analytics.md @@ -8,38 +8,115 @@ Terms for annotating analytical resources Term|Type|Description :---|:---|:---------- -[Dimension](Analytics.xml#L41) *(Deprecated)*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|Deprecated in favor of [`AnalyticalContext/Dimension`](#AnalyticalContext) -[Measure](Analytics.xml#L53) *(Deprecated)*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|Deprecated in favor of [`AnalyticalContext/Measure`](#AnalyticalContext) -[AccumulativeMeasure](Analytics.xml#L65) *(Deprecated)*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|Deprecated in favor of [`AnalyticalContext/AccumulativeMeasure`](#AnalyticalContext) -[RolledUpPropertyCount](Analytics.xml#L77) *([Experimental](Common.md#Experimental))*|Int16|Number of properties in the entity instance that have been aggregated away -[DrillURL](Analytics.xml#L83) *([Experimental](Common.md#Experimental))*|URL|URL to retrieve more detailed data related to a node of a recursive hierarchy. Annotations with this term MUST include a qualifier to select the hierarchy for which the drill URL is provided. -[PlanningAction](Analytics.xml#L95) *([Experimental](Common.md#Experimental))*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|Processes or generates plan data. Its logic may have side-effects on entity sets. -[AggregatedProperties](Analytics.xml#L103) *(Deprecated)*|\[[AggregatedPropertyType](#AggregatedPropertyType)\]|Deprecated in favor of [`AggregatedProperty`](#AggregatedProperty) -[AggregatedProperty](Analytics.xml#L121)|[AggregatedPropertyType](#AggregatedPropertyType)|Dynamic property for aggregate expression with specified aggregation method defined on the annotated entity type. -[AnalyticalContext](Analytics.xml#L141)|\[[AnalyticalContextType](#AnalyticalContextType)\]|Collection of properties that define an analytical context +[Dimension](Analytics.xml#L44) *(Deprecated)*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|Deprecated in favor of [`AnalyticalContext/Dimension`](#AnalyticalContext) +[Measure](Analytics.xml#L56) *(Deprecated)*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|Deprecated in favor of [`AnalyticalContext/Measure`](#AnalyticalContext) +[AccumulativeMeasure](Analytics.xml#L68) *(Deprecated)*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|Deprecated in favor of [`AnalyticalContext/AccumulativeMeasure`](#AnalyticalContext) +[RolledUpPropertyCount](Analytics.xml#L80) *([Experimental](Common.md#Experimental))*|Int16|Number of properties in the entity instance that have been aggregated away +[DrillURL](Analytics.xml#L86) *([Experimental](Common.md#Experimental))*|URL|URL to retrieve more detailed data related to a node of a recursive hierarchy. Annotations with this term MUST include a qualifier to select the hierarchy for which the drill URL is provided. +[PlanningAction](Analytics.xml#L98) *([Experimental](Common.md#Experimental))*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|Processes or generates plan data. Its logic may have side-effects on entity sets. +[AggregatedProperties](Analytics.xml#L106) *(Deprecated)*|\[[AggregatedPropertyType](#AggregatedPropertyType)\]|Deprecated in favor of [`AggregatedProperty`](#AggregatedProperty) +[AggregatedProperty](Analytics.xml#L124)|[AggregatedPropertyType](#AggregatedPropertyType)|Dynamic property for aggregate expression with specified aggregation method defined on the annotated entity type. +[AnalyticalContext](Analytics.xml#L144)|\[[AnalyticalContextType](#AnalyticalContextType)\]|Collection of properties that define an analytical context +[LevelInformation](Analytics.xml#L288) *([Experimental](Common.md#Experimental))*|[HierarchyType](Hierarchy.md#HierarchyType)|Information about grouping levels in the result set of a request including the [`AutoExpand`](#AutoExpand) transformation + + +## Functions + + +### [AutoExpand](Analytics.xml#L182) *([Experimental](Common.md#Experimental))* + +`$apply` transformation that expands an unnamed leveled hierarchy with custom aggregation of certain properties + +Example transformation sequence: +filter on columns `Industry`, `Amount` and `Currency`, +order by `Amount` descending, +show 2 levels, with two exceptions +``` +$apply=filter(Industry in ('IT','AI')) +/groupby((Country,Region,Segment,Industry), + filter($these/aggregate(Amount) gt 0 and + $these/aggregate(Currency) ne null)) +/concat( + groupby((Country,Region,Segment,Industry)) + /aggregate($count as LeavesCount), + aggregate(Amount,Currency), + Analytics.AutoExpand( + Levels=[{"D":["Country"],"A":["CountryName"]}, + {"D":["Region"],"A":["RegionName"]}, + {"D":["Segment","Industry"],"A":[]}], + Aggregation=["Amount","Currency"], + SiblingOrder=[{"Property":"Amount","Descending":true}], + ShowLevels=2, + ExpandEntries=[{"Entry":["US"],"Levels":0}, + {"Entry":["DE","BW"],"Levels":1}] + )/concat(aggregate($count as ResultEntriesCount), + skip(20)/top(10))) +``` + + +Parameter|Type|Description +:--------|:---|:---------- +**[InputSet](Analytics.xml#L213)**|\[EntityType\]|**Binding parameter:** Entity set to be processed +[Levels](Analytics.xml#L216)|\[[AutoExpandLevel](#AutoExpandLevel)\]|Collection of aggregation levels forming a leveled hierarchy
Each element in the collection defines the properties that constitute one level. A property must not referenced by more than one level. The first element in the collection defines the property names of the coarsest level, the following elements define the property names of consecutively finer-grained aggregation levels. The function result is the leveled hierarchy with these levels in preorder, entries on the finest-grained level cannot be expanded further. All referenced properties must be groupable. +[Aggregation](Analytics.xml#L228)|\[String\]|Properties to aggregate for all result entries on all levels
All properties in this collection must be custom aggregates. +[SiblingOrder](Analytics.xml#L234)|\[[AutoExpandSiblingOrder](#AutoExpandSiblingOrder)\]|Sort specification to apply to all direct descendants of a given entry in the resulting leveled hierarchy +*[ShowLevels](Analytics.xml#L237)*|Int64|*Optional parameter:* Number of levels to be shown in the initial expansion (absent means all levels) +*[ExpandEntries](Analytics.xml#L243)*|\[[AutoExpandEntry](#AutoExpandEntry)\]|*Optional parameter:* Entries with exceptional expansion +[→](Analytics.xml#L249)|\[EntityType\]|Output set including the instance annotation [`LevelInformation`](#LevelInformation) + -## [AggregatedPropertyType](Analytics.xml#L124) +## [AggregatedPropertyType](Analytics.xml#L127) Property|Type|Description :-------|:---|:---------- -[Name](Analytics.xml#L125)|[SimpleIdentifier](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#SimpleIdentifier)|Name of the dynamic property holding the aggregated value. -[AggregationMethod](Analytics.xml#L128)|[AggregationMethod](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Aggregation.V1.md#AggregationMethod)|Name of the standard or custom aggregation method to be applied. -[AggregatableProperty](Analytics.xml#L131)|PropertyPath|Property whose values shall be aggregated. +[Name](Analytics.xml#L128)|[SimpleIdentifier](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#SimpleIdentifier)|Name of the dynamic property holding the aggregated value. +[AggregationMethod](Analytics.xml#L131)|[AggregationMethod](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Aggregation.V1.md#AggregationMethod)|Name of the standard or custom aggregation method to be applied. +[AggregatableProperty](Analytics.xml#L134)|PropertyPath|Property whose values shall be aggregated. **Applicable Annotation Terms:** - [Label](Common.md#Label) -## [AnalyticalContextType](Analytics.xml#L145) +## [AnalyticalContextType](Analytics.xml#L148) Exactly one of `Property` and `DynamicProperty` must be present Property|Type|Description :-------|:---|:---------- -[Property](Analytics.xml#L147)|PropertyPath?|Property that is part of the analytical context -[DynamicProperty](Analytics.xml#L150)|AnnotationPath?|Dynamic property introduced by annotations that is part of the analytical context
Allowed terms: -[Dimension](Analytics.xml#L159)|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|The property holds the key of a dimension -[Measure](Analytics.xml#L162)|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|The property holds the numeric value of a measure -[AccumulativeMeasure](Analytics.xml#L165)|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|The measure has non-negative and additive values; it can be used in whole-part charts, e.g. the Donut +[Property](Analytics.xml#L150)|PropertyPath?|Property that is part of the analytical context +[DynamicProperty](Analytics.xml#L153)|AnnotationPath?|Dynamic property introduced by annotations that is part of the analytical context
Allowed terms: +[Dimension](Analytics.xml#L162)|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|The property holds the key of a dimension +[Measure](Analytics.xml#L165)|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|The property holds the numeric value of a measure +[AccumulativeMeasure](Analytics.xml#L168)|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|The measure has non-negative and additive values; it can be used in whole-part charts, e.g. the Donut + + +## [AutoExpandLevel](Analytics.xml#L253) *([Experimental](Common.md#Experimental))* +Property names constituting a level in an [unnamed leveled hierarchy](#AutoExpand) + +Properties in `D` must be used to identify entries in [`ExpandEntries/Entry`](#AutoExpandEntry), + otherwise they have the same effect as properties in `A`. + +Property|Type|Description +:-------|:---|:---------- +[D](Analytics.xml#L260)|\[String\]|A non-empty set of property names that define a combination of dimension values +[A](Analytics.xml#L263)|\[String\]|A possibly empty set of names of additional properties of the dimensions that occur in `D` + + +## [AutoExpandSiblingOrder](Analytics.xml#L267) *([Experimental](Common.md#Experimental))* +Sibling order in an [unnamed leveled hierarchy](#AutoExpand) + +Property|Type|Description +:-------|:---|:---------- +[Property](Analytics.xml#L270)|String|Property by which to sort +[Descending](Analytics.xml#L273)|Boolean?|Sort direction, ascending if not specified otherwise + + +## [AutoExpandEntry](Analytics.xml#L277) *([Experimental](Common.md#Experimental))* +Expansion state of an entry in an [unnamed leveled hierarchy](#AutoExpand) + +Property|Type|Description +:-------|:---|:---------- +[Entry](Analytics.xml#L280)|\[String\]|An entry on a given [level](#AutoExpandLevel) is identified by a collection of values for the `D` properties that constitute all levels up to and including the given one +[Levels](Analytics.xml#L283)|Int64?|Number of levels to be expanded, null means all levels, 0 means collapsed diff --git a/vocabularies/Analytics.xml b/vocabularies/Analytics.xml index 104d3991..1115c6da 100644 --- a/vocabularies/Analytics.xml +++ b/vocabularies/Analytics.xml @@ -12,6 +12,9 @@ + + + @@ -176,6 +179,117 @@ + + + + + Example transformation sequence: +filter on columns `Industry`, `Amount` and `Currency`, +order by `Amount` descending, +show 2 levels, with two exceptions +``` +$apply=filter(Industry in ('IT','AI')) +/groupby((Country,Region,Segment,Industry), + filter($these/aggregate(Amount) gt 0 and + $these/aggregate(Currency) ne null)) +/concat( + groupby((Country,Region,Segment,Industry)) + /aggregate($count as LeavesCount), + aggregate(Amount,Currency), + Analytics.AutoExpand( + Levels=[{"D":["Country"],"A":["CountryName"]}, + {"D":["Region"],"A":["RegionName"]}, + {"D":["Segment","Industry"],"A":[]}], + Aggregation=["Amount","Currency"], + SiblingOrder=[{"Property":"Amount","Descending":true}], + ShowLevels=2, + ExpandEntries=[{"Entry":["US"],"Levels":0}, + {"Entry":["DE","BW"],"Levels":1}] + )/concat(aggregate($count as ResultEntriesCount), + skip(20)/top(10))) +``` + + + + + + + + + Each element in the collection defines the properties that constitute one level. + A property must not referenced by more than one level. + The first element in the collection defines the property names of the coarsest level, + the following elements define the property names of consecutively finer-grained aggregation levels. + The function result is the leveled hierarchy with these levels in preorder, + entries on the finest-grained level cannot be expanded further. + All referenced properties must be groupable. + + + + + + All properties in this collection must be custom aggregates. + + + + + + + + + + + + + + + + + + + + + + + + + + Properties in `D` must be used to identify entries in [`ExpandEntries/Entry`](#AutoExpandEntry), + otherwise they have the same effect as properties in `A`. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vocabularies/Hierarchy.json b/vocabularies/Hierarchy.json index 07673fc8..71e6d815 100644 --- a/vocabularies/Hierarchy.json +++ b/vocabularies/Hierarchy.json @@ -33,8 +33,39 @@ "@Core.Description": "Hierarchy-specific information in the result set of a hierarchical request", "@Core.LongDescription": "The [base term](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.html#RecursiveHierarchy)\n governs what are the nodes and parents in the hierarchy, whereas this term defines derived information." }, + "HierarchyType": { + "$Kind": "ComplexType", + "@Common.Experimental": true, + "@Core.LongDescription": "The properties in this complex type contain information about\n an entry in the result set of a request with multiple aggregation levels, some of which are expanded.\n These properties also serve in the derived [`RecursiveHierarchyType`](#RecursiveHierarchyType)\n with their definitions rephrased in the concept of recursive hierarchies.", + "LimitedDescendantCount": { + "$Type": "Edm.Int64", + "$Nullable": true, + "@Core.Description": "Number of entries from finer-grained aggregation levels that are expanded" + }, + "DrillState": { + "$Nullable": true, + "@Core.Description": "Drill state of an entry", + "@Validation.AllowedValues": [ + { + "Value": "expanded", + "@Core.Description": "The entry precedes entries from finer-grained aggregation levels" + }, + { "Value": "leaf", "@Core.Description": "The entry belongs to the finest-grained aggregation level" }, + { + "Value": "collapsed", + "@Core.Description": "The entry belongs to the coarsest-grained non-expanded aggregation level, but is not a leaf" + } + ] + }, + "DistanceFromRoot": { + "$Type": "Edm.Int64", + "$Nullable": true, + "@Core.Description": "Position of the current aggregation level in the list of all aggregation levels" + } + }, "RecursiveHierarchyType": { "$Kind": "ComplexType", + "$BaseType": "Hierarchy.HierarchyType", "@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\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": { @@ -47,16 +78,6 @@ "@Core.Description": "Type of a node", "@Core.LongDescription": "In a recursive hierarchy with mixed types, nodes can\n- have a type-specific (navigation) property whose name is the node type or\n- be represented by entities of different subtypes of a common entity type that is\n\nannotated with the `RecursiveHierarchy` annotation. The qualified name of the subtype is the node type." }, - "ChildCount": { - "$Type": "Edm.Int64", - "$Nullable": true, - "@Core.Description": "Number of children a node has in the unlimited hierarchy" - }, - "DescendantCount": { - "$Type": "Edm.Int64", - "$Nullable": true, - "@Core.Description": "Number of descendants a node has in the unlimited hierarchy" - }, "LimitedDescendantCount": { "$Type": "Edm.Int64", "$Nullable": true, @@ -65,7 +86,14 @@ "DrillState": { "$Nullable": true, "@Core.Description": "Drill state of an occurrence of a node", - "@Core.LongDescription": "Possible drill states are:\n
- `expanded` if a node has children in the limited hierarchy\n
- `collapsed` if a node has children in the unlimited hierarchy but not in the limited hierarchy\n
- `leaf` if a node has no children in the unlimited hierarchy" + "@Validation.AllowedValues": [ + { "Value": "expanded", "@Core.Description": "The node has children in the limited hierarchy" }, + { + "Value": "collapsed", + "@Core.Description": "The node has children in the unlimited hierarchy but not in the limited hierarchy" + }, + { "Value": "leaf", "@Core.Description": "The node has no children in the unlimited hierarchy" } + ] }, "DistanceFromRoot": { "$Type": "Edm.Int64", @@ -73,6 +101,16 @@ "@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." }, + "ChildCount": { + "$Type": "Edm.Int64", + "$Nullable": true, + "@Core.Description": "Number of children a node has in the unlimited hierarchy" + }, + "DescendantCount": { + "$Type": "Edm.Int64", + "$Nullable": true, + "@Core.Description": "Number of descendants a node has in the unlimited hierarchy" + }, "LimitedRank": { "$Type": "Edm.Int64", "$Nullable": true, @@ -107,6 +145,7 @@ }, "RecursiveHierarchyActionsType": { "$Kind": "ComplexType", + "@Common.Experimental": true, "@Core.LongDescription": "The qualified action names identify actions for maintaining nodes in the recursive hierarchy,\nwhich are specific for the given annotation qualifier.\nThese actions MUST have the same signature as the template actions linked below, with\n`Edm.EntityType` replaced with the entity type on which the recursive hierarchy is defined.\nThe resource path of the binding parameter MUST traverse the hierarchy collection,\nincluding any hierarchy directory. If the resource path contains a Content ID reference to an earlier request,\nthe hierarchy directory MUST be determined from the resource path of that request.\n```json\n{\"requests\": [{\n \"id\": \"1\",\n \"method\": \"post\",\n \"url\": \"HierarchyDirectory(1)/Nodes\",\n \"body\": {\n \"Name\": \"child of A\",\n \"Superordinate@odata.bind\": \"Nodes('A')\"\n }\n}, {\n \"id\": \"2\",\n \"dependsOn\": [\"1\"],\n \"method\": \"post\",\n \"url\": \"$1/Hierarchy.ChangeNextSiblingAction\",\n \"body\": {\n \"NextSibling\": null\n }\n}]}\n```\nThe template actions themselves cannot be invoked.", "ChangeNextSiblingAction": { "$Type": "Common.QualifiedName", diff --git a/vocabularies/Hierarchy.md b/vocabularies/Hierarchy.md index 3824a443..c8c231d9 100644 --- a/vocabularies/Hierarchy.md +++ b/vocabularies/Hierarchy.md @@ -9,26 +9,26 @@ Terms for Hierarchies Term|Type|Description :---|:---|:---------- [RecursiveHierarchy](Hierarchy.xml#L41) *([Experimental](Common.md#Experimental))*|[RecursiveHierarchyType](#RecursiveHierarchyType)|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#L155) *([Experimental](Common.md#Experimental))*|[RecursiveHierarchyActionsType](#RecursiveHierarchyActionsType)|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#L209) *([Experimental](Common.md#Experimental))*|Int64|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#L293) *([Experimental](Common.md#Experimental))*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|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. +[RecursiveHierarchyActions](Hierarchy.xml#L199) *([Experimental](Common.md#Experimental))*|[RecursiveHierarchyActionsType](#RecursiveHierarchyActionsType)|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#L254) *([Experimental](Common.md#Experimental))*|Int64|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#L338) *([Experimental](Common.md#Experimental))*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|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#L303) *([Experimental](Common.md#Experimental))* +### [Template_ChangeNextSiblingAction](Hierarchy.xml#L348) *([Experimental](Common.md#Experimental))* Template for actions that move a node among its siblings and are named in [`RecursiveHierarchyActions/ChangeNextSiblingAction`](#RecursiveHierarchyActionsType) Parameter|Type|Description :--------|:---|:---------- -**[Node](Hierarchy.xml#L306)**|EntityType|**Binding parameter:** The node T to be moved -[NextSibling](Hierarchy.xml#L309)|ComplexType?|Key of the node's new next sibling S (null if the node shall become the last sibling)
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#L351)**|EntityType|**Binding parameter:** The node T to be moved +[NextSibling](Hierarchy.xml#L354)|ComplexType?|Key of the node's new next sibling S (null if the node shall become the last sibling)
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#L337) *([Experimental](Common.md#Experimental))* +### [Template_CopyAction](Hierarchy.xml#L382) *([Experimental](Common.md#Experimental))* Template for actions that copy a node and its descendants and are named in [`RecursiveHierarchyActions/CopyAction`](#RecursiveHierarchyActionsType) @@ -52,15 +52,15 @@ by a PATCH that binds the parent navigation property (for example, `Superordinat Parameter|Type|Description :--------|:---|:---------- -**[Node](Hierarchy.xml#L359)**|EntityType|**Binding parameter:** The node to be copied -[→](Hierarchy.xml#L362)|EntityType|The copied node +**[Node](Hierarchy.xml#L404)**|EntityType|**Binding parameter:** The node to be copied +[→](Hierarchy.xml#L407)|EntityType|The copied node ## Functions -### [TopLevels](Hierarchy.xml#L239) *([Experimental](Common.md#Experimental))* +### [TopLevels](Hierarchy.xml#L284) *([Experimental](Common.md#Experimental))* Returns the first n levels of a hierarchical collection in preorder with individual nodes expanded or collapsed @@ -76,18 +76,36 @@ This function can be used as a transformation whose input set has a recursive hi Parameter|Type|Description :--------|:---|:---------- -**[InputSet](Hierarchy.xml#L253)**|\[EntityType\]|**Binding parameter** -[HierarchyNodes](Hierarchy.xml#L254)|\[EntityType\]|A collection, given through a `$root` expression -[HierarchyQualifier](Hierarchy.xml#L257)|[HierarchyQualifier](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Aggregation.V1.md#HierarchyQualifier)| -[NodeProperty](Hierarchy.xml#L258)|String|Property path to the node identifier, evaluated relative to the binding parameter -*[Levels](Hierarchy.xml#L261)*|Int64|*Optional parameter:* The number n of levels to be output, absent means all levels -*[Show](Hierarchy.xml#L268)*|\[String\]|*Optional parameter:* Identifiers of nodes to be shown -*[ExpandLevels](Hierarchy.xml#L274)*|\[[TopLevelsExpandType](#TopLevelsExpandType)\]|*Optional parameter:* Nodes to be expanded -[→](Hierarchy.xml#L280)|\[EntityType\]| +**[InputSet](Hierarchy.xml#L298)**|\[EntityType\]|**Binding parameter** +[HierarchyNodes](Hierarchy.xml#L299)|\[EntityType\]|A collection, given through a `$root` expression +[HierarchyQualifier](Hierarchy.xml#L302)|[HierarchyQualifier](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Aggregation.V1.md#HierarchyQualifier)| +[NodeProperty](Hierarchy.xml#L303)|String|Property path to the node identifier, evaluated relative to the binding parameter +*[Levels](Hierarchy.xml#L306)*|Int64|*Optional parameter:* The number n of levels to be output, absent means all levels +*[Show](Hierarchy.xml#L313)*|\[String\]|*Optional parameter:* Identifiers of nodes to be shown +*[ExpandLevels](Hierarchy.xml#L319)*|\[[TopLevelsExpandType](#TopLevelsExpandType)\]|*Optional parameter:* Nodes to be expanded +[→](Hierarchy.xml#L325)|\[EntityType\]| + +## [HierarchyType](Hierarchy.xml#L50) *([Experimental](Common.md#Experimental))* + + +The properties in this complex type contain information about + an entry in the result set of a request with multiple aggregation levels, some of which are expanded. + These properties also serve in the derived [`RecursiveHierarchyType`](#RecursiveHierarchyType) + with their definitions rephrased in the concept of recursive hierarchies. + +**Derived Types:** +- [RecursiveHierarchyType](#RecursiveHierarchyType) + +Property|Type|Description +:-------|:---|:---------- +[LimitedDescendantCount](Hierarchy.xml#L58)|Int64?|Number of entries from finer-grained aggregation levels that are expanded +[DrillState](Hierarchy.xml#L61)|String?|Drill state of an entry
Allowed values:
[expanded](Hierarchy.xml#L65)
The entry precedes entries from finer-grained aggregation levels
[leaf](Hierarchy.xml#L69)
The entry belongs to the finest-grained aggregation level
[collapsed](Hierarchy.xml#L73)
The entry belongs to the coarsest-grained non-expanded aggregation level, but is not a leaf
+[DistanceFromRoot](Hierarchy.xml#L80)|Int64?|Position of the current aggregation level in the list of all aggregation levels + -## [RecursiveHierarchyType](Hierarchy.xml#L50) *([Experimental](Common.md#Experimental))* +## [RecursiveHierarchyType](Hierarchy.xml#L84): [HierarchyType](#HierarchyType) *([Experimental](Common.md#Experimental))* The properties in this complex type contain information about @@ -126,20 +144,20 @@ the following collections of hierarchy nodes are distinguished: Property|Type|Description :-------|:---|:---------- -[ExternalKey](Hierarchy.xml#L87)|String?|Human-readable key value for a node
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)|String?|Type of a node

In a recursive hierarchy with mixed types, nodes can

annotated with the RecursiveHierarchy annotation. The qualified name of the subtype is the node type.

-[ChildCount](Hierarchy.xml#L104)|Int64?|Number of children a node has in the unlimited hierarchy -[DescendantCount](Hierarchy.xml#L107)|Int64?|Number of descendants a node has in the unlimited hierarchy -[LimitedDescendantCount](Hierarchy.xml#L110)|Int64?|Number of descendants a node has in the limited hierarchy -[DrillState](Hierarchy.xml#L113)|String?|Drill state of an occurrence of a node
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#L122)|Int64?|Number of ancestors an occurrence of a node has in the limited hierarchy
This equals the number of ancestors in the sub-hierarchy, if the request involves a sub-hierarchy. -[LimitedRank](Hierarchy.xml#L128)|Int64?|Rank of a node in the limited hierarchy in preorder or postorder
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#L135)|Int64?|Sibling rank of a node
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#L142)|Boolean?|Flag indicating [matching](#MatchCount) nodes -[MatchedDescendantCount](Hierarchy.xml#L145)|Int64?|Number of [matching](#MatchCount) descendants a node has in the unlimited hierarchy +[ExternalKey](Hierarchy.xml#L121)|String?|Human-readable key value for a node
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#L128)|String?|Type of a node

In a recursive hierarchy with mixed types, nodes can

annotated with the RecursiveHierarchy annotation. The qualified name of the subtype is the node type.

+[LimitedDescendantCount](Hierarchy.xml#L138)|Int64?|Number of descendants a node has in the limited hierarchy +[DrillState](Hierarchy.xml#L141)|String?|Drill state of an occurrence of a node
Allowed values:
[expanded](Hierarchy.xml#L145)
The node has children in the limited hierarchy
[collapsed](Hierarchy.xml#L149)
The node has children in the unlimited hierarchy but not in the limited hierarchy
[leaf](Hierarchy.xml#L153)
The node has no children in the unlimited hierarchy
+[DistanceFromRoot](Hierarchy.xml#L160)|Int64?|Number of ancestors an occurrence of a node has in the limited hierarchy
This equals the number of ancestors in the sub-hierarchy, if the request involves a sub-hierarchy. +[ChildCount](Hierarchy.xml#L166)|Int64?|Number of children a node has in the unlimited hierarchy +[DescendantCount](Hierarchy.xml#L169)|Int64?|Number of descendants a node has in the unlimited hierarchy +[LimitedRank](Hierarchy.xml#L172)|Int64?|Rank of a node in the limited hierarchy in preorder or postorder
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#L179)|Int64?|Sibling rank of a node
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#L186)|Boolean?|Flag indicating [matching](#MatchCount) nodes +[MatchedDescendantCount](Hierarchy.xml#L189)|Int64?|Number of [matching](#MatchCount) descendants a node has in the unlimited hierarchy -## [RecursiveHierarchyActionsType](Hierarchy.xml#L163) +## [RecursiveHierarchyActionsType](Hierarchy.xml#L207) *([Experimental](Common.md#Experimental))* The qualified action names identify actions for maintaining nodes in the recursive hierarchy, @@ -172,15 +190,15 @@ The template actions themselves cannot be invoked. Property|Type|Description :-------|:---|:---------- -[ChangeNextSiblingAction](Hierarchy.xml#L193)|[QualifiedName?](Common.md#QualifiedName)|Action that moves a node among its siblings, following [this template](#Template_ChangeNextSiblingAction) -[ChangeSiblingForRootsSupported](Hierarchy.xml#L201)|Boolean|Whether the sibling of a root can be changed -[CopyAction](Hierarchy.xml#L204)|[QualifiedName?](Common.md#QualifiedName)|Action that copies a node and its descendants, following [this template](#Template_CopyAction) +[ChangeNextSiblingAction](Hierarchy.xml#L238)|[QualifiedName?](Common.md#QualifiedName)|Action that moves a node among its siblings, following [this template](#Template_ChangeNextSiblingAction) +[ChangeSiblingForRootsSupported](Hierarchy.xml#L246)|Boolean|Whether the sibling of a root can be changed +[CopyAction](Hierarchy.xml#L249)|[QualifiedName?](Common.md#QualifiedName)|Action that copies a node and its descendants, following [this template](#Template_CopyAction) -## [TopLevelsExpandType](Hierarchy.xml#L282) *([Experimental](Common.md#Experimental))* +## [TopLevelsExpandType](Hierarchy.xml#L327) *([Experimental](Common.md#Experimental))* Information about nodes to be expanded Property|Type|Description :-------|:---|:---------- -[NodeID](Hierarchy.xml#L285)|String|Identifier of a node to be expanded -[Levels](Hierarchy.xml#L288)|Int64?|Number of levels to be expanded, null means all levels, 0 means collapsed +[NodeID](Hierarchy.xml#L330)|String|Identifier of a node to be expanded +[Levels](Hierarchy.xml#L333)|Int64?|Number of levels to be expanded, null means all levels, 0 means collapsed diff --git a/vocabularies/Hierarchy.xml b/vocabularies/Hierarchy.xml index 9788f382..aa962850 100644 --- a/vocabularies/Hierarchy.xml +++ b/vocabularies/Hierarchy.xml @@ -47,7 +47,41 @@ governs what are the nodes and parents in the hierarchy, whereas this term defines derived information. - + + + + The properties in this complex type contain information about + an entry in the result set of a request with multiple aggregation levels, some of which are expanded. + These properties also serve in the derived [`RecursiveHierarchyType`](#RecursiveHierarchyType) + with their definitions rephrased in the concept of recursive hierarchies. + + + + + + + + + + + + + + + + + + + + + + + + + + + + The properties in this complex type contain information about @@ -101,22 +135,26 @@ the following collections of hierarchy nodes are distinguished: annotated with the `RecursiveHierarchy` annotation. The qualified name of the subtype is the node type. - - - - - - - - Possible drill states are: - <br>- `expanded` if a node has children in the limited hierarchy - <br>- `collapsed` if a node has children in the unlimited hierarchy but not in the limited hierarchy - <br>- `leaf` if a node has no children in the unlimited hierarchy + + + + + + + + + + + + + + + @@ -125,6 +163,12 @@ annotated with the `RecursiveHierarchy` annotation. The qualified name of the su This equals the number of ancestors in the sub-hierarchy, if the request involves a sub-hierarchy. + + + + + + @@ -161,6 +205,7 @@ annotated with the `RecursiveHierarchy` annotation. The qualified name of the su + The qualified action names identify actions for maintaining nodes in the recursive hierarchy, which are specific for the given annotation qualifier.