This API is used to interrogate the service metadata document of the OData provider. Both Dynamic API and proxy classes use this API for their functionality. When an application uses this API, it is usually because it needs to discover the data model at run time for a number of very specific use cases.
The API maps closely to the contents of the service metadata document, also known as the Common Schema Definition Language (CSDL) document. Therefore, as long as the items and their relationships in the CSDL for a particular version of OData are understood, usage of the API follows naturally.
Metadata API is contained in the
Metadata may be loaded online as the application starts or embedded within the generated classes with a supplied XML document. Once loaded by the Metadata API, it resides in memory and can be interrogated by the application. The generic class,
DataService, returns an instance of CsdlDocument using the
getMetadata method. It is from this CsdlDocument instance that we can go through the data model.
CsdlDocument csdlDocument = dataService.getMetadata();
val csdlDocument = dataService.metadata
The CSDL document has a hierarchical structure that includes entity containers as the logical containers of entity sets and service operations.
Unless you are sure that there is only one entity container in the service metadata document, it is recommended that you start the metadata interrogation through the entity container. With OData v2 and v3, there can be multiple entity containers within a service metadata document and one of those is marked as the default container. Containers can be accessed from the CSDL document as follows:
EntityContainer container = csdlDocument.getDefaultContainer();
val container = csdlDocument.defaultContainer
We can also access the entity container using its qualified name,
<namespace>.<container name>, for example,
EntityContainerMap containerMap = csdlDocument.getEntityContainers(); EntityContainer container = containerMap.get("ODataAPI.EventService");
val containerMap = csdlDocument.entityContainers val container = containerMap.get("ODataAPI.EventService")
While entity sets are defined within an entity container, the CsdlDocument instance has a map of all the entity sets from all the containers. You can get the entity set directly from the CsdlDocument instance or from a container.
1 2 3 4
// From default container EntitySet eventSet = csdlDocument.getEntitySet("Events"); // OR from EventService container EntitySet eventSet = csdlDocument.getEntitySet("EventService.Events");
1 2 3 4
// From default container val eventSet = csdlDocument.getEntitySet("Events") // OR from EventService container val eventSet = csdlDocument.getEntitySet("EventService.Events")
getEntitySet method can handle both qualified name and local name. On the other hand, if you want to make sure the entity set being retrieved is within the container, use the following:
1 2 3
EntityContainer container = csdlDocument.getDefaultContainer(); EntitySetMap entitySetMap = container.getEntitySets(); EntitySet eventSet = entitySetMap.get("Events");
1 2 3
val container = csdlDocument.defaultContainer val entitySetMap = container.entitySets val eventSet = entitySetMap.get("Events")
Each CSDL document has within it the definition of each entity type. Therefore, it is possible to get the map of all entity types defined within the document. The entity type is retrieved using the qualified name, which consists of the namespace and the entity type name.
If there is no entity for the name specified when using the
getEntityType method of CsdlDocument, an undefined error will be thrown.
1 2 3 4
EntityType eventType = csdlDocument.getEntityType("ODataAPI.Event"); EntityTypeMap entityTypeMap = csdlDocument.getEntityTypes(); EntityType eventType = entityTypeMap.get("ODataAPI.Event");
1 2 3 4
val eventType = csdlDocument.getEntityType("ODataAPI.Event") val entityTypeMap = csdlDocument.entityTypes val eventType = entityTypeMap.get("ODataAPI.Event")
You can also start from the container by looking for the entity set containing the entity type and then get the entity type as follows:
1 2 3 4 5
EntityContainer container = csdlDocument.getDefaultContainer(); EntitySetMap entitySetMap = container.getEntitySets(); EntitySet eventSet = entitySetMap.get("Events"); // Get entity type for entity set Events EntityType eventType = event.getEntityType();
1 2 3 4 5
val container = csdlDocument.defaultContainer() val entitySetMap = container.entitySets val eventSet = entitySetMap.get("Events") // Get entity type for entity set Events val eventType = eventSet.entityType
Following the OData v4 nomenclature, properties are either structural or navigational. Both types are contained within the same property map returned by the entity type.
1 2 3 4 5 6 7 8
PropertyMap properties = eventType.getPropertyMap(); // Get structural property Property nameProp = properties.get("Name"); assertTrue(nameProp.isStructural()); // Get navigation property Property sessionsProp = properties.get("Sessions"); assertTrue(sessionsProp.isNavigation()); assertTrue(sessionsProp.isList());
1 2 3 4 5 6 7 8
val propertyMap = eventType.getPropertyMap() // Get structural property val nameProp = propertyMap.get("Name") assertTrue(nameProp.isStructural()) // Get navigation property val sessionsProp = propertyMap.get("Sessions") assertTrue(sessionsProp.isNavigation()) assertTrue(sessionsProp.isList())
Because the Android SDK is based on the OData v4 specification, associations and association sets are no longer available. You can instead determine whether a navigation property is referring to multiple instances or a single instance by using the
In most cases, you are not likely to need to use the Metadata API when creating your applications. You can look up entity sets, entity types, and properties using the proxy classes or Dynamic API as long as you have a prior knowledge of the data model. For example, you will need to know the name of the entity set to look it up.
The Metadata API can support discovery of the data model at runtime. There is no need to know any of the names. Instead, you can start from the entity container, iterate through all the entity sets, examine the entity types associated with the entity set, and visit all the properties of the entity type.
Refer to the code fragment for information on iterating through all the entity sets and retrieving every collection from the provider. For each entity set, the corresponding entity type is used to get the values of its structural properties as a string.