About this Example

This QDM represents information about people and the houses they own. Basic Information Structure provides a model of the information we wish to represent. People QDM and House QDM provide the complete QDM code. The other topics highlight aspects and techniques used in these QDMs.

Basic Information Structure

Let us consider the following data structure:

For any individual, we represent the following information in a people data type:

  • Name: consisting of first name, middle name and last name
  • Date of birth
  • Gender
  • Mother
  • Father
  • Spouse
  • Their home
  • The houses they own

For the house, we represent the following information in a house data type:

  • Address: consisting of the street, the city, the zipcode, the state and the country
  • Owner

People QDM

Below is the QDM representing the people information we want to exchange:

people.xml
<?xml version="1.0"?>
<types xmlns="http://www.qeo.org/formal/2013/Qeo_Data_Model" version="0.1">
  <include file="qeo_types.xml"/>
  <module name="org::qeo::sample::people">
    <struct name="Name">
      <member name="first" type="string" />
      <member name="middle" type="string" sequenceMaxLength="-1" />
      <member name="last" type="string" />
    </struct>
    <struct behavior="state" name="Person">
      <member name="id" key="true" type="nonBasic" nonBasicTypeName="org::qeo::UUID">
        <doc>A person's unique ID.</doc>
      </member>
      <member name="name" type="nonBasic" nonBasicTypeName="Name" />
      <member name="birthDate" type="int64" />
      <member name="gender" type="string" />
      <member name="mother" type="nonBasic" nonBasicTypeName="org::qeo::UUID" />
      <member name="father" type="nonBasic" nonBasicTypeName="org::qeo::UUID" />
      <member name="spouse" type="nonBasic" nonBasicTypeName="org::qeo::UUID" />
      <member name="home" type="nonBasic" nonBasicTypeName="org::qeo::UUID" />
      <member name="ownedHouses" type="nonBasic" nonBasicTypeName="org::qeo::UUID" sequenceMaxLength="-1" />
    </struct>
  </module>
</types>

House QDM

Below is the QDM for a house:

housing.xml
 <?xml version="1.0"?>
<types xmlns="http://www.qeo.org/formal/2013/Qeo_Data_Model" version="0.1">
  <include file="qeo_types.xml"/>
  <module name="org::qeo::sample::housing">
    <struct name="Address">
      <member name="street" type="string" />
      <member name="city" type="string" />
      <member name="zipcode" type="string" />
      <member name="state" type="string" />
      <member name="country" type="string" />
    </struct>
    <struct behavior="state" name="House">
      <member name="id" key="true" type="nonBasic" nonBasicTypeName="org::qeo::UUID">
        <doc>A house's unique ID.</doc>
      </member>
      <member name="address" type="nonBasic" nonBasicTypeName="Address" />
      <member name="owners" type="nonBasic" nonBasicTypeName="org::qeo::UUID" sequenceMaxLength="-1" />
    </struct>
  </module>
</types>

Defining Auxiliary Structs and Using them in Member Declarations

IN THE PEOPLE DATA MODEL

The people data model shows how we can define and use a struct (without behaviour) as a member in another struct. In it, there are two structs:

  • Person: the major struct
  • Name: a supporting struct, which is used as a member in Person.

This is shown in the diagram below:

STEP 1: DEFINE THE STRUCT

  First, we define the Name struct:

    <struct name="Name">
      <member name="first" type="string" />
      <member name="middle" type="string" sequenceMaxLength="-1" />
      <member name="last" type="string" />
    </struct>
STEP 2: USE IT AS MEMBER

Then we use it as a member type for the Person struct:

<member name="name" type="nonBasic" nonBasicTypeName="Name" />
Icon

"middle" is a sequence. There can be any number of middle names. We use the sequenceMaxLength attribute to indicate this. Since Qeo only supports unlimited sequences at this point, we define the value of this attribute as -1. other values are not allowed (for now).

IN THE HOUSE DATA MODEL

Similarly to the case described above, the House struct uses the Address struct as a member type. This struct is defined as follows:

<struct name="Address">
<member name="street" type="string" />
<member name="city" type="string" />
<member name="zipcode" type="string" />
<member name="state" type="string" />
<member name="country" type="string" />
</struct>

The House struct then uses this struct as a member:

<member name="address" type="nonBasic" nonBasicTypeName="Address" />

Defining Key Members

We need to be able to clearly identify instances of a data type. We therefore use one of its members as a key member. An instance can be clearly defined by the value of its key member. Only main structs require a key. Auxiliary members used as member types do not require a key. In order to declare a member as key, we provide it with the key="true" attribute. In the house and person QDMs, id is a key member:

<member name="id" key="true" type="nonBasic" nonBasicTypeName="org::qeo::UUID">
Icon

It is good practice to use UUID as type for identifying members.

Referencing Structs as Members

Consider our example. In the Person struct, mother, father, and spouse are members of the people type, and ownedHouses is of the housing type. These members do not contain the actual data type instances, but rather contain a reference to them. In order to make this work, we need to:

  1. Make sure that the type of the referencing member and the type of the key member to which we are referencing are the same.
  2. Include the data model that defines the data type to which we are referencing in the data type we are referencing from.
STEP 1: DEFINE THE REFERENCING MEMBER

 In the example, we followed the practice of using UUID as id member type of the Person and House struct.

  <member name="id" key="true" type="nonBasic" nonBasicTypeName="org::qeo::UUID">

All referencing members are therefore declared as UUID type as well:

<...>
<member name="mother" type="nonBasic" nonBasicTypeName="org::qeo::UUID" />
<member name="father" type="nonBasic" nonBasicTypeName="org::qeo::UUID" />
<member name="spouse" type="nonBasic" nonBasicTypeName="org::qeo::UUID" />
<member name="home" type="nonBasic" nonBasicTypeName="org::qeo::UUID" />
<member name="ownedHouses" type="nonBasic" nonBasicTypeName="org::qeo::UUID" sequenceMaxLength="-1" />
<...>
<member name="owners" type="nonBasic" nonBasicTypeName="org::qeo::UUID" sequenceMaxLength="-1" />
<...>


Icon

ownedHouses and owners are sequences. A house can have multiple owners and and a person can have multiple houses.  However, only one house is marked as "home".

STEP 2: INCLUDE THE REFERENCED MODEL

To include the referenced data models, we use the include statement:

<...>
<include file="housing.xml" />
<...>
<include file="people.xml" />
<...>
EXAMPLE

The diagram below shows an example of how several instances of the data types can be linked through referencing:

Using Predefined Data Models

In the same way we can use predefined structs inside of other structs, we can use predefined, standard data models. This adds a degree of standardization to your Data Models. Even though such a library does not yet exist, it is the intention of the Qeo programme to provide it. 

Both people and house use UUID,  a struct defined in the Qeo library, defined in the qeo_types.xml file. 

Snippet from Qeo.xml
<struct name="UUID">
      <doc>The Qeo UUID type.</doc>
      <member name="upper" type="int64" />
      <member name="lower" type="int64" />
</struct>

In order to incorporate this struct into our QDM, we use the include statement:

<include file="qeo_types.xml"/>

Attachments:

referencing.jpg (image/jpeg)
Usingstructsasmembers.jpg (image/jpeg)