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
51 changes: 51 additions & 0 deletions examples/Common.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/Common.json": {
"$Include": [{ "$Namespace": "com.sap.vocabularies.Common.v1", "$Alias": "Common" }]
}
},
"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" },
"@Common.CorrespondingContentIDs": [
{
"@Core.Description": "Correspondence between sales quotation item and sales order item",
"ParameterValue": "items",
"ReturnedEntity": "$ReturnType/Items"
}
]
}
],
"default": {
"$Kind": "EntityContainer",
"SalesQuotations": { "$Collection": true, "$Type": "self.SalesQuotation" }
}
},
"$EntityContainer": "corresponding.sample.default"
}
45 changes: 45 additions & 0 deletions examples/Common.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/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.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="Common.CorrespondingContentIDs">
<Collection>
<Record>
<Annotation Term="Core.Description" String="Correspondence between sales quotation item and sales order item" />
<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 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 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{\"requests\": [{\n \"id\": \"1\",\n \"method\": \"post\",\n \"url\": \"SalesQuotation(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.\n\nExactly one of `ParameterValue` and `ParameterEntity` and\nexactly one of `ReturnedValue` and `ReturnedEntity` 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`"
}
}
}
}
43 changes: 43 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 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="TextFormatType"></a>
## [TextFormatType](Common.xml#L120)
Expand Down Expand Up @@ -441,3 +442,45 @@ 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": "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` must be given.

Property|Type|Description
:-------|:---|:----------
[ParameterValue](Common.xml#L1527)|PropertyPath?|Path to a value in a parameter that may be annotated with `Core.ContentID`
[ParameterEntity](Common.xml#L1530)|NavigationPropertyPath?|Path to an entity in a parameter that may be annotated with `Core.ContentID`
[ReturnedValue](Common.xml#L1533)|PropertyPath?|Path to a value in the return type that will be annotated with the same `Core.ContentID`
[ReturnedEntity](Common.xml#L1536)|NavigationPropertyPath?|Path to an entity in the return type that will be annotated with the same `Core.ContentID`
57 changes: 57 additions & 0 deletions vocabularies/Common.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,63 @@ 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": "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` 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>