|
| 1 | +--- |
| 2 | +parser: v2 |
| 3 | +author_name: DJ Adams |
| 4 | +author_profile: https://github.com/qmacro |
| 5 | +auto_validation: false |
| 6 | +primary_tag: software-product>sap-business-technology-platform |
| 7 | +tags: [ software-product>sap-business-technology-platform, topic>cloud, programming-tool>odata, tutorial>beginner ] |
| 8 | +time: 20 |
| 9 | +--- |
| 10 | + |
| 11 | +# Understand how vocabularies are used in OData metadata documents |
| 12 | + |
| 13 | +<!-- description --> Metadata can be extended, using content organized into vocabularies. |
| 14 | + |
| 15 | +## You will learn |
| 16 | + |
| 17 | +- How annotations are organized into vocabularies |
| 18 | +- How they're included within an OData metadata document |
| 19 | + |
| 20 | +## Intro |
| 21 | + |
| 22 | +The members of the OData Technical Committee have worked hard on OData as a robust, well-defined and extensible standard. In this tutorial we'll look at a key extensibility mechanism in the form of vocabularies, and how they're used to organize annotations. |
| 23 | + |
| 24 | +--- |
| 25 | + |
| 26 | +### Examine the rest of the entity model wrapper |
| 27 | + |
| 28 | +In the previous [Metadata](https://developers.sap.com/tutorials/odata-dd-4-metadata.html) tutorial we saw how the schema was presented within a context. That context is called the [entity model wrapper](https://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part3-csdl/odata-v4.0-errata03-os-part3-csdl-complete.html#_Toc453752500). We left the examination of part of that wrapper - the references to vocabularies - to this tutorial. Let's start by digging into those now. |
| 29 | + |
| 30 | +Here's what the relevant section of the wrapper in [the Northbreeze OData service's metadata document](https://odd.cfapps.eu10.hana.ondemand.com/northbreeze/$metadata) looks like: |
| 31 | + |
| 32 | +```xml |
| 33 | +<?xml version="1.0" encoding="utf-8"?> |
| 34 | +<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"> |
| 35 | + <edmx:Reference |
| 36 | + Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Capabilities.V1.xml"> |
| 37 | + <edmx:Include Alias="Capabilities" Namespace="Org.OData.Capabilities.V1"/> |
| 38 | + </edmx:Reference> |
| 39 | + <edmx:Reference |
| 40 | + Uri="https://sap.github.io/odata-vocabularies/vocabularies/Common.xml"> |
| 41 | + <edmx:Include Alias="Common" Namespace="com.sap.vocabularies.Common.v1"/> |
| 42 | + </edmx:Reference> |
| 43 | + <edmx:Reference |
| 44 | + Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml"> |
| 45 | + <edmx:Include Alias="Core" Namespace="Org.OData.Core.V1"/> |
| 46 | + </edmx:Reference> |
| 47 | + ... |
| 48 | +</edmx:Edmx> |
| 49 | +``` |
| 50 | + |
| 51 | +What are these references? Well, section [3.3 Element edmx:Reference](https://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part3-csdl/odata-v4.0-errata03-os-part3-csdl-complete.html#_Toc453752504) of the CSDL standards document is helpful here (as well as section [3.1 Element edmx:Edmx](https://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part3-csdl/odata-v4.0-errata03-os-part3-csdl-complete.html#_Toc453752504) telling us that there can be zero or more of them within an `<edmx:Edmx>` element). |
| 52 | + |
| 53 | +Basically, `edmx:Reference` elements point to external CSDL documents, specific content from which (indicated by the `edmx:Include` elements within) is then added to the overall scope of the referring (OData metadata) document. |
| 54 | + |
| 55 | +Think of it like an "include" or "import" as found in various programming languages; these references might look like this in pseudo-JavaScript, for example: |
| 56 | + |
| 57 | +```javascript |
| 58 | +import { "Org.OData.Capabilities.V1" as "Capabilities" } from "https://oasis-tcs.github.io/.../Org.OData.Capabilities.V1.xml"; |
| 59 | +import { "com.sap.vocabularies.Common.v1" as "Common" } from "https://sap.github.io/.../Common.xml"; |
| 60 | +import { "Org.OData.Core.V1" as "Core" } from "https://oasis-tcs.github.io/.../Org.OData.Core.V1.xml"; |
| 61 | +``` |
| 62 | + |
| 63 | +### Meet the OData vocabularies |
| 64 | + |
| 65 | +Note that each of the referenced external documents in our OData metadata document are resources in GitHub repositories: |
| 66 | + |
| 67 | +- two belonging to OASIS in <https://oasis-tcs.github.io/odata-vocabularies/> |
| 68 | +- one belonging to SAP in <https://sap.github.io/odata-vocabularies/> |
| 69 | + |
| 70 | +Taking the first of the three `<edmx:Reference>` elements here: |
| 71 | + |
| 72 | +```xml |
| 73 | +<edmx:Reference |
| 74 | + Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Capabilities.V1.xml"> |
| 75 | + <edmx:Include Alias="Capabilities" Namespace="Org.OData.Capabilities.V1"/> |
| 76 | +</edmx:Reference> |
| 77 | +``` |
| 78 | + |
| 79 | +we see that: |
| 80 | + |
| 81 | +- the reference points to an [XML representation](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Capabilities.V1.xml) of a CSDL document "Org.OData.Capabilities.V1" |
| 82 | +- moving one level up from that CSDL document resource's location, there is a [vocabularies overview page](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/) listing each of the OASIS Technical Committee vocabularies, including this "Capabilities" one. |
| 83 | +- for each of these vocabulary resources there are HTML, XML and JSON representations |
| 84 | +- the HTML representation is especially useful for us as it describes the vocabulary's purpose in general, and gives details for each of the terms and types contained within it |
| 85 | + |
| 86 | + |
| 87 | + |
| 88 | +If we look specifically at the [XML source](https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Capabilities.V1.xml) representation of the "Capabilities" vocabulary in CSDL form, we see this: |
| 89 | + |
| 90 | +```xml |
| 91 | +<?xml version="1.0" encoding="utf-8"?> |
| 92 | + ... |
| 93 | + |
| 94 | + Abstract: |
| 95 | + This document contains terms describing capabilities of an OData service. |
| 96 | + |
| 97 | +--> |
| 98 | +<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0"> |
| 99 | + <edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Authorization.V1.xml"> |
| 100 | + <edmx:Include Alias="Authorization" Namespace="Org.OData.Authorization.V1" /> |
| 101 | + </edmx:Reference> |
| 102 | + <edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml"> |
| 103 | + <edmx:Include Alias="Core" Namespace="Org.OData.Core.V1" /> |
| 104 | + </edmx:Reference> |
| 105 | + <edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Validation.V1.xml"> |
| 106 | + <edmx:Include Alias="Validation" Namespace="Org.OData.Validation.V1" /> |
| 107 | + </edmx:Reference> |
| 108 | + <edmx:DataServices> |
| 109 | + <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Org.OData.Capabilities.V1" Alias="Capabilities"> |
| 110 | + ... |
| 111 | + </Schema> |
| 112 | + </edmx:DataServices> |
| 113 | +</edmx:Edmx> |
| 114 | +``` |
| 115 | + |
| 116 | +It's another EDMX document! There is definitely a certain beauty to the OData specifications that is special. |
| 117 | + |
| 118 | +Anyway, there are two thing of note here: |
| 119 | + |
| 120 | +- this document _also_ has references to vocabularies |
| 121 | +- there is a single `<Schema>` element, with the OData namespace "Org.Data.Capabilities.V1" |
| 122 | + |
| 123 | +And that specific schema is exactly the one that's referenced in the `<edmx:Include>` element within the `<edmx:Reference>` element: |
| 124 | + |
| 125 | +```xml |
| 126 | +<edmx:Include Alias="Capabilities" Namespace="Org.OData.Capabilities.V1"/> |
| 127 | +``` |
| 128 | + |
| 129 | +It just so happens that in this referenced CSDL document, there _is_ only one schema, but there could be more. |
| 130 | + |
| 131 | +So an `<edmx:Include>` element forms an important part of the `<edmx:Reference>`. |
| 132 | + |
| 133 | +> Indeed, [section 3.3 Element edmx:Reference](https://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part3-csdl/odata-v4.0-errata03-os-part3-csdl-complete.html#_Toc453752504) states that at least one `<edmx:Include>` or `<edmx:IncludeAnnotation>` is mandatory. |
| 134 | +
|
| 135 | +The `<edmx:Include>` element serves to identify a particular schema to be included, from the referenced vocabulary. It also does one more thing here - it specifies a short name, in the form of a value for an `Alias` attribute, which can be used to refer to that imported vocabulary schema. Just like the `as` aliasing in our imaginary JavaScript equivalent example earlier. So instead of the full name "Org.OData.Capabilities.V1" being needed to prefix vocabulary terms, the short form "Capabilities" can be used, as we'll see in subsequent steps. |
| 136 | + |
| 137 | +### Take a first look at the annotations |
| 138 | + |
| 139 | +Now we understand how vocabulary resources are referenced to be included into an OData metadata document, let's now take a first look at what annotations are used in this particular OData metadata document, and how. |
| 140 | + |
| 141 | +To set the scene, if we take brief look at the CSDL specification, we learn that: |
| 142 | + |
| 143 | +- "Vocabulary annotations can be specified as a child of the model element being annotated or as a child of an `edm:Annotations` element that targets the model element." (from [section 4.6 Annotations](https://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part3-csdl/odata-v4.0-errata03-os-part3-csdl-complete.html#_Toc453752519)) |
| 144 | +- "An annotation applies a term to a model element and defines how to calculate a value for the applied term." (from [section 14 Vocabulary and Annotation](https://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part3-csdl/odata-v4.0-errata03-os-part3-csdl-complete.html#_Vocabulary_and_Annotation)) |
| 145 | + |
| 146 | +Additionally: |
| 147 | + |
| 148 | +- "A service SHOULD NOT require a client to interpret annotations. Clients SHOULD ignore unknown terms and silently treat unexpected or invalid values (including invalid type, invalid literal expression, etc.) as an unknown value for the term." ( also from [section 14 Vocabulary and Annotation](https://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part3-csdl/odata-v4.0-errata03-os-part3-csdl-complete.html#_Vocabulary_and_Annotation)) |
| 149 | + |
| 150 | +With the information from the first two points here, we can see in our OData metadata document that both approaches to annotation are used. |
| 151 | + |
| 152 | +First, we see the "annotation as child element" approach where the annotation "Core.Links" is applied directly to the `<Schema>` element via the `<Annotation>` element which appears a direct child of `<Schema>`: |
| 153 | + |
| 154 | +```xml |
| 155 | +<Schema Namespace="Main" xmlns="http://docs.oasis-open.org/odata/ns/edm"> |
| 156 | + <Annotation Term="Core.Links"> |
| 157 | + <Collection> |
| 158 | + <Record> |
| 159 | + <PropertyValue Property="rel" String="author"/> |
| 160 | + <PropertyValue Property="href" String="https://cap.cloud.sap"/> |
| 161 | + </Record> |
| 162 | + </Collection> |
| 163 | + </Annotation> |
| 164 | + ... |
| 165 | +</Schema> |
| 166 | +``` |
| 167 | + |
| 168 | +Further on in the metadata document we see an example of the other approach, where `<Annotation>` elements appear as direct children of a containing `<Annotations>` element, and the schema elements to which the annotations are applied are specified in `Target` attributes): |
| 169 | + |
| 170 | +> Again, as explained in the previous [Metadata](https://developers.sap.com/tutorials/odata-dd-4-metadata.html) tutorial, in the "Get acquainted with the schema element" step, we'll leave out the XML namespace prefix `edm` her when writing elements that belong to that namespace. |
| 171 | +
|
| 172 | + |
| 173 | +```xml |
| 174 | +<Schema Namespace="Main" xmlns="http://docs.oasis-open.org/odata/ns/edm"> |
| 175 | + ... |
| 176 | + <EntityContainer Name="EntityContainer"> |
| 177 | + <EntitySet Name="Categories" EntityType="Main.Categories"> |
| 178 | + <NavigationPropertyBinding Path="Products" Target="Products"/> |
| 179 | + </EntitySet> |
| 180 | + </EntityContainer> |
| 181 | + ... |
| 182 | + <Annotations Target="Main.EntityContainer/Categories"> |
| 183 | + <Annotation Term="Capabilities.DeleteRestrictions"> |
| 184 | + <Record Type="Capabilities.DeleteRestrictionsType"> |
| 185 | + <PropertyValue Property="Deletable" Bool="false"/> |
| 186 | + </Record> |
| 187 | + </Annotation> |
| 188 | + <Annotation Term="Capabilities.InsertRestrictions"> |
| 189 | + <Record Type="Capabilities.InsertRestrictionsType"> |
| 190 | + <PropertyValue Property="Insertable" Bool="false"/> |
| 191 | + </Record> |
| 192 | + </Annotation> |
| 193 | + <Annotation Term="Capabilities.UpdateRestrictions"> |
| 194 | + <Record Type="Capabilities.UpdateRestrictionsType"> |
| 195 | + <PropertyValue Property="Updatable" Bool="false"/> |
| 196 | + </Record> |
| 197 | + </Annotation> |
| 198 | + </Annotations> |
| 199 | +</Schema> |
| 200 | +``` |
| 201 | + |
| 202 | +Here, three different annotations terms: |
| 203 | + |
| 204 | +- Capabilities.DeleteRestrictions |
| 205 | +- Capabilities.InsertRestrictions |
| 206 | +- Capabilities.UpdateRestrictions |
| 207 | + |
| 208 | +are being applied via `Target="Main.EntityContainer/Categories"` to the "Categories" entityset in the entity container named "EntityContainer" in the "Main" OData namespace. |
| 209 | + |
| 210 | +In the next tutorial we'll dig in to the detail of the annotations used in this OData metadata document. |
0 commit comments