In mashup scenarios it is often the case that a third party can detect a rule that allows constructing URLs from information provided in an entity that allow navigation to other resources in the web.
Annotations allow to express these construction rules, this construction rules can also be seen as "special navigation properties defined via annotations".
We want to annotate these "special navigagtion properties" in a such a way, that they can be used in further annotation similar to native navigation properties.
In the following example two navigation properties ( to a supplier and to purchase orders ) and one property is annotated at the product entity type; and they are used in a other annotation. This example is currently invalid, because the <Url> element isn't specified so far.
Complete annotation file example (it uses https://tools.oasis-open.org/issues/browse/ODATA-257):
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx/4.0">
<edmx:Reference Url="http://biz.org/odata/foobar/ProductService.srv/$metadata" />
<edmx:Reference Url="http://example.org:1234/odata/bar/SupplierService.srv/$metadata" />
<edmx:Reference Url="http://somewhere.org/odata/foo/Purchasing.srv/$metadata" />
<edmx:DataServices DataServiceVersion="4.0">
<Schema xmlns="http://docs.oasis-open.org/odata/ns/csdl/4.0" Namespace="AnnotationCrossReference" Alias="ACR">
<Using Namespace="com.sap.erp.products" Alias="ServiceA" />
<Using Namespace="com.sap.erp.supplier" Alias="ServiceB" />
<Using Namespace="com.sap.foo.purchasing" Alias="ServiceC" />
<Term Name="DataFieldWithNavigation" Type="DataFieldWithNavigationType" />
<ComplexType Name="DataFieldWithNavigationType">
<Property Name="Label" Type="String" Nullable="true">
<Annotation Term="Core.IsLanguageDependent" />
</Property>
<Property Name="Value" Type="Edm.PrimitiveType" Nullable="false" />
<Property Name="NavigationPath" Type="Edm.NavigationPropertyPath" Nullable="false" />
</ComplexType>
<Term Name="Supplier" Type="ServiceB.Supplier" />
<Term Name="PurchaseOrders" Type="Collection(ServiceC.PurchaseOrder)" />
<Term Name="NumberOfPurchaseOrders" Type="Edm.Int32" />
<Annotations Target="ServiceA.Product">
<Annotation Term="Supplier">
<Url>
<Apply Function="odata.fillUriTemplate">
<!-- ... construct path to ServiceB.Supplier -->
<String>http://example.org:1234/odata/bar/SupplierService.srv/Suppliers(
)</String>
<LabeledElement Name="suppID">
<Apply Function="odata.UriEncode">
<Path>SupplierId</Path>
</Apply>
</LabeledElement>
</Apply>
</Url>
</Annotation>
<Annotation Term="PurchaseOrders">
<Url>
<Apply Function="odata.fillUriTemplate">
<!-- ... construct path to a ServiceC.EntiySet of entity type PurchaseOrders -->
<String>http://somewhere.org/odata/foo/Purchasing.srv/PurchaseOrders?$search=
<LabeledElement Name="productID">
<Apply Function="odata.UriEncode">
<Path>ProductKey</Path>
</Apply>
</LabeledElement>
</Apply>
</Url>
</Annotation>
<Annotation Term="NumberOfPurchaseOrders">
<Url>
<Apply Function="odata.fillUriTemplate">
<!-- ... construct path an int value -->
<String>http://somewhere.org/odata/foo/Purchasing.srv/PurchaseOrders/$count?$search={productID}
</String>
<LabeledElement Name="productID">
<Apply Function="odata.UriEncode">
<Path>ProductKey</Path>
</Apply>
</LabeledElement>
</Apply>
</Url>
</Annotation>
<Annotation Term="DataFieldWithNavigation" Qualifier="FirstDataField">
<Record>
<PropertyValue Property="Label" String="Supplier" />
<PropertyValue Property="Value" Path="@ACR.Supplier/SupplierName" />
<PropertyValue Property="NavigationPath" NavigationPropertyPath="@ACR.Supplier" />
</Record>
</Annotation>
<Annotation Term="DataFieldWithNavigation" Qualifier="SecondDataField">
<Record>
<PropertyValue Property="Label" String="Purchase Orders" />
<PropertyValue Property="Value" Path="@ACR.NumberOfPurchaseOrders" />
<PropertyValue Property="NavigationPath" NavigationPropertyPath="@ACR.PurchaseOrders" />
</Record>
</Annotation>
</Annotations>
</Schema>
</edmx:DataServices>
</edmx:Edmx>