Skip to content

Commit

Permalink
Use Core.ContentID in actions
Browse files Browse the repository at this point in the history
  • Loading branch information
HeikoTheissen committed Aug 29, 2024
1 parent 082489e commit 790a3d7
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 0 deletions.
42 changes: 42 additions & 0 deletions examples/Common.CorrespondingContentIDs-sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"$Version": "4.0",
"$Reference": {
"https://sap.github.io/odata-vocabularies/vocabularies/Common.json": {
"$Include": [{ "$Namespace": "com.sap.vocabularies.Common.v1", "$Alias": "Common" }]
}
},
"corresponding.sample": {
"$Alias": "self",
"SalesQuotation": { "$Kind": "EntityType", "id": { "$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" },
"@Common.CorrespondingContentIDs": [{ "ParameterValue": "items", "ReturnedEntity": "$ReturnType/Items" }]
}
],
"default": {
"$Kind": "EntityContainer",
"SalesQuotations": { "$Collection": true, "$Type": "self.SalesQuotation" }
}
},
"$EntityContainer": "corresponding.sample.default"
}
41 changes: 41 additions & 0 deletions examples/Common.CorrespondingContentIDs-sample.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?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://sap.github.io/odata-vocabularies/vocabularies/Common.xml">
<edmx:Include Namespace="com.sap.vocabularies.Common.v1" Alias="Common" />
</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.String" />
</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="Common.CorrespondingContentIDs">
<Collection>
<Record>
<PropertyValue Property="ParameterValue" PropertyPath="items" />
<PropertyValue Property="ReturnedEntity" NavigationPropertyPath="$ReturnType/Items" />
</Record>
</Collection>
</Annotation>
</Action>
<EntityContainer Name="default">
<EntitySet Name="SalesQuotations" EntityType="self.SalesQuotation" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
35 changes: 35 additions & 0 deletions vocabularies/Common.json
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,41 @@
"@Common.Experimental": true,
"@Core.IsURL": true,
"@Core.Description": "Base URL for WebSocket connections"
},
"CorrespondingContentIDs": {
"$Kind": "Term",
"$Collection": true,
"$Type": "Common.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 entities 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 or entity in a parameter and in the return type",
"@Core.LongDescription": "Given a sales quotation with items for coffee, sugar and paper,\nthe following $batch request to [this service](../examples/Common.CorrespondingContentIDs-sample.xml)\ninvokes an action to create a sales order for sugar and paper\nand adds a 10% discount for the sugar.\n```json\n{\n \"requests\": [\n {\n \"id\": \"1\",\n \"method\": \"post\",\n \"url\": \"/service/SalesQuotation(68)/self.CreateSalesOrder\",\n \"body\": {\n \"items\": [\n {\"product\": \"Sugar\", \"@Core.ContentID\": \"I1\"},\n {\"product\": \"Paper\"}\n ]\n }\n },\n {\n \"id\": \"2\",\n \"dependsOn\": [ \"1\" ],\n \"method\": \"post\",\n \"url\": \"$I1/Discounts\",\n \"body\": {\n \"percent\": 10\n }\n }\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.\n\nExactly one of `ParameterValue` and `ParameterEntity` and\nexactly one of `ReturnedValue` and `ReturnedEntity` and must be given.",
"ParameterValue": {
"$Type": "Edm.PropertyPath",
"$Nullable": true,
"@Core.Description": "Path to a value in a parameter that may be annotated with `Core.ContentID`"
},
"ParameterEntity": {
"$Type": "Edm.NavigationPropertyPath",
"$Nullable": true,
"@Core.Description": "Path to an entity in a parameter that may be annotated with `Core.ContentID`"
},
"ReturnedValue": {
"$Type": "Edm.PropertyPath",
"$Nullable": true,
"@Core.Description": "Path to a value in the return type that will be annotated with the same `Core.ContentID`"
},
"ReturnedEntity": {
"$Type": "Edm.NavigationPropertyPath",
"$Nullable": true,
"@Core.Description": "Path to an entity in the return type that will be annotated with the same `Core.ContentID`"
}
}
}
}
48 changes: 48 additions & 0 deletions vocabularies/Common.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ Term|Type|Description
[mediaUploadLink](Common.xml#L1457) *([Experimental](Common.md#Experimental))*|URL|<a name="mediaUploadLink"></a>URL for uploading new media content to a Document Management Service<br>In contrast to the `@odata.mediaEditLink` this URL allows to upload new media content without directly changing a stream property or media resource. The upload request typically uses HTTP POST with `Content-Type: multipart/form-data` following RFC 7578. The upload request must contain one multipart representing the content of the file. The `name` parameter in the `Content-Disposition` header (as described in RFC 7578) is irrelevant, but the `filename` parameter is expected. If the request succeeds the response will contain a JSON body of `Content-Type: application/json` with a JSON property `readLink`. The newly uploaded media resource can be linked to the stream property by changing the `@odata.mediaReadLink` to the value of this `readLink` in a subsequent PATCH request to the OData entity.
[PrimitivePropertyPath](Common.xml#L1472) *([Experimental](Common.md#Experimental))*|[Tag](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Tag)|<a name="PrimitivePropertyPath"></a>A term or term property with this tag whose type is (a collection of) `Edm.PropertyPath` MUST resolve to a primitive structural property
[WebSocketBaseURL](Common.xml#L1477) *([Experimental](Common.md#Experimental))*|URL|<a name="WebSocketBaseURL"></a>Base URL for WebSocket connections
[CorrespondingContentIDs](Common.xml#L1483) *([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 entities 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="TextFormatType"></a>
## [TextFormatType](Common.xml#L120)
Expand Down Expand Up @@ -441,3 +442,50 @@ Use terms [Aggregation.RecursiveHierarchy](https://github.com/oasis-tcs/odata-vo
**Type:** String

User ID

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

Given a sales quotation with items for coffee, sugar and paper,
the following $batch request to [this service](../examples/Common.CorrespondingContentIDs-sample.xml)
invokes an 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": "/service/SalesQuotation(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.

Exactly one of `ParameterValue` and `ParameterEntity` and
exactly one of `ReturnedValue` and `ReturnedEntity` and must be given.

Property|Type|Description
:-------|:---|:----------
[ParameterValue](Common.xml#L1532)|PropertyPath?|Path to a value in a parameter that may be annotated with `Core.ContentID`
[ParameterEntity](Common.xml#L1535)|NavigationPropertyPath?|Path to an entity in a parameter that may be annotated with `Core.ContentID`
[ReturnedValue](Common.xml#L1538)|PropertyPath?|Path to a value in the return type that will be annotated with the same `Core.ContentID`
[ReturnedEntity](Common.xml#L1541)|NavigationPropertyPath?|Path to an entity in the return type that will be annotated with the same `Core.ContentID`
62 changes: 62 additions & 0 deletions vocabularies/Common.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,68 @@ If the request succeeds the response will contain a JSON body of `Content-Type:
<Annotation Term="Core.Description" String="Base URL for WebSocket connections" />
</Term>

<Term Name="CorrespondingContentIDs" Type="Collection(Common.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 or entity in a parameter and in the return type" />
<Annotation Term="Core.LongDescription">
<String>Given a sales quotation with items for coffee, sugar and paper,
the following $batch request to [this service](../examples/Common.CorrespondingContentIDs-sample.xml)
invokes an 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": "/service/SalesQuotation(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.

Exactly one of `ParameterValue` and `ParameterEntity` and
exactly one of `ReturnedValue` and `ReturnedEntity` and must be given.</String>
</Annotation>
<Property Name="ParameterValue" Type="Edm.PropertyPath" Nullable="true">
<Annotation Term="Core.Description" String="Path to a value in a parameter that may be annotated with `Core.ContentID`" />
</Property>
<Property Name="ParameterEntity" Type="Edm.NavigationPropertyPath" Nullable="true">
<Annotation Term="Core.Description" String="Path to an entity in a parameter that may be annotated with `Core.ContentID`" />
</Property>
<Property Name="ReturnedValue" Type="Edm.PropertyPath" Nullable="true">
<Annotation Term="Core.Description" String="Path to a value in the return type that will be annotated with the same `Core.ContentID`" />
</Property>
<Property Name="ReturnedEntity" Type="Edm.NavigationPropertyPath" Nullable="true">
<Annotation Term="Core.Description" String="Path to an entity in the return type that will be annotated with the same `Core.ContentID`" />
</Property>
</ComplexType>
</Schema>
</edmx:DataServices>
</edmx:Edmx>

0 comments on commit 790a3d7

Please sign in to comment.