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

Use Core.ContentID in actions #340

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SAP Vocabularies for semantic markup of structured data published via [OData](ht
This repository defines the following SAP vocabularies:

- [Analytics: Analytical resources](vocabularies/Analytics.md)
- [Batch: Advanced batch requests](vocabularies/Batch.md) - _experimental_
- [CodeList: Code Lists](vocabularies/CodeList.md)
- [Common: Semantics common to all types of APIs](vocabularies/Common.md)
- [Communication: Contact information based on vCard](vocabularies/Communication.md)
Expand Down
51 changes: 51 additions & 0 deletions examples/Batch.CorrespondingContentIDs-sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"$Version": "4.0",
"$Reference": {
"https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.json": {
"$Include": [{ "$Namespace": "Org.OData.Core.V1", "$Alias": "Core" }]
},
"https://sap.github.io/odata-vocabularies/vocabularies/Batch.json": {
"$Include": [{ "$Namespace": "com.sap.vocabularies.Batch.v1", "$Alias": "Batch" }]
}
},
"corresponding.sample": {
"$Alias": "self",
"SalesQuotation": { "$Kind": "EntityType", "id": { "$Type": "Edm.Int16", "$Nullable": true } },
"SalesQuotationItemToBeCopied": { "$Kind": "ComplexType", "product": { "$Nullable": true } },
"SalesOrder": {
"$Kind": "EntityType",
"Items": { "$Kind": "NavigationProperty", "$Collection": true, "$Type": "self.SalesOrderItem" }
},
"SalesOrderItem": {
"$Kind": "EntityType",
"Discounts": { "$Kind": "NavigationProperty", "$Collection": true, "$Type": "self.SalesOrderItemDiscount" }
},
"SalesOrderItemDiscount": {
"$Kind": "EntityType",
"percent": { "$Type": "Edm.Decimal", "$Nullable": true, "$Scale": 0 }
},
"CreateSalesOrder": [
{
"$Kind": "Action",
"$IsBound": true,
"$Parameter": [
{ "$Name": "_it", "$Type": "self.SalesQuotation" },
{ "$Name": "items", "$Collection": true, "$Type": "self.SalesQuotationItemToBeCopied" }
],
"$ReturnType": { "$Type": "self.SalesOrder" },
"@Batch.CorrespondingContentIDs": [
{
"@Core.Description": "Correspondence between sales quotation item and sales order item",
"ParameterValue": "items",
"ReturnedValue": "$ReturnType/Items"
}
]
}
],
"default": {
"$Kind": "EntityContainer",
"SalesQuotations": { "$Collection": true, "$Type": "self.SalesQuotation" }
}
},
"$EntityContainer": "corresponding.sample.default"
}
45 changes: 45 additions & 0 deletions examples/Batch.CorrespondingContentIDs-sample.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml">
<edmx:Include Namespace="Org.OData.Core.V1" Alias="Core" />
</edmx:Reference>
<edmx:Reference Uri="https://sap.github.io/odata-vocabularies/vocabularies/Batch.xml">
<edmx:Include Namespace="com.sap.vocabularies.Batch.v1" Alias="Batch" />
</edmx:Reference>
<edmx:DataServices>
<Schema Namespace="corresponding.sample" Alias="self" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="SalesQuotation">
<Property Name="id" Type="Edm.Int16" />
</EntityType>
<ComplexType Name="SalesQuotationItemToBeCopied">
<Property Name="product" Type="Edm.String" />
</ComplexType>
<EntityType Name="SalesOrder">
<NavigationProperty Name="Items" Type="Collection(self.SalesOrderItem)" />
</EntityType>
<EntityType Name="SalesOrderItem">
<NavigationProperty Name="Discounts" Type="Collection(self.SalesOrderItemDiscount)" />
</EntityType>
<EntityType Name="SalesOrderItemDiscount">
<Property Name="percent" Type="Edm.Decimal" />
</EntityType>
<Action Name="CreateSalesOrder" IsBound="true">
<Parameter Name="_it" Type="self.SalesQuotation" Nullable="false" />
<Parameter Name="items" Type="Collection(self.SalesQuotationItemToBeCopied)" />
<ReturnType Type="self.SalesOrder" Nullable="false" />
<Annotation Term="Batch.CorrespondingContentIDs">
<Collection>
<Record>
<Annotation Term="Core.Description" String="Correspondence between sales quotation item and sales order item" />
<PropertyValue Property="ParameterValue" PropertyPath="items" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does this "items" come from? It's a PropertyPath, so I would expect somewhere a property "items" - the only thing I see in the example is a parameter.

Copy link
Contributor Author

@HeikoTheissen HeikoTheissen Aug 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A property path relative to an action starts with a parameter name or with $ReturnType. See here.

<PropertyValue Property="ReturnedValue" NavigationPropertyPath="$ReturnType/Items" />
HeikoTheissen marked this conversation as resolved.
Show resolved Hide resolved
</Record>
</Collection>
</Annotation>
</Action>
<EntityContainer Name="default">
<EntitySet Name="SalesQuotations" EntityType="self.SalesQuotation" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
45 changes: 45 additions & 0 deletions vocabularies/Batch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"$Version": "4.01",
"$Reference": {
"https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.json": {
"$Include": [{ "$Namespace": "Org.OData.Core.V1", "$Alias": "Core" }]
},
"https://sap.github.io/odata-vocabularies/vocabularies/Common.json": {
"$Include": [{ "$Namespace": "com.sap.vocabularies.Common.v1", "$Alias": "Common" }]
}
},
"com.sap.vocabularies.Batch.v1": {
"$Alias": "Batch",
"@Core.Description": "Terms for advanced batch request processing",
"@Core.Description#Published": "2024-08-29 © Copyright 2024 SAP SE. All rights reserved.",
"@Core.Links": [
{ "rel": "alternate", "href": "https://sap.github.io/odata-vocabularies/vocabularies/Batch.xml" },
{ "rel": "latest-version", "href": "https://sap.github.io/odata-vocabularies/vocabularies/Batch.json" },
{ "rel": "describedby", "href": "https://github.com/sap/odata-vocabularies/blob/main/vocabularies/Batch.md" }
],
"@Common.Experimental": true,
"CorrespondingContentIDs": {
"$Kind": "Term",
"$Collection": true,
"$Type": "Batch.CorrespondingContentID",
"$AppliesTo": ["Action"],
"@Common.Experimental": true,
"@Core.Description": "Correspondence between `Core.ContentID` in a parameter and in the return type of an action",
"@Core.LongDescription": "If values in the action invocation are annotated with `Core.ContentID`,\n the corresponding values returned by the action are annotated with the same `Core.ContentID`\n and can thus be referenced in subsequent requests within the same batch request."
},
"CorrespondingContentID": {
"$Kind": "ComplexType",
"@Common.Experimental": true,
"@Core.Description": "Establishes a correspondence between a value in a parameter and a value in the return type",
"@Core.LongDescription": "[This service](../examples/Batch.CorrespondingContentIDs-sample.xml)\ncontains an action annotated with\n```json\n\"@Batch.CorrespondingContentIDs\": [{\n \"ParameterValue\": \"items\",\n \"ReturnedValue\": \"$ReturnType/Items\"\n}]\n```\nGiven a sales quotation with items for coffee, sugar and paper,\nthe following batch request invokes the action to create a sales order for sugar and paper\nand adds a 10% discount for the sugar.\n```json\n{\"requests\": [{\n \"id\": \"1\",\n \"method\": \"post\",\n \"url\": \"SalesQuotations(68)/self.CreateSalesOrder\",\n \"body\": {\n \"items\": [\n {\"product\": \"Sugar\", \"@Core.ContentID\": \"I1\"},\n {\"product\": \"Paper\"}\n ]\n }\n}, {\n \"id\": \"2\",\n \"dependsOn\": [\"1\"],\n \"method\": \"post\",\n \"url\": \"$I1/Discounts\",\n \"body\": {\n \"percent\": 10\n }\n}]}\n```\nIn the response to the action invocation the sales order item for the sugar is annotated\nwith `\"@Core.ContentID\": \"I1\"`. The subsequent POST request can reference this item without knowing its key.",
"ParameterValue": {
"$Type": "Edm.AnyPropertyPath",
"@Core.Description": "Path to a value in a parameter that may be annotated with `Core.ContentID`"
},
"ReturnedValue": {
"$Type": "Edm.AnyPropertyPath",
"@Core.Description": "Path to a value in the return type that will be annotated with the same `Core.ContentID`"
}
}
}
}
55 changes: 55 additions & 0 deletions vocabularies/Batch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Batch Vocabulary
**Namespace: [com.sap.vocabularies.Batch.v1](Batch.xml)**

Terms for advanced batch request processing


## Terms

Term|Type|Description
:---|:---|:----------
[CorrespondingContentIDs](Batch.xml#L35) *([Experimental](Common.md#Experimental))*|\[[CorrespondingContentID](#CorrespondingContentID)\]|<a name="CorrespondingContentIDs"></a>Correspondence between `Core.ContentID` in a parameter and in the return type of an action<br>If values in the action invocation are annotated with `Core.ContentID`, the corresponding values returned by the action are annotated with the same `Core.ContentID` and can thus be referenced in subsequent requests within the same batch request.

<a name="CorrespondingContentID"></a>
## [CorrespondingContentID](Batch.xml#L44) *([Experimental](Common.md#Experimental))*
Establishes a correspondence between a value in a parameter and a value in the return type

[This service](../examples/Batch.CorrespondingContentIDs-sample.xml)
contains an action annotated with
```json
"@Batch.CorrespondingContentIDs": [{
"ParameterValue": "items",
"ReturnedValue": "$ReturnType/Items"
}]
```
Given a sales quotation with items for coffee, sugar and paper,
the following batch request invokes the action to create a sales order for sugar and paper
and adds a 10% discount for the sugar.
```json
{"requests": [{
"id": "1",
"method": "post",
"url": "SalesQuotations(68)/self.CreateSalesOrder",
"body": {
"items": [
{"product": "Sugar", "@Core.ContentID": "I1"},
{"product": "Paper"}
]
}
}, {
"id": "2",
"dependsOn": ["1"],
"method": "post",
"url": "$I1/Discounts",
"body": {
"percent": 10
}
}]}
```
In the response to the action invocation the sales order item for the sugar is annotated
with `"@Core.ContentID": "I1"`. The subsequent POST request can reference this item without knowing its key.

Property|Type|Description
:-------|:---|:----------
[ParameterValue](Batch.xml#L83)|AnyPropertyPath|Path to a value in a parameter that may be annotated with `Core.ContentID`
[ReturnedValue](Batch.xml#L86)|AnyPropertyPath|Path to a value in the return type that will be annotated with the same `Core.ContentID`
94 changes: 94 additions & 0 deletions vocabularies/Batch.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.01">
<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml">
<edmx:Include Alias="Core" Namespace="Org.OData.Core.V1" />
</edmx:Reference>
<edmx:Reference Uri="https://sap.github.io/odata-vocabularies/vocabularies/Common.xml">
<edmx:Include Alias="Common" Namespace="com.sap.vocabularies.Common.v1" />
</edmx:Reference>
<edmx:DataServices>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="com.sap.vocabularies.Batch.v1" Alias="Batch">
<Annotation Term="Core.Description">
<String>Terms for advanced batch request processing</String>
</Annotation>
<Annotation Term="Core.Description" Qualifier="Published">
<String>2024-08-29 © Copyright 2024 SAP SE. All rights reserved.</String>
</Annotation>
<Annotation Term="Core.Links">
<Collection>
<Record>
<PropertyValue Property="rel" String="latest-version" />
<PropertyValue Property="href" String="https://sap.github.io/odata-vocabularies/vocabularies/Batch.xml" />
</Record>
<Record>
<PropertyValue Property="rel" String="alternate" />
<PropertyValue Property="href" String="https://sap.github.io/odata-vocabularies/vocabularies/Batch.json" />
</Record>
<Record>
<PropertyValue Property="rel" String="describedby" />
<PropertyValue Property="href" String="https://github.com/sap/odata-vocabularies/blob/main/vocabularies/Batch.md" />
</Record>
</Collection>
</Annotation>
<Annotation Term="Common.Experimental" />

<Term Name="CorrespondingContentIDs" Type="Collection(Batch.CorrespondingContentID)" Nullable="false" AppliesTo="Action">
<Annotation Term="Common.Experimental" />
<Annotation Term="Core.Description" String="Correspondence between `Core.ContentID` in a parameter and in the return type of an action" />
<Annotation Term="Core.LongDescription">
<String>If values in the action invocation are annotated with `Core.ContentID`,
the corresponding values returned by the action are annotated with the same `Core.ContentID`
and can thus be referenced in subsequent requests within the same batch request.</String>
</Annotation>
</Term>
<ComplexType Name="CorrespondingContentID">
<Annotation Term="Common.Experimental" />
<Annotation Term="Core.Description" String="Establishes a correspondence between a value in a parameter and a value in the return type" />
<Annotation Term="Core.LongDescription">
<String>[This service](../examples/Batch.CorrespondingContentIDs-sample.xml)
contains an action annotated with
```json
"@Batch.CorrespondingContentIDs": [{
"ParameterValue": "items",
"ReturnedValue": "$ReturnType/Items"
}]
```
Given a sales quotation with items for coffee, sugar and paper,
the following batch request invokes the action to create a sales order for sugar and paper
and adds a 10% discount for the sugar.
```json
{"requests": [{
"id": "1",
"method": "post",
"url": "SalesQuotations(68)/self.CreateSalesOrder",
"body": {
"items": [
{"product": "Sugar", "@Core.ContentID": "I1"},
{"product": "Paper"}
]
}
}, {
"id": "2",
"dependsOn": ["1"],
"method": "post",
"url": "$I1/Discounts",
"body": {
"percent": 10
}
}]}
```
In the response to the action invocation the sales order item for the sugar is annotated
with `"@Core.ContentID": "I1"`. The subsequent POST request can reference this item without knowing its key.</String>
</Annotation>
<Property Name="ParameterValue" Type="Edm.AnyPropertyPath" Nullable="false">
<Annotation Term="Core.Description" String="Path to a value in a parameter that may be annotated with `Core.ContentID`" />
</Property>
<Property Name="ReturnedValue" Type="Edm.AnyPropertyPath" Nullable="false">
<Annotation Term="Core.Description" String="Path to a value in the return type that will be annotated with the same `Core.ContentID`" />
</Property>
</ComplexType>

</Schema>
</edmx:DataServices>
</edmx:Edmx>