Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RetrieveFunction and UpdateAction for aggregated entities #212

Open
wants to merge 39 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
653936c
UpdateAction
HeikoTheissen Dec 15, 2022
b6577f3
result payload
HeikoTheissen Dec 15, 2022
b390da3
`Aggregate` parameter non-nullable
HeikoTheissen Dec 15, 2022
81c048c
Is this sufficiently cryptic?
HeikoTheissen Dec 15, 2022
f77cf1d
corrected example
HeikoTheissen Dec 15, 2022
34c9e6c
renamed parameter Changes -> Updates
HeikoTheissen Dec 15, 2022
8321dff
make example self-contained
HeikoTheissen Dec 15, 2022
95c1b93
Merge remote-tracking branch 'origin/main' into updateAction
HeikoTheissen Dec 15, 2022
470b169
prettier
HeikoTheissen Dec 15, 2022
a726b47
Merge remote-tracking branch 'origin/main' into updateAction
HeikoTheissen Jan 10, 2023
aa3c87d
auto-refreshed
HeikoTheissen Jan 10, 2023
1750082
weak example reference
HeikoTheissen Feb 23, 2023
295c84d
Effect of $search on RecursiveHierarchy (#182)
HeikoTheissen Feb 24, 2023
fd634e4
No need to base64-encode string parameters
HeikoTheissen Mar 3, 2023
32cf8f6
Revert "No need to base64-encode string parameters"
HeikoTheissen Mar 3, 2023
5c1a506
Suggestion by Nicolas Lunet (#235)
HeikoTheissen Mar 10, 2023
3667180
RetrieveFunction
HeikoTheissen Mar 16, 2023
8acd423
Correct type for term
HeikoTheissen Mar 16, 2023
2013a73
AppliesTo
HeikoTheissen Mar 20, 2023
7b81c5a
Merge remote-tracking branch 'origin/main' into
HeikoTheissen Apr 12, 2023
b9b8ea3
Merge remote-tracking branch 'origin/main' into aggregation-cs03-rele…
HeikoTheissen Apr 12, 2023
a9c1de8
OptionalParameter cannot have default value []
HeikoTheissen Apr 14, 2023
bd83e11
Merge remote-tracking branch 'origin/main' into aggregation-cs03-rele…
HeikoTheissen Apr 27, 2023
38eacf5
Merge remote-tracking branch 'origin/main' into aggregation-cs03-rele…
HeikoTheissen Apr 27, 2023
691b6d1
Expand all levels (#237)
HeikoTheissen Apr 28, 2023
9e30fc1
Merge remote-tracking branch 'origin/main' into aggregation-cs03-rele…
HeikoTheissen May 23, 2023
9500b9c
Merge branch 'aggregation-cs03-release-candidate' of [email protected]:S…
HeikoTheissen May 23, 2023
47ad2a4
Actions for creating and moving hierarchy nodes (#247)
HeikoTheissen Jul 7, 2023
66a9c92
Action -> Function
HeikoTheissen Aug 8, 2023
141e7d3
auto-refreshed
HeikoTheissen Aug 8, 2023
58c7d54
Merge remote-tracking branch 'origin/aggregation-cs03-release-candidate'
HeikoTheissen Aug 8, 2023
650cdab
Merge branch 'updateAction' of [email protected]:SAP/odata-vocabularies.git
HeikoTheissen Aug 8, 2023
a3eb69b
entity type -> entity set
HeikoTheissen Aug 8, 2023
a199ef7
Instance annotations for recursive hierarchies (#258)
HeikoTheissen Sep 5, 2023
c79bbb9
NextSibling has complex type
HeikoTheissen Sep 8, 2023
2cc2758
Common.QualifiedName
HeikoTheissen Sep 8, 2023
71921da
Merge remote-tracking branch 'origin/aggregation-cs03-release-candidate'
HeikoTheissen Sep 8, 2023
d731fa4
revert
HeikoTheissen Sep 8, 2023
004c094
revert
HeikoTheissen Sep 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions examples/Analytics.AggregateEntity-result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"@odata.context": "$metadata#Sales",
"value": [
{
"Customer": {
"Country": "Netherlands"
},
"Product": {
"Name": "Paper"
},
"Amount": 3,
"@Analytics.AggregateEntity": {
"Aggregate": "Z3JvdXBieSgoQ3VzdG9tZXIvQ291bnRyeSxQcm9kdWN0L05hbWUpLGFnZ3JlZ2F0ZShBbW91bnQpKS9maWx0ZXIoQ3VzdG9tZXIvQ291bnRyeSBlcSAnTmV0aGVybGFuZHMnIGFuZCBQcm9kdWN0L05hbWUgZXEgJ1BhcGVyJyk=",
"RetrieveFunctionImport": "RetrieveAggregateSales",
"UpdateActionImport": "UpdateAggregateSales",
"UpdatableProperties": ["Amount"]
}
},
{
"Customer": {
"Country": "Netherlands"
},
"Product": {
"Name": "Sugar"
},
"Amount": 2,
"@Analytics.AggregateEntity": {
"Aggregate": "Z3JvdXBieSgoQ3VzdG9tZXIvQ291bnRyeSxQcm9kdWN0L05hbWUpLGFnZ3JlZ2F0ZShBbW91bnQpKS9maWx0ZXIoQ3VzdG9tZXIvQ291bnRyeSBlcSAnTmV0aGVybGFuZHMnIGFuZCBQcm9kdWN0L05hbWUgZXEgJ1N1Z2FyJyk=",
"RetrieveFunctionImport": "RetrieveAggregateSales",
"UpdateActionImport": "UpdateAggregateSales",
"UpdatableProperties": ["Amount"]
}
},
{
"Customer": {
"Country": "USA"
},
"Product": {
"Name": "Coffee"
},
"Amount": 12,
"@Analytics.AggregateEntity": {
"Aggregate": "Z3JvdXBieSgoQ3VzdG9tZXIvQ291bnRyeSxQcm9kdWN0L05hbWUpLGFnZ3JlZ2F0ZShBbW91bnQpKS9maWx0ZXIoQ3VzdG9tZXIvQ291bnRyeSBlcSAnVVNBJyBhbmQgUHJvZHVjdC9OYW1lIGVxICdDb2ZmZWUnKQ==",
"RetrieveFunctionImport": "RetrieveAggregateSales",
"UpdateActionImport": "UpdateAggregateSales",
"UpdatableProperties": ["Amount"]
}
},
{
"Customer": {
"Country": "USA"
},
"Product": {
"Name": "Paper"
},
"Amount": 5,
"@Analytics.AggregateEntity": {
"Aggregate": "Z3JvdXBieSgoQ3VzdG9tZXIvQ291bnRyeSxQcm9kdWN0L05hbWUpLGFnZ3JlZ2F0ZShBbW91bnQpKS9maWx0ZXIoQ3VzdG9tZXIvQ291bnRyeSBlcSAnVVNBJyBhbmQgUHJvZHVjdC9OYW1lIGVxICdQYXBlcicp",
"RetrieveFunctionImport": "RetrieveAggregateSales",
"UpdateActionImport": "UpdateAggregateSales",
"UpdatableProperties": ["Amount"]
}
},
{
"Customer": {
"Country": "USA"
},
"Product": {
"Name": "Sugar"
},
"Amount": 2,
"@Analytics.AggregateEntity": {
"Aggregate": "Z3JvdXBieSgoQ3VzdG9tZXIvQ291bnRyeSxQcm9kdWN0L05hbWUpLGFnZ3JlZ2F0ZShBbW91bnQpKS9maWx0ZXIoQ3VzdG9tZXIvQ291bnRyeSBlcSAnVVNBJyBhbmQgUHJvZHVjdC9OYW1lIGVxICdTdWdhcicp",
"RetrieveFunctionImport": "RetrieveAggregateSales",
"UpdateActionImport": "UpdateAggregateSales",
"UpdatableProperties": ["Amount"]
}
}
]
}
73 changes: 73 additions & 0 deletions examples/Analytics.AggregateEntity-sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"$Version": "4.0",
"$Reference": {
"https://sap.github.io/odata-vocabularies/vocabularies/Analytics.json": {
"$Include": [{ "$Namespace": "com.sap.vocabularies.Analytics.v1", "$Alias": "Analytics" }]
},
"https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.json": {
"$Include": [{ "$Namespace": "Org.OData.Aggregation.V1", "$Alias": "Aggregation" }]
}
},
"example.Analytics.AggregateEntity": {
"$Alias": "SalesModel",
"Customer": {
"$Kind": "EntityType",
"$Key": ["ID"],
"ID": {},
"Name": { "$Nullable": true },
"Country": { "$Nullable": true }
},
"Product": {
"$Kind": "EntityType",
"$Key": ["ID"],
"ID": {},
"Name": { "$Nullable": true },
"Color": { "$Nullable": true },
"TaxRate": { "$Type": "Edm.Decimal", "$Nullable": true, "$Scale": 2 }
},
"Sale": {
"$Kind": "EntityType",
"$Key": ["ID"],
"ID": {},
"Amount": { "$Type": "Edm.Decimal", "$Nullable": true, "$Scale": 2 },
"Product": { "$Kind": "NavigationProperty", "$Type": "SalesModel.Product", "$Nullable": true },
"Customer": { "$Kind": "NavigationProperty", "$Type": "SalesModel.Customer", "$Nullable": true }
},
"UpdateAggregateSales": [
{
"$Kind": "Action",
"@Core.Description": "Updates an aggregate entity in the `Sales` entity set",
"$Parameter": [
{ "$Name": "Aggregate", "@Core.Description": "String identifying the aggregate entity to be updated" },
{
"$Name": "Updates",
"$Type": "SalesModel.Sale",
"@Core.Description": "Aggregate entity with nested properties that are to be updated, like the body of a PATCH request"
}
],
"$ReturnType": { "$Type": "SalesModel.Sale", "@Core.Description": "Aggregate entity with updates applied" }
}
],
"RetrieveAggregateSales": [
{
"$Kind": "Function",
"@Core.Description": "Retrieves an aggregate entity in the `Sales` entity set",
"$Parameter": [
{ "$Name": "Aggregate", "@Core.Description": "String identifying the aggregate entity to be retrieved" }
],
"$ReturnType": { "$Type": "SalesModel.Sale" }
}
],
"container": {
"$Kind": "EntityContainer",
"Sales": {
"$Collection": true,
"$Type": "SalesModel.Sale",
"@Aggregation.CustomAggregate#Amount": "Edm.Decimal"
},
"UpdateAggregateSales": { "$Action": "SalesModel.UpdateAggregateSales", "$EntitySet": "Sales" },
"RetrieveAggregateSales": { "$Function": "SalesModel.RetrieveAggregateSales", "$EntitySet": "Sales" }
}
},
"$EntityContainer": "example.Analytics.AggregateEntity.container"
}
66 changes: 66 additions & 0 deletions examples/Analytics.AggregateEntity-sample.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
<edmx:Reference Uri="https://sap.github.io/odata-vocabularies/vocabularies/Analytics.xml">
<edmx:Include Namespace="com.sap.vocabularies.Analytics.v1" Alias="Analytics" />
</edmx:Reference>
<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.xml">
<edmx:Include Namespace="Org.OData.Aggregation.V1" Alias="Aggregation" />
</edmx:Reference>

<edmx:DataServices>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="example.Analytics.AggregateEntity" Alias="SalesModel">
<EntityType Name="Customer">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Edm.String" Nullable="false" />
<Property Name="Name" Type="Edm.String" />
<Property Name="Country" Type="Edm.String" />
</EntityType>
<EntityType Name="Product">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Edm.String" Nullable="false" />
<Property Name="Name" Type="Edm.String" />
<Property Name="Color" Type="Edm.String" />
<Property Name="TaxRate" Type="Edm.Decimal" Scale="2"/>
</EntityType>
<EntityType Name="Sale">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Edm.String" Nullable="false" />
<Property Name="Amount" Type="Edm.Decimal" Scale="2" />
<NavigationProperty Name="Product" Type="SalesModel.Product" />
<NavigationProperty Name="Customer" Type="SalesModel.Customer"/>
</EntityType>
<Action Name="UpdateAggregateSales">
<Annotation Term="Core.Description" String="Updates an aggregate entity in the `Sales` entity set" />
<Parameter Name="Aggregate" Type="Edm.String" Nullable="false">
<Annotation Term="Core.Description" String="String identifying the aggregate entity to be updated" />
</Parameter>
<Parameter Name="Updates" Type="SalesModel.Sale" Nullable="false">
<Annotation Term="Core.Description" String="Aggregate entity with nested properties that are to be updated, like the body of a PATCH request" />
</Parameter>
<ReturnType Type="SalesModel.Sale" Nullable="false">
<Annotation Term="Core.Description" String="Aggregate entity with updates applied" />
</ReturnType>
</Action>
<Function Name="RetrieveAggregateSales">
<Annotation Term="Core.Description" String="Retrieves an aggregate entity in the `Sales` entity set" />
<Parameter Name="Aggregate" Type="Edm.String" Nullable="false">
<Annotation Term="Core.Description" String="String identifying the aggregate entity to be retrieved" />
</Parameter>
<ReturnType Type="SalesModel.Sale" Nullable="false" />
</Function>
<EntityContainer Name="container">
<EntitySet Name="Sales" EntityType="SalesModel.Sale">
<Annotation Term="Aggregation.CustomAggregate" Qualifier="Amount" String="Edm.Decimal" />
</EntitySet>
<ActionImport Name="UpdateAggregateSales" Action="SalesModel.UpdateAggregateSales" EntitySet="Sales" />
<FunctionImport Name="RetrieveAggregateSales" Function="SalesModel.RetrieveAggregateSales" EntitySet="Sales" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
45 changes: 45 additions & 0 deletions vocabularies/Analytics.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,51 @@
"@Core.Description": "The measure has non-negative and additive values; it can be used in whole-part charts, e.g. the Donut"
}
},
"AggregateEntity": {
"$Kind": "Term",
"$Type": "Analytics.AggregateEntityType",
"$AppliesTo": ["EntityType"],
"@Common.Experimental": true,
"@Common.IsInstanceAnnotation": true,
"@Core.Description": "Function and action for retrieving and updating an aggregate entity",
"@Core.LongDescription": "Transient entities that result from the application of a transformation sequence represent an\n aggregate of persistent entities (for example, aggregate sales per country and product, as in [OData-Data-Agg-v4.0], first example in simple grouping section).\n Such a transient entity may be annotated with this term to describe<br>\n - a service-defined function import that can be used to retrieve the transient entity in order to `$expand` additional properties<br>\n - a service-defined action import that can be used to update the transient entity. This effectively means updating the persistent entities whose aggregate\n the transient entity represents, how this dis-aggregation happens is defined by the service.",
"@Core.Example": {
"@odata.type": "https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml#Core.ExternalExampleValue",
"Description": "Based on the [example model](../examples/Analytics.AggregateEntity-sample.xml).\n The format of the `Aggregate` parameter allows the server to re-create the transient entity\n without storing an identifier, based solely on the parameter value.",
"ExternalValue": "../examples/Analytics.AggregateEntity-result.json"
}
},
"AggregateEntityType": {
"$Kind": "ComplexType",
"@Common.Experimental": true,
"Aggregate": {
"@Core.Description": "Value that the first parameter of the function or action invocation must have",
"@Core.LongDescription": "This string value identifies the aggregate that the transient entity represents.\n This value MUST be treated as opaque by the client."
},
"RetrieveFunctionImport": {
"$Type": "Core.SimpleIdentifier",
"$Nullable": true,
"@Core.Description": "Name of a function import",
"@Core.LongDescription": "The function has only one parameter."
},
"UpdateActionImport": {
"$Type": "Core.SimpleIdentifier",
"$Nullable": true,
"@Core.Description": "Name of an action import",
"@Core.LongDescription": "Action parameters after the first define how the identified aggregate entity is updated,\n they are explained in the action definition in the service metadata."
},
"ExpandableProperties": {
"$Collection": true,
"$Type": "Edm.NavigationPropertyPath",
"@Core.Description": "Declared navigation properties of the aggregate entity that can be expanded"
},
"UpdatableProperties": {
"$Collection": true,
"$Type": "Edm.PropertyPath",
"@Core.Description": "Declared properties of the aggregate entity that can be updated with the action",
"@Core.LongDescription": "If a declared property whose name equals a custom aggregate can be updated, this means updating the\n aggregate value."
}
},
"$Annotations": {
"Aggregation.CustomAggregate": {
"@[email protected]": "Adding a list of other terms that can be annotated to it.",
Expand Down
13 changes: 13 additions & 0 deletions vocabularies/Analytics.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Term|Type|Description
[AggregatedProperties](./Analytics.xml#L103:~:text=<Term%20Name="-,AggregatedProperties,-") *(Deprecated)*|\[[AggregatedPropertyType](#AggregatedPropertyType)\]|<a name="AggregatedProperties"></a>Deprecated in favor of [`AggregatedProperty`](#AggregatedProperty)
[AggregatedProperty](./Analytics.xml#L121:~:text=<Term%20Name="-,AggregatedProperty,-")|[AggregatedPropertyType](#AggregatedPropertyType)|<a name="AggregatedProperty"></a>Dynamic property for aggregate expression with specified aggregation method defined on the annotated entity type.
[AnalyticalContext](./Analytics.xml#L141:~:text=<Term%20Name="-,AnalyticalContext,-")|\[[AnalyticalContextType](#AnalyticalContextType)\]|<a name="AnalyticalContext"></a>Collection of properties that define an analytical context
[AggregateEntity](./Analytics.xml#L170:~:text=<Term%20Name="-,AggregateEntity,-") *([Experimental](Common.md#Experimental))*|[AggregateEntityType](#AggregateEntityType)|<a name="AggregateEntity"></a>Function and action for retrieving and updating an aggregate entity ([Example](./Analytics.xml#L182))<br>Transient entities that result from the application of a transformation sequence represent an aggregate of persistent entities (for example, aggregate sales per country and product, as in [OData-Data-Agg-v4.0], first example in simple grouping section). Such a transient entity may be annotated with this term to describe<br> - a service-defined function import that can be used to retrieve the transient entity in order to `$expand` additional properties<br> - a service-defined action import that can be used to update the transient entity. This effectively means updating the persistent entities whose aggregate the transient entity represents, how this dis-aggregation happens is defined by the service.

<a name="AggregatedPropertyType"></a>
## [AggregatedPropertyType](./Analytics.xml#L124:~:text=<ComplexType%20Name="-,AggregatedPropertyType,-")
Expand All @@ -43,3 +44,15 @@ Property|Type|Description
[Dimension](./Analytics.xml#L159:~:text=<ComplexType%20Name="-,AnalyticalContextType,-")|[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:~:text=<ComplexType%20Name="-,AnalyticalContextType,-")|[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:~:text=<ComplexType%20Name="-,AnalyticalContextType,-")|[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

<a name="AggregateEntityType"></a>
## [AggregateEntityType](./Analytics.xml#L193:~:text=<ComplexType%20Name="-,AggregateEntityType,-") *([Experimental](Common.md#Experimental))*


Property|Type|Description
:-------|:---|:----------
[Aggregate](./Analytics.xml#L195:~:text=<ComplexType%20Name="-,AggregateEntityType,-")|String|Value that the first parameter of the function or action invocation must have<br>This string value identifies the aggregate that the transient entity represents. This value MUST be treated as opaque by the client.
[RetrieveFunctionImport](./Analytics.xml#L202:~:text=<ComplexType%20Name="-,AggregateEntityType,-")|[SimpleIdentifier?](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#SimpleIdentifier)|Name of a function import<br>The function has only one parameter.
[UpdateActionImport](./Analytics.xml#L208:~:text=<ComplexType%20Name="-,AggregateEntityType,-")|[SimpleIdentifier?](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#SimpleIdentifier)|Name of an action import<br>Action parameters after the first define how the identified aggregate entity is updated, they are explained in the action definition in the service metadata.
[ExpandableProperties](./Analytics.xml#L215:~:text=<ComplexType%20Name="-,AggregateEntityType,-")|\[NavigationPropertyPath\]|Declared navigation properties of the aggregate entity that can be expanded
[UpdatableProperties](./Analytics.xml#L218:~:text=<ComplexType%20Name="-,AggregateEntityType,-")|\[PropertyPath\]|Declared properties of the aggregate entity that can be updated with the action<br>If a declared property whose name equals a custom aggregate can be updated, this means updating the aggregate value.
Loading