SAP ECC Plugins

Introduction

This plugin would allow SAP ECC enterprise users to specify one of the Inventory Management data sources as source in Cloud Data Fusion. Typical pipeline scenario would include specifying one of the data sources as source (under Sources plugins) and BigQuery as sink. For the sake of simplicity, this document will cover one data source (Material Movements from Inventory Management - 2LIS_03_BF).

User Experience and Configuration

  • SAP ECC Setup
    1. SAP ECC users log into SAP Gateway Service Builder (segw) to create and expose the data source as SAP OData service. SAP has published following articles around this step:

      1. OData service introduction 

      2. Step-by-step guide to build OData service

    2. User creates OData service for the data source (2LIS_03_BF). Output is RESTful OData service that can be accessed by Cloud Data Fusion.

    3. User can also use SAP Netweaver Gateway client to test the service (with HTTP request and response)

  • Cloud Data Fusion - Source configuration
    1. Source Data Types Mapping
    2. User would log into their CDF instance and click on “Hub”.

    3. Under “Plugins” section, user should be able to find “SAP ECC Source”.

    4. This integration would provide a single JAR files for SAP ECC data sources. User would upload the JAR file and this would deploy the plugin using the JAR file.

    5. Once uploaded, the user is prompted to provide following configuration information. Please note that all the fields below should be macro enabled.


Label

Label Description

User Widget

Name

Name of the source

Textbox

Description

Description of the service and the data source it is going to connect to (e.g. 2LIS_03_BF)

Textbox

OData service URL

OData service URL exposed via SAP ECC

Textbox

User name

Login user name for authenticating API call

Textbox

Password

Password for authenticating API call

Textbox

    1. The same dialog will have “Test connection” button to allow users to validate a validation API call. If failed, the error message will be presented to the user in red next to “Test connection” button.

    2. Once connection has been established successfully to this OData service, it can be used as a source for creating data pipelines using Cloud Data Fusion.

  • Cloud Data Fusion - Sink setup (e.g. BigQuery for this specific example)
    1. User would create a BigQuery table inside a dataset where the data extracted through OData service API will be ingested.

    2. User needs to ensure that the table schema includes data types that have been mapped as part of this integration (see below for integration considerations section for more details)

Integration considerations

  • Data type mismatch - OData output has data types (section 6) different than the data types available in BigQuery. Some sort of data type conversion needs to happen before the extracted data can be ingested into BigQuery. Below is the suggested mapping of OData data types to CDAP schema data types:

OData data type

CDAP schema data type

Edm.Binary

Schema.Type.String

Edm.Boolean

Schema.Type.Bool

Edm.Byte

Schema.Type.Byte

Edm.DateTime

Schema.Type.DateTime

Edm.Decimal

Schema.Type.Float

Edm.Double

Schema.Type.Double

Edm.Single

Schema.Type.Float

Edm.Guid

Schema.Type.String

Edm.Int16

Schema.Type.Int

Edm.Int32

Schema.Type.Int

Edm.Int64

Schema.Type.Long

Edm.SByte

Schema.Type.Bytes

Edm.String

Schema.Type.String

Edm.Time

Schema.Type.Time

Edm.DateTimeOffset

Schema.Type.Timestamp

  • Field Level Lineage (FLL): Field level lineage should be available for all the sources and sinks.

OData Service API

Service Metadata Document

Describes the structure of all resources in the service. 

Note: service metadata document has no JSON representation.

GET: http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S3_SRV/$metadata

Response:

Sample metadata response
<?xml version="1.0" encoding="UTF-8"?>
<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData" Version="1.0">
  <edmx:DataServices m:DataServiceVersion="2.0">
    <Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" Namespace="ZGW100_XX_S2_SRV" xml:lang="en" sap:schema-version="1">
      <EntityType Name="SalesOrder" sap:content-version="1">
        <Key>
          <PropertyRef Name="SoId" />
        </Key>
        <Property Name="SoId" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Sales Order ID" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="Note" Type="Edm.String" Nullable="false" MaxLength="255" sap:label="Description" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="BuyerId" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Business Partner ID" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="BuyerName" Type="Edm.String" Nullable="false" MaxLength="80" sap:label="Company" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="CurrencyCode" Type="Edm.String" Nullable="false" MaxLength="5" sap:label="Currency Code" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" sap:semantics="currency-code" />
        <Property Name="GrossAmount" Type="Edm.Decimal" Nullable="false" Precision="16" Scale="3" sap:label="Gross Amount" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="NetAmount" Type="Edm.Decimal" Nullable="false" Precision="16" Scale="3" sap:label="Net Amount" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="TaxAmount" Type="Edm.Decimal" Nullable="false" Precision="16" Scale="3" sap:label="Tax Amount" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <NavigationProperty Name="SalesOrderItems" Relationship="ZGW100_XX_S2_SRV.SalesOrderSalesOrderItems" FromRole="FromRole_SalesOrderSalesOrderItems" ToRole="ToRole_SalesOrderSalesOrderItems" />
      </EntityType>
      <EntityType Name="SalesOrderItem" sap:content-version="1">
        <Key>
          <PropertyRef Name="SoId" />
          <PropertyRef Name="SoItemPos" />
        </Key>
        <Property Name="SoId" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Sales Order ID" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="SoItemPos" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Item Position" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="ProductId" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Product ID" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="Note" Type="Edm.String" Nullable="false" MaxLength="255" sap:label="Description" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="CurrencyCode" Type="Edm.String" Nullable="false" MaxLength="5" sap:label="Currency Code" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" sap:semantics="currency-code" />
        <Property Name="GrossAmount" Type="Edm.Decimal" Nullable="false" Precision="16" Scale="3" sap:label="Gross Amount" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="NetAmount" Type="Edm.Decimal" Nullable="false" Precision="16" Scale="3" sap:label="Net Amount" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="TaxAmount" Type="Edm.Decimal" Nullable="false" Precision="16" Scale="3" sap:label="Tax Amount" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="Quantity" Type="Edm.Decimal" Nullable="false" Precision="13" Scale="3" sap:label="Quantity" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />
        <Property Name="QuantityUnit" Type="Edm.String" Nullable="false" MaxLength="3" sap:label="Unit of Measure" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" sap:semantics="unit-of-measure" />
      </EntityType>
      <Association Name="SalesOrderSalesOrderItems" sap:content-version="1">
        <End Type="ZGW100_XX_S2_SRV.SalesOrder" Multiplicity="1" Role="FromRole_SalesOrderSalesOrderItems" />
        <End Type="ZGW100_XX_S2_SRV.SalesOrderItem" Multiplicity="*" Role="ToRole_SalesOrderSalesOrderItems" />
        <ReferentialConstraint>
          <Principal Role="FromRole_SalesOrderSalesOrderItems">
            <PropertyRef Name="SoId" />
          </Principal>
          <Dependent Role="ToRole_SalesOrderSalesOrderItems">
            <PropertyRef Name="SoId" />
          </Dependent>
        </ReferentialConstraint>
      </Association>
      <EntityContainer Name="ZGW100_XX_S2_SRV_Entities" m:IsDefaultEntityContainer="true" sap:supported-formats="atom json xlsx">
        <EntitySet Name="SalesOrderSet" EntityType="ZGW100_XX_S2_SRV.SalesOrder" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1" />
        <EntitySet Name="SalesOrderCollection" EntityType="ZGW100_XX_S2_SRV.SalesOrder" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1" />
        <EntitySet Name="SalesOrderItemSet" EntityType="ZGW100_XX_S2_SRV.SalesOrderItem" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1" />
        <EntitySet Name="SalesOrderItemCollection" EntityType="ZGW100_XX_S2_SRV.SalesOrderItem" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1" />
        <AssociationSet Name="SalesOrderSalesOrderItems_AssocSet" Association="ZGW100_XX_S2_SRV.SalesOrderSalesOrderItems" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1">
          <End EntitySet="SalesOrderSet" Role="FromRole_SalesOrderSalesOrderItems" />
          <End EntitySet="SalesOrderItemSet" Role="ToRole_SalesOrderSalesOrderItems" />
        </AssociationSet>
      </EntityContainer>
      <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="self" href="http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/$metadata" />
      <atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="latest-version" href="http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/$metadata" />
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>


Service Document

Lists the available top-level resources.

GET: http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/

Response:

Sample service XML document
<?xml version="1.0" encoding="UTF-8"?>
<app:service xmlns:app="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData" xml:lang="en" xml:base="http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/">
   <app:workspace>
      <atom:title type="text">Data</atom:title>
      <app:collection sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1" href="SalesOrderSet">
         <atom:title type="text">SalesOrderSet</atom:title>
         <sap:member-title>SalesOrder</sap:member-title>
      </app:collection>
      <app:collection sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1" href="SalesOrderCollection">
         <atom:title type="text">SalesOrderCollection</atom:title>
         <sap:member-title>SalesOrder</sap:member-title>
      </app:collection>
      <app:collection sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1" href="SalesOrderItemSet">
         <atom:title type="text">SalesOrderItemSet</atom:title>
         <sap:member-title>SalesOrderItem</sap:member-title>
      </app:collection>
      <app:collection sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:addressable="false" sap:content-version="1" href="SalesOrderItemCollection">
         <atom:title type="text">SalesOrderItemCollection</atom:title>
         <sap:member-title>SalesOrderItem</sap:member-title>
      </app:collection>
   </app:workspace>
   <atom:link rel="self" href="http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/" />
   <atom:link rel="latest-version" href="http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/" />
</app:service>


GET: http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/?$format=json

Response:

Sample service JSON document
{
  "d":{
    "EntitySets":[
      "SalesOrderSet",
      "SalesOrderCollection",
      "SalesOrderItemSet",
      "SalesOrderItemCollection"
    ]
  }
}

Requesting EntitySet

GET: http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S3_SRV/SalesOrderSet

Response:
Sample 'GetEntitySet' response
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xml:base="http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S3_SRV/">
  <id>http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S3_SRV/SalesOrderSet</id>
  <title type="text">SalesOrderSet</title>
  <updated>2019-08-21T10:29:14Z</updated>
  <author>
    <name />
  </author>
  <link href="SalesOrderSet" rel="self" title="SalesOrderSet" />
  <entry>
    <id>http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S3_SRV/SalesOrderSet('500000000')</id>
    <title type="text">SalesOrderSet('500000000')</title>
    <updated>2019-08-21T10:29:14Z</updated>
    <category term="ZGW100_XX_S3_SRV.SalesOrder" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <link href="SalesOrderSet('500000000')" rel="edit" title="SalesOrder" />
    <content type="application/xml">
      <m:properties>
        <d:SoId>500000000</d:SoId>
        <d:BuyerId>100000000</d:BuyerId>
        <d:BuyerName>SAP</d:BuyerName>
      </m:properties>
    </content>
  </entry>
  <entry>
    <id>http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S3_SRV/SalesOrderSet('500000001')</id>
    <title type="text">SalesOrderSet('500000001')</title>
    <updated>2019-08-21T10:29:14Z</updated>
    <category term="ZGW100_XX_S3_SRV.SalesOrder" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <link href="SalesOrderSet('500000001')" rel="edit" title="SalesOrder" />
    <content type="application/xml">
      <m:properties>
        <d:SoId>500000001</d:SoId>
        <d:BuyerId>100000002</d:BuyerId>
        <d:BuyerName>DelBont Industries</d:BuyerName>
      </m:properties>
    </content>
  </entry>
  <entry>
    <id>http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S3_SRV/SalesOrderSet('500000002')</id>
    <title type="text">SalesOrderSet('500000002')</title>
    <updated>2019-08-21T10:29:14Z</updated>
    <category term="ZGW100_XX_S3_SRV.SalesOrder" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <link href="SalesOrderSet('500000002')" rel="edit" title="SalesOrder" />
    <content type="application/xml">
      <m:properties>
        <d:SoId>500000002</d:SoId>
        <d:BuyerId>100000005</d:BuyerId>
        <d:BuyerName>TECUM</d:BuyerName>
      </m:properties>
    </content>
  </entry>
  ...


GET: http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/SalesOrderCollection?$format=json

Response:
Sample 'GetEntitySet' JSON response
{
  "d":{
    "results":[
      {
        "__metadata":{
          "id":"http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/SalesOrderCollection('500000000')",
          "uri":"http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/SalesOrderCollection('500000000')",
          "type":"ZGW100_XX_S2_SRV.SalesOrder"
        },
        "SoId":"500000000",
        "Note":"EPM DG: SO ID 0500000000 Deliver as fast as possible",
        "BuyerId":"100000000",
        "BuyerName":"SAP",
        "CurrencyCode":"USD",
        "GrossAmount":"14385.850",
        "NetAmount":"12088.950",
        "TaxAmount":"2296.900",
        "SalesOrderItems":{
          "__deferred":{
            "uri":"http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/SalesOrderCollection('500000000')/SalesOrderItems"
          }
        }
      },
      {
        "__metadata":{
          "id":"http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/SalesOrderCollection('500000001')",
          "uri":"http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/SalesOrderCollection('500000001')",
          "type":"ZGW100_XX_S2_SRV.SalesOrder"
        },
        "SoId":"500000001",
        "Note":"EPM DG: SO ID 0500000001 Deliver as fast as possible",
        "BuyerId":"100000002",
        "BuyerName":"DelBont Industries",
        "CurrencyCode":"USD",
        "GrossAmount":"15117.760",
        "NetAmount":"12704.000",
        "TaxAmount":"2413.760",
        "SalesOrderItems":{
          "__deferred":{
            "uri":"http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/SalesOrderCollection('500000001')/SalesOrderItems"
          }
        }
      },
  ...

Querying Data

GET: http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/SalesOrderCollection?$top=1&$select=BuyerName

Response:
Sample querying data response
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xml:base="http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/">
  <id>http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/SalesOrderCollection</id>
  <title type="text">SalesOrderCollection</title>
  <updated>2019-08-21T10:46:14Z</updated>
  <author>
    <name />
  </author>
  <link href="SalesOrderCollection" rel="self" title="SalesOrderCollection" />
  <entry>
    <id>http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/SalesOrderCollection('500000000')</id>
    <title type="text">SalesOrderCollection('500000000')</title>
    <updated>2019-08-21T10:46:14Z</updated>
    <category term="ZGW100_XX_S2_SRV.SalesOrder" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <link href="SalesOrderCollection('500000000')" rel="self" title="SalesOrder" />
    <content type="application/xml">
      <m:properties>
        <d:BuyerName>SAP</d:BuyerName>
      </m:properties>
    </content>
  </entry>
</feed>


For more examples, please, refer: https://www.odata.org/odata-services/

SAP ECC Source Plugin

Design

The suggestion is to use Apache Olingo as Client Library. Both OData v2 and v4 are supported by the SAP Gateway, so it could require to use Olingo v2 and Olingo v4.

Sample application to read OData resources
public class OlingoSampleApp {
  
  private static final String ROOT_URL = "http://vhcalnplci.dummy.nodomain:8000/sap/opu/odata/SAP/ZGW100_XX_S2_SRV/";
  private static final String USERNAME = "DEVELOPER";
  private static final String PASSWORD = "Appl1ance";
  private static final String RESOURCE_PATH = "SalesOrderCollection";

  public static void main(String[] params) throws Exception {

    ODataClient client = ODataClientFactory.getClient();
    client.getConfiguration().setHttpClientFactory(new BasicAuthHttpClientFactory(USERNAME, PASSWORD));
    
    URI resourcesUri = client.newURIBuilder(ROOT_URL)
      .appendEntitySetSegment(RESOURCE_PATH)
      .build();
    
    ODataEntitySetIteratorRequest<ClientEntitySet, ClientEntity> request = client
      .getRetrieveRequestFactory()
      .getEntitySetIteratorRequest(resourcesUri);
    request.setAccept("application/atom+xml");

    ODataRetrieveResponse<ClientEntitySetIterator<ClientEntitySet, ClientEntity>> response  = request.execute();
    ClientEntitySetIterator<ClientEntitySet, ClientEntity> iterator = response.getBody();

    while (iterator.hasNext()) {
      ClientEntity entity = iterator.next();
      // process client entity
    }
  }
}

Source Properties

Section

User Facing Name

Widget Type

Description

Constraints

GeneralLabeltextboxLabel for UI.
Reference NametextboxUniquely identified name for lineage.
OData Service URL
textbox

URL of the SAP ECC OData service. The URL must end with an external service name

(e.g., http://eccsvrname:8000/sap/opu/odata/sap/zgw100_dd02l_so_srv/).

Required

Resource Pathtextbox

Path of the SAP ECC OData entity.

For example:

  • "SalesOrderCollection"
  • "Category(1)/Products"

Required


Query Options
keyvalue

OData query options to filter the data.

For example:

  • "$select=Name,Description"
  • "$top=10".


The plugin copies data from the combined URL:
<OData Service URL>/<Entity Set>?<Query Option 1>&<Query Option 2>

For more information, see OData URL components.


Include Metadata AnnotationstoggleWhether the plugin should read SAP metadata annotations and include them to each record.
CredentialsUsername
textboxUsername for basic authentication.
PasswordpasswordPassword for basic authentication.

Output SchemaschemaSpecifies the schema of the entries.

OData V2 Data Types Mapping

Types can be mapped as follows, according to the org.apache.olingo.odata2.api.edm.EdmSimpleType and OData Primitive Data Types(section 6):

EDM primitive type

CDAP Schema Data Type

Comment

Edm.Binary
bytes

Edm.Boolean

boolean

Edm.Byte

intUnsigned 8-bit integer value

Edm.DateTime

timestamp

Datetime in the following format:

'yyyy-mm-ddThh:mm[:ss[.fffffff]]'

Edm.Decimal

decimal

Edm.Double

double

Edm.Single

float

Edm.Guid

string

Edm.Int16

int

Edm.Int32

int

Edm.Int64

long

Edm.SByte

intRepresents a signed 8-bit integer value

Edm.String

string

Edm.Time

timeRepresents the time of day with values ranging from 0:00:00.x to 23:59:59.y, where x and y depend upon the precision

Edm.DateTimeOffset

string

Represents date and time as an Offset in minutes from GMT, with values ranging from 12:00:00 midnight, January 1, 1753 A.D. through 11:59:59 P.M, December 9999 A.D


Example 1: 2002-10-10T17:00:00Z

Mapped to string to avoid timezone information loss.

OData V4 Data Types Mapping

Types can be mapped as follows, according to the org.apache.olingo.commons.api.edm.EdmPrimitiveType and OData CSDL Primitive Types:

EDM primitive type

CDAP Schema Data Type

JSONXML

Comment

Edm.Binary
bytes



Edm.Boolean

boolean


Edm.Byte

int

Unsigned 8-bit integer value

Edm.Date

timestamp

Date without a time-zone offset


Edm.DateTimeOffsetstring

Represents date and time as an Offset in minutes from GMT, with values ranging from 12:00:00 midnight, January 1, 1753 A.D. through 11:59:59 P.M, December 9999 A.D


Example 1: 2002-10-10T17:00:00Z

Mapped to string to avoid timezone information loss.

Edm.Decimal

decimal


Edm.Double

double


Edm.Durationstring
"Duration@odata.type": "#Duration",
"Duration": "P12DT23H59M59.999999999999S",
<d:Duration m:type="Edm.Duration">P12DT23H59M59.999999999999S</d:Duration>
Signed duration in days, hours, minutes, and (sub)seconds.

Edm.Guid

string


Edm.Int16

int


Edm.Int32

int


Edm.Int64

long


Edm.SByte

int

Represents a signed 8-bit integer value
Edm.Singlefloat


Edm.Stream
record
"Stream@odata.mediaReadLink": "http://placehold.it/10x10.jpg?read",
"Stream@odata.mediaEditLink": "http://placehold.it/10x10.jpg?edit",
"Stream@odata.mediaContentType": "image/jpeg",
"Stream@odata.mediaEtag": "W/\"####\"",
"Stream": ""
<link rel="http://docs.oasis-open.org/odata/ns/edit-media/Stream" title="Stream" href="AllDataTypes(3)/Stream"/>


Binary data stream.


Olingo client maps this data type to java.net.URI.


The proposal is to map this data type to CDAP record that corresponds to the JSON representation.

Edm.String

string


Edm.TimeOfDay

time

Clock time 00:00-23:59:59.999999999999
Edm.Geography-

Abstract base type for all Geography types.
Edm.GeographyPointrecord
"GeographyPoint": {
  "type": "Point",
  "coordinates": [142.1, 64.1]
}
<d:GeographyPoint m:type="GeographyPoint">
  <gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326">
    <gml:pos>15 161.8</gml:pos>
  </gml:Point>
</d:GeographyPoint>
A point in a round-earth coordinate system
Edm.GeographyLineStringrecord
"GeographyLineString": {
  "type": "LineString",
  "coordinates": [
    [100.0, 0.0],
    [101.0, 1.0]
  ]
}
<d:GeographyLineString m:type="Edm.GeographyLineString">
  <gml:LineString gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326">
    <gml:pos>10 10</gml:pos>
    <gml:pos>20 20</gml:pos>
    <gml:pos>40 10</gml:pos>
  </gml:LineString>
</d:GeographyLineString>
Line string in a round-earth coordinate system
Edm.GeographyPolygonrecord
"GeographyPolygon": { 
  "type": "Polygon",
  "coordinates": [
    [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
    [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
  ]
}
<d:GeographyPolygon m:type="Edm.GeographyPolygon">
  <gml:Polygon gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326"/>
  <gml:pos>10 10</gml:pos>
  <gml:pos>10 40</gml:pos>
  <gml:pos>40 10</gml:pos>
  <gml:pos>40 40</gml:pos>
</d:GeographyPolygon>
Polygon in a round-earth coordinate system
Edm.GeographyMultiPointrecord
"GeographyMultiPoint": {
  "type": "MultiPoint",
  "coordinates": [
    [ 2.5, 3.125],
    [3.5, 4.125],
    [4.5, 5.125]
  ]
}
<d:GeographyMultiPoint m:type="Edm.GeographyMultiPoint">
  <gml:MultiPoint gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326">
    <gml:pointMembers>
      <gml:Point>
        <gml:pos>47.38 -122.7</gml:pos>
      </gml:Point>
    </gml:pointMembers>
  </gml:MultiPoint>
</d:GeographyMultiPoint>
Collection of points in a round-earth coordinate system
Edm.GeographyMultiLineStringrecord
"GeographyMultiLineString": {
  "type": "MultiLineString",
  "coordinates": [
    [[1.0,1.0],[2.0,2.0],[3.0,3.0],[4.0,4.0],[5.0,5.0]],
    [[99.5,101.5],[150.0,151.25]]
  ]
}
<d:GeographyMultiLineString m:type="Edm.GeographyMultiLineString">
  <gml:MultiCurve gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326">
    <gml:curveMembers>
      <gml:LineString>
        <gml:pos>10.5 10.5</gml:pos>
        <gml:pos>20.5 20.5</gml:pos>
        <gml:pos>40.5 10.5</gml:pos>
      </gml:LineString>
      <gml:LineString>
        <gml:pos>40.5 40.5</gml:pos>
        <gml:pos>30.5 30.5</gml:pos>
        <gml:pos>20.5 40.5</gml:pos>
        <gml:pos>10.5 30.5</gml:pos>
      </gml:LineString>
    </gml:curveMembers>
  </gml:MultiCurve>
</d:GeographyMultiLineString>
Collection of line strings in a round-earth coordinate system
Edm.GeographyMultiPolygonrecord
"GeographyMultiPolygon": {
  "type": "MultiPolygon",
  "coordinates": [
    [
      [[0.0,0.0],[3.0,0.0],[3.0,3.0],[0.0,3.0],[0.0,0.0]],
      [[1.0,1.0],[1.0,2.0],[2.0,2.0],[2.0,1.0],[1.0,1.0]]],
    [
      [[0.0,0.0],[30.0,0.0],[0.0,30.0],[0.0,0.0]],
      [[10.0,10.0],[10.0,20.0],[20.0,10.0],[10.0,10.0]]
    ]
  ]
}
<d:GeographyMultiPolygon m:type="Edm.GeographyMultiPolygon">
  <gml:MultiSurface
          gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326">
    <gml:surfaceMembers>
      <gml:Polygon>
        <gml:exterior>
          <gml:LinearRing>
            <gml:pos>40 40</gml:pos>
            <gml:pos>45 20</gml:pos>
            <gml:pos>30 45</gml:pos>
            <gml:pos>40 40</gml:pos>
          </gml:LinearRing>
        </gml:exterior>
      </gml:Polygon>
      <gml:Polygon>
        <gml:exterior>
          <gml:LinearRing>
            <gml:pos>35 20</gml:pos>
            <gml:pos>20 45</gml:pos>
            <gml:pos>5 30</gml:pos>
            <gml:pos>10 10</gml:pos>
            <gml:pos>30 10</gml:pos>
            <gml:pos>35 20</gml:pos>
          </gml:LinearRing>
        </gml:exterior>
        <gml:interior>
          <gml:LinearRing>
            <gml:pos>20 30</gml:pos>
            <gml:pos>25 20</gml:pos>
            <gml:pos>15 20</gml:pos>
            <gml:pos>20 30</gml:pos>
          </gml:LinearRing>
        </gml:interior>
      </gml:Polygon>
    </gml:surfaceMembers>
  </gml:MultiSurface>
</d:GeographyMultiPolygon>
Collection of polygons in a round-earth coordinate system
Edm.GeographyCollectionrecord
"GeographyCollection@odata.type": "#GeographyCollection",
"GeographyCollection": { 
  "type": "GeometryCollection",
  "geometries": [
    { "type": "Point",
      "coordinates": [100.0, 0.0]
    },
    { "type": "LineString",
      "coordinates": [ [101.0, 0.0], [102.0, 1.0] ]
    }
  ]
}
<d:GeographyCollection m:type="Edm.GeographyCollection">
  <gml:MultiGeometry
          gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326" />

  <gml:LineString gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326">
    <gml:pos>10 10</gml:pos>
    <gml:pos>20 20</gml:pos>
    <gml:pos>40 10</gml:pos>
  </gml:LineString>

  <gml:Polygon gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326">
    <gml:pos>10 10</gml:pos>
    <gml:pos>10 40</gml:pos>
    <gml:pos>40 10</gml:pos>
    <gml:pos>40 40</gml:pos>
  </gml:Polygon>
</d:GeographyCollection>

Collection of arbitrary Geography values.

Note, that JSON representation contains type control information (`@odata.type`). Otherwise, Olingo client reports invalid value type for `Edm.GeometryCollection` and `Edm.GeographyCollection` JSON values.


Since metadata does not contain component info, the proposal is to map this data type to CDAP record with the following fields:

  • "type" - type of GeoJSON object 
  • "points" - array of geospatial "Point" values 
  • "lineStrings" - array of geospatial "LineString" values 
  • "polygons" - array of geospatial "Polygon" values
  • "multiPoints" - array of geospatial "MultiPoint" values   
  • "multiLineStrings" - array of geospatial "MultiLineString" values   
  • "multiPolygons" - array of geospatial "MultiPolygon" values

    Nested collections can not be supported since metadata does not contain component info.


Edm.Geometry-

Abstract base type for all Geometry types
Edm.GeometryPointrecordSimilar to Edm.GeographyPointSimilar to Edm.GeographyPointPoint in a flat-earth coordinate system
Edm.GeometryLineStringrecordSimilar to Edm.GeographyLineString Similar to Edm.GeographyLineStringLine string in a flat-earth coordinate system
Edm.GeometryPolygonrecordSimilar to Edm.GeographyPolygon Similar to Edm.GeographyPolygon Polygon in a flat-earth coordinate system
Edm.GeometryMultiPointrecordSimilar to Edm.GeographyMultiPoint Similar to Edm.GeographyMultiPoint Collection of points in a flat-earth coordinate system
Edm.GeometryMultiLineStringrecordSimilar to Edm.GeographyMultiLineString Similar to Edm.GeographyMultiLineString Collection of line strings in a flat-earth coordinate system
Edm.GeometryMultiPolygonrecordSimilar to Edm.GeographyMultiPolygon Similar to Edm.GeographyMultiPolygon Collection of polygons in a flat-earth coordinate system
Edm.GeometryCollectionrecordSimilar to Edm.GeographyCollection Similar to Edm.GeographyCollection

Collection of arbitrary Geometry values


OData V4 Metadata Annotations Mapping

An annotation applies a term to a model element and defines how to calculate a value for the term application. The value of an annotation is specified as an annotation expression, which is either a constant expression representing a constant value or a dynamic expression.

"Include Metadata Annotations" configuration property indicates whether the plugin should read metadata annotations and include them to each record. In this case, each property will be mapped to a CDAP 'record' with exactly two fields "value" and "metadata-annotations". OData V4 metadata annotations are mapped to a record of the following fields:

  • term - a simple identifier, such as "UI.DisplayName" or "Core.Description", etc.
  • qualifier - a term can be applied multiple times to the same model element by providing a qualifier to distinguish the annotations.
  • expression - CDAP record that corresponds to a constant expression or a dynamic expression. Please, refer the table below for expressions mapping.
  • annotations - CDAP record that corresponds to nested annotations. Please, refer examples below for nested annotations mapping.

OData V4 Annotation Expression Mapping

EDM expression

Type

ExampleCDAP record schema
Binary
constant
<Annotation Term="org.example.display.Thumbnail">
  <Binary>T0RhdGE</Binary>
</Annotation>
  • name - field of type 'string' with value "Binary" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Boolconstant
<Annotation Term="org.example.display.ReadOnly">
  <Bool>true</Bool>
</Annotation>
  • name - field of type 'string' with value "Bool" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Dateconstant
<Annotation Term="org.example.vCard.birthDay">
  <Date>2000-01-01</Date>
</Annotation>
  • name - field of type 'string' with value "Date" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
DateTimeOffsetconstant
<Annotation Term="org.example.display.LastUpdated">
  <DateTimeOffset>2000-01-01T16:00:00.000-09:00</DateTimeOffset>
</Annotation>
  • name - field of type 'string' with value "DateTimeOffset" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Decimalconstant
<Annotation Term="org.example.display.Width">
  <Decimal>3.14</Decimal>
</Annotation>
  • name - field of type 'string' with value "Decimal" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Durationconstant
<Annotation Term="org.example.task.duration">
  <Duration>P11DT23H59M59.999999999999S</Duration>
</Annotation>
  • name - field of type 'string' with value "Duration" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
EnumMemberconstant
<Annotation Term="org.example.HasPattern">
  <EnumMember>org.example.Pattern/Red</EnumMember>
</Annotation>
  • name - field of type 'string' with value "EnumMember" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Floatconstant
<Annotation Term="org.example.display.Width">
  <Float>3.14</Float>
</Annotation>
  • name - field of type 'string' with value "Float" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Guidconstant
<Annotation Term="org.example.display.Id">
  <Guid>21EC2020-3AEA-1069-A2DD-08002B30309D</Guid>
</Annotation>
  • name - field of type 'string' with value "Guid" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Intconstant
<Annotation Term="org.example.display.Width">
  <Int>42</Int>
</Annotation>
  • name - field of type 'string' with value "Int" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Stringconstant
<Annotation Term="org.example.display.DisplayName">
  <String>Product Catalog</String>
</Annotation>
  • name - field of type 'string' with value "String" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
TimeOfDayconstant
<Annotation Term="org.example.display.EndTime">
  <TimeOfDay>21:45:00</TimeOfDay>
</Annotation>
  • name - field of type 'string' with value "TimeOfDay" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Pathdynamic
<Annotation Term="org.example.display.DisplayName">
  <Path>@vCard.Address#work/FullName</Path>
</Annotation>
  • name - field of type 'string' with value "Path" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
AnnotationPathdynamic
<Annotation Term="UI.CollectionFacet" Qualifier="Contacts">
  <Collection>
    <AnnotationPath>Supplier/@Communication.Contact</AnnotationPath>
    <AnnotationPath>Customer/@Communication.Contact</AnnotationPath>
  </Collection>
</Annotation>
  • name - field of type 'string' with value "AnnotationPath" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
LabeledElementReferencedynamic
<Annotation Term="org.example.display.DisplayName">
  <LabeledElementReference>Model.CustomerFirstName</LabeledElementReference>
</Annotation>
  • name - field of type 'string' with value "LabeledElementReference" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Nulldynamic
<Annotation Term="@UI.Address">
  <Null>
    <Annotation Term="self.Reason" String="Private" />
  </Null>
</Annotation>
NavigationPropertyPathdynamic
<Annotation Term="Capabilities.UpdateRestrictions">
  <Record>
    <PropertyValue Property="NonUpdatableNavigationProperties">
      <Collection>
        <NavigationPropertyPath>Supplier</NavigationPropertyPath>
        <NavigationPropertyPath>Category</NavigationPropertyPath>
      </Collection>
    </PropertyValue>
  </Record>
</Annotation>
  • name - field of type 'string' with value "NavigationPropertyPath" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
PropertyPathdynamic
<Annotation Term="Capabilities.UpdateRestrictions">
  <Record>
    <PropertyValue Property="NonUpdatableProperties">
      <Collection>
        <PropertyPath>CreatedAt</PropertyPath>
        <PropertyPath>ChangedAt</PropertyPath>
      </Collection>
    </PropertyValue>
  </Record>
</Annotation>
  • name - field of type 'string' with value "PropertyPath" to distinguish expression.
  • value - field of type 'string' with a string representation of expression value as declared in the service metadata document.
Anddynamic
<Annotation Term="Core.Description">
<And>
<Path>BooleanProperty1</Path>
<Path>BooleanProperty2</Path>
</And>
</Annotation>
  • name - field of type 'string' with value "And" to distinguish expression.
  • left - CDAP record that corresponds to the left expression
  • right - CDAP record that corresponds to the right expression
  • annotations - CDAP record that corresponds to nested annotations
Ordynamic
Annotation Term="Core.Description">
<Or>
<Path>BooleanProperty1</Path>
<Path>BooleanProperty2</Path>
</Or>
</Annotation>
  • name - field of type 'string' with value "Or" to distinguish expression.
  • left - CDAP record that corresponds to the left expression
  • right - CDAP record that corresponds to the right expression
  • annotations - CDAP record that corresponds to nested annotations
Eqdynamic
<Annotation Term="Core.Description">
<Eq>
<Path>SomeProperty1</Path>
<Path>SomeProperty2</Path>
</Eq>
</Annotation>
  • name - field of type 'string' with value "Eq" to distinguish expression.
  • left - CDAP record that corresponds to the left expression
  • right - CDAP record that corresponds to the right expression
  • annotations - CDAP record that corresponds to nested annotations
Nedynamic
<Annotation Term="Core.Description">
<Ne>
<Path>SomeProperty1</Path>
<Path>SomeProperty2</Path>
</Ne>
</Annotation>
  • name - field of type 'string' with value "Ne" to distinguish expression.
  • left - CDAP record that corresponds to the left expression
  • right - CDAP record that corresponds to the right expression
  • annotations - CDAP record that corresponds to nested annotations
Gtdynamic
<Annotation Term="Core.Description">
<Gt>
<Path>SomeProperty1</Path>
<Path>SomeProperty2</Path>
</Gt>
</Annotation>
  • name - field of type 'string' with value "Gt" to distinguish expression.
  • left - CDAP record that corresponds to the left expression
  • right - CDAP record that corresponds to the right expression
  • annotations - CDAP record that corresponds to nested annotations
Gedynamic
<Annotation Term="Core.Description">
<Ge>
<Path>SomeProperty1</Path>
<Path>SomeProperty2</Path>
</Ge>
</Annotation>
  • name - field of type 'string' with value "Ge" to distinguish expression.
  • left - CDAP record that corresponds to the left expression
  • right - CDAP record that corresponds to the right expression
  • annotations - CDAP record that corresponds to nested annotations
Ltdynamic
<Annotation Term="Core.Description">
<Lt>
<Path>SomeProperty1</Path>
<Path>SomeProperty2</Path>
</Lt>
</Annotation>
  • name - field of type 'string' with value "Lt" to distinguish expression.
  • left - CDAP record that corresponds to the left expression
  • right - CDAP record that corresponds to the right expression
  • annotations - CDAP record that corresponds to nested annotations
Ledynamic
<Annotation Term="Core.Description">
<Le>
<Path>SomeProperty1</Path>
<Path>SomeProperty2</Path>
</Le>
</Annotation>
  • name - field of type 'string' with value "Le" to distinguish expression.
  • left - CDAP record that corresponds to the left expression
  • right - CDAP record that corresponds to the right expression
  • annotations - CDAP record that corresponds to nested annotations
Notdynamic
<Annotation Term="Core.Description">
<Not>
<Path>SomeProperty</Path>
</Not>
</Annotation>
  • name - field of type 'string' with value "Not" to distinguish expression.
  • value - CDAP record that corresponds to the value expression
  • annotations - CDAP record that corresponds to nested annotations
Applydynamic
<Annotation Term="Core.Description">
<Apply Function="odata.concat">
<String>Product:</String>
<!-- AllDataTypesEntity/String -->
<Path>SomeProperty1</Path>
<String>(</String>
<!-- AllDataTypesEntity/Int16 -->
<Path>SomeProperty2</Path>
<String>)</String>
</Apply>
</Annotation>
  • name - field of type 'string' with value "Apply" to distinguish expression.
  • function - field of type 'string' with value of a function name
  • parameters - CDAP record of parameters with fields that correspond to parameter expressions
  • annotations - CDAP record that corresponds to nested annotations


Note: the proposal is to use the parameter index as a prefix for field name to avoid conflicts. In this case, parameters record will be a record of the following fields:

  • String_0
  • Path_1
  • String_2
  • Path_3
  • String_4
Castdynamic
<Annotation Term="Core.Description">
<Cast Type="Edm.String">
<Path>SomeProperty</Path>
</Cast>
</Annotation>
Collectiondynamic
<Annotation Term="Core.Description">
<Collection>
<String>Product</String>
<String>Supplier</String>
<String>Customer</String>
</Collection>
</Annotation>
  • name - field of type 'string' with value "Collection" to distinguish expression.
  • items - array of the item expressions
Ifdynamic
<Annotation Term="Core.Description">
<If>
<Path>SomeBooleanProperty</Path>
<String>Female</String>
<String>Male</String>
</If>
</Annotation>
  • name - field of type 'string' with value "If" to distinguish expression.
  • guard - CDAP record that corresponds to the 'guard' expression
  • then - CDAP record that corresponds to the 'then' expression
  • else - CDAP record that corresponds to the 'else' expression
  • annotations - CDAP record that corresponds to nested annotations
IsOfdynamic
<Annotation Term="Core.Description">
<IsOf Type="Edm.Boolean">
<Path>SomeProperty</Path>
</IsOf>
</Annotation>
LabeledElementdynamic
<Annotation Term="Core.Description">
<LabeledElement Name="CustomerFirstName">
<Path>SomeProperty</Path>
</LabeledElement>
</Annotation>
  • name - field of type 'string' with value "LabeledElement" to distinguish expression.
  • elementName - field of type 'string' with value of element name
  • value - CDAP record that corresponds to the value expression
  • annotations - CDAP record that corresponds to nested annotations
Recorddynamic
<Annotation Term="Core.Description">
<Record>
<Annotation Term="Core.Description" String="Annotation on record"/>
<PropertyValue Property="GivenName" Path="SomeProperty"/>
<PropertyValue Property="Age" Path="Byte"/>
</Record>
</Annotation>
  • name - field of type 'string' with value "Record" to distinguish expression.
  • type - field of type 'string' with the qualified name of a structured type in scope.
  • propertyValues - CDAP record that corresponds to the property values
  • annotations - CDAP record that corresponds to nested annotations
UrlRefdynamic
<Annotation Term="Core.LongDescription">
  <UrlRef><String>http://host/wiki/HowToUse</String></UrlRef>
</Annotation>
  • name - field of type 'string' with value "UrlRef" to distinguish expression.
  • value - CDAP record that corresponds to the value expression
  • annotations - CDAP record that corresponds to nested annotations

Notes

Complex Types Mapping

Both OData V2 and V4 support complex types. Complex types are keyless nominal structured types. The lack of a key means that instances of complex types cannot be referenced, created, updated or deleted independently of an entity type. Complex types allow entity models to group properties into common structures.

The example below demonstrates the definition of several complex types in the service metadata document:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices>
  <Schema Namespace="TestService" xmlns="http://docs.oasis-open.org/odata/ns/edm" Alias="self">
    <ComplexType Name="City">
      <Property Name="CountryRegion" Type="Edm.String" Nullable="false"/>
      <Property Name="Name" Type="Edm.String" Nullable="false"/>
      <Property Name="Region" Type="Edm.String" Nullable="false"/>
    </ComplexType>
    <ComplexType Name="Location" OpenType="true">
      <Property Name="Address" Type="Edm.String" Nullable="false"/>
      <Property Name="City" Type="TestService.City" Nullable="false"/>
    </ComplexType>
    <ComplexType Name="HomeAddress" BaseType="TestService.Location">
      <Property Name="FamilyName" Type="Edm.String"/>
    </ComplexType>
    ...
    <EntityType Name="AllDataTypesEntity">
      ...
      <Property Name="Address" Type="TestService.Location" Nullable="false"/>
      <Property Name="HomeAddress" Type="TestService.HomeAddress" Nullable="false"/>
      <Property Name="Size" Type="TestService.Size" Nullable="false"/>
    </EntityType>
    ...
    </Schema>
</edmx:DataServices>
</edmx:Edmx>

Properties of these types are mapped to a record with corresponding fields and each of them is mapped according to it's Edm type: OData V2 Data Types MappingOData V4 Data Types Mapping.

OData V4 EnumType and TypeDefinition

OData V4 supports enumeration types and type definitions, that are defined as follows:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices>
  <Schema Namespace="TestService" xmlns="http://docs.oasis-open.org/odata/ns/edm" Alias="self">
    <EnumType Name="PersonGender">
      <Member Name="Male" Value="0"/>
      <Member Name="Female" Value="1"/>
      <Member Name="Unknown" Value="2">
        <Annotation Term="Core.Description" String="Shipped with highest priority" />
      </Member>
    </EnumType>
    <TypeDefinition Name="Length" UnderlyingType="Edm.Int32">
      <Annotation Term="Org.OData.Measures.V1.Unit" String="Centimeters" />
    </TypeDefinition>
    <TypeDefinition Name="Weight" UnderlyingType="Edm.Int32">
      <Annotation Term="Org.OData.Measures.V1.Unit" String="Kilograms" />
    </TypeDefinition>
    ...
    <EntityType Name="AllDataTypesEntity">
      ...
      <Property Name="Gender" Type="self.PersonGender" Nullable="false"/>
      <Property Name="Height" Type="self.Length" />
      <Property Name="Weight" Type="self.Weight" />
    </EntityType>
    ...
    </Schema>
</edmx:DataServices>
</edmx:Edmx>

Properties of the enum types are mapped to string. Properties of the TypeDefinition are mapped according to it's underlying Edm type: OData V2 Data Types MappingOData V4 Data Types Mapping.

References

Plugin Type

  • Batch Source
  • Batch Sink 
  • Real-time Source
  • Real-time Sink
  • Action
  • Post-Run Action
  • Aggregate
  • Join
  • Spark Model
  • Spark Compute