# Metadata Module Most of the metadata captured from the OData `$metadata` HTTP request is output to a separate module. That is, all `` and `` entities are transformed to Rust `struct`s and `enum`s. The metadata information for the following entities is parsed, but not yet written to the generated metadata module: * `` * `` ## Metadata for Complex Type `struct`s For each metadata `` containing more than one ``, a corresponding metadata `struct` is created. E.G. In the `GWSAMPLE_BASIC` service, the metadata XML for the complex type `CT_Address`is: ```xml ``` This is then translated to a Rust `struct` whose name ends with `Metadata`: ```rust pub struct CtAddressMetadata { pub address_type: Property, pub building: Property, pub city: Property, pub country: Property, pub postal_code: Property, pub street: Property, } ``` All fields within a complex type metadata `struct` are of type `parse_sap_odata::property::Property`. ## Metadata for Entity Type `struct`s One or more `struct`s are created for each `` listed in the metadata. E.G. In the `GWSAMPLE_BASIC` service, the metadata XML for `BusinessPartner` is the following: ```xml ``` This XML is transformed into the following Rust `struct`: ```rust pub struct BusinessPartnerMetadata { pub key: Vec, pub address: CtAddressMetadata, pub business_partner_id: Property, pub business_partner_role: Property, pub changed_at: Property, pub company_name: Property, pub created_at: Property, pub currency_code: Property, pub email_address: Property, pub fax_number: Property, pub legal_form: Property, pub phone_number: Property, pub web_address: Property, } ``` All `` metadata `struct`s have an additional `key` field of type `Vec` All fields in a metadata `struct` will either be of type `Property` or of a previously declared complex type `struct`. ## Implementation of Metadata Entity Type `struct`s Each metadata `struct` for an `` has an implementation containing a getter function for the `key` and a getter function for each `struct` field. * The `get_key()` function returns a vector of `PropertyRef` * The field getter functions return either an instance of a `Property` or an instance of `ComplexType`. E.G. The implementation of the `BusinessPartnerMetadata` `struct` shown above starts as follows: ```rust impl BusinessPartnerMetadata { pub fn get_key() -> Vec { vec![PropertyRef { name: "business_partner_id".to_owned(), }] } pub fn get_address() -> ComplexType { ComplexType { name: "CT_Address".to_owned(), properties: vec![ Property {...}, // City Property {...}, // PostalCode Property {...}, // Street Property {...}, // Building Property {...}, // Country Property {...}, // AddressType ] } } pub fn get_business_partner_id() -> Property { Property {...} } // SNIP } ``` ## Metadata for Associations An `Association` describes the relationship between two `EntityTypes`. Using the `GWSAMPLE_BASIC` OData service as an example, there is an association called `Assoc_VH_Country_BusinessPartners` between the entity types `BusinessPartner` and `Country`. All associations have exactly two `End` objects, each of which describes the "From" and "To" sides of the association. In this case, one `Country` is related to many `BusinessPartners` ```rust pub fn vh_country_business_partners() -> Association { Association { name: "Assoc_VH_Country_BusinessPartners".to_owned(), sap_content_version: "1".to_owned(), ends: [ End { role: "FromRole_Assoc_VH_Country_BusinessPartners".to_owned(), entity_set: None, end_type: Some("VhCountry".to_owned()), multiplicity: Some("1".to_owned()), }, End { role: "ToRole_Assoc_VH_Country_BusinessPartners".to_owned(), entity_set: None, end_type: Some("BusinessPartner".to_owned()), multiplicity: Some("*".to_owned()), }, ], referential_constraint: None, } } ``` Since this is a simple relationship, there is no need to define a referential constraint. ### Referential Constraints A referential constraint describes a foreign key relationship. This is the situation in which the set of permissible values for a non-key field in one `EntityType` is defined (or constrained) by the key values found in some other `EntityType`. For example, the referential constraint in association `Assoc_VH_ProductTypeCode_Products` describes the fact that the non-key field `Product.type_code` may only use a value found in the `EntitySet` field `VhProductTypeCode.type_code`. ```rust pub fn vh_product_type_code_products() -> Association { Association { // SNIP referential_constraint: Some(ReferentialConstraint { principal: Principal { role: "FromRole_Assoc_VH_ProductTypeCode_Products".to_owned(), property_refs: vec![PropertyRef { name: "type_code".to_owned(), }], }, dependent: Dependent { role: "ToRole_Assoc_VH_ProductTypeCode_Products".to_owned(), property_refs: vec![PropertyRef { name: "type_code".to_owned(), }], }, }), } } ``` There is no requirement for the "From" and "To" field names to be the same. This can be seen in cases where an `EntitySet` containing the German field name `waers` (for currency code) is linked to the field name `currency_code` in some other `EntitySet`. ## Metadata for AssociationSets In the same way that an `Association` describes the relationship between two `EntityType`s, an `AssociationSet` describes the relationship between two `EntitySet`s.