The Platform allows you to define relationships between entities much like you would define relationships between tables in a relational database yet it provides additional aspects of Object Oriented Design.
The following types seen below are key association types and the meaning of their relationships.
Platform Type | Description | Cardinality | UML Type |
common:consists_of | The source entity contains the destination entities. | one to many | Composition |
common:aggregates_of | The source entity may have destination entity associated with it. | one to many | Aggregation |
common:relates_to | The source entity may relate to the destination entity. | many to many | Association |
common:is_a | The destination entity offers a specific qualification for the source entity. | one to one | Composition |
common:has | The destination entity may be associated with the source entity. | one to many | Aggregation |
common:uses | The destination entity depends on the source entity. | many to one | Composition |
The defacto rule for using association declarations VS association derivations is…
Our example UgottaRide solution, uses both association declarations and association derivations which we will discuss in more detail in the sections below.
You must manually add your association type(s) to your entity definitions regardless of which type of association you decide to use. The rule of thumb is to add your association types within the parent entity definition, not the child entity. In the example below (lines 40 - 44) we see that the rider entity is declaring a common:has relationship to the ride entity, which means that a single rider can have many rides (over time) associated with the rider.
/fsoc_projects/my_tenant/ugottaride/objects/model/entities/rider.json
Now add the association types in each of the following entity json files.
/fsoc_projects/my_tenant/ugottaride/objects/model/entities/rider.json
"associationTypes": {
"common:has": [
"ugottaride:ride"
]
}
/fsoc_projects/my_tenant/ugottaride/objects/model/entities/ride.json
"associationTypes": {
"common:has": [
"ugottaride:ride_assign"
]
}
/fsoc_projects/my_tenant/ugottaride/objects/model/entities/driver.json
"associationTypes": {
"common:has": [
"ugottaride:ride_assign"
]
}
/fsoc_projects/my_tenant/ugottaride/objects/model/entities/vehicle.json
"associationTypes": {
"common:has": [
"ugottaride:ride_assign"
]
}
Dev Tip While our example UgottaRide solution has only one association defined in the parent entities, the Platform supports associations in a given parent to multiple children with multiple association types as seen in the example below from another solution.
"associationTypes": {
"common:aggregates_of": [
"saplegacy:system_instance",
"saplegacy:backend",
"saplegacy:business_transaction"
],
"common:has": [
"saplegacy:system_database_status",
"saplegacy:system_logs_errors_status",
"saplegacy:system_server_status",
"saplegacy:system_workprocs_users_status"
]
}
You can get more details about the json structure of entity definitions, including the supported relationship types here:
The Platform allows you to model your solution from the perspective of a real world context. In a real world ride share service context, we know that when a rider makes a request for a new ride, the details of the requested ride will be sent in the ride request, but that the rider had previously created an account with the ride share service, so there would be no need to send all the details for the rider in the same request, just enough data to uniquely identify the rider.
In the real world we would use an association derivation for this relationship. However, we are going to create an association declaration between the rider and the ride and then send all the details of the rider and the ride within the same request (e.g. the same OTLP payload), so that you gain an understanding of how an association declarations works.
Use the following commands to add a new association declaration for the rider entity.
fsoc command to add an association declaration for an entity in your solution. | |
Command Format: | fsoc solution extend --add-associationDeclarations <entity_name> |
Command Help: | fsoc solution extend -h |
Windows Example Commands:
cd C:\fsoc_projects\my_tenant\ugottaride
fsoc solution extend --add-associationDeclarations rider
Unix-Mac Example Commands:
cd /fsoc_projects/my_tenant/ugottaride
fsoc solution extend --add-associationDeclarations rider
/fsoc_projects/my_tenant/ugottaride/objects/model/association-declarations/rider-associationDeclarations.json
[
{
"namespace": {
"name": "ugottaride",
"version": 1
},
"kind": "associationDeclaration",
"name": "ugottaride_rider_to_ride_relationship",
"displayName": "Declared Relationship between rider and ride",
"scopeFilter": "true",
"fromType": "ugottaride:rider",
"toType": "ugottaride:ride",
"associationType": "common:has"
}
]
Currently, there is no fsoc command that will generate association derivations for you. You must define them manually, however, we have some good examples for association derivations in our example UgottaRide example solution.
Dev Tip Remember, we must use association derivations to establish a relationship between two entities whos OTLP payloads are sent at different times.
Below are the “golden rules” when creating / using association derivations:
primary key = only the required attribute(s) that make an entity instance unique
We will go into more detail in the section where we create mock MELT data for the payloads, whereas here we are focusing on the association derivation definition.
Let’s look at the association derivation definition between the ride and ride_assign entities. In the real world, a rider requests a ride, and then, hopefully soon afterward, a driver then confirms the request, which triggers the creation of the ride_assign that links the driver and the vehicle to the ride.
In this real world context, we know that the payload for the ride_assign will always be ingested at a different time than the payload for the ride.
In the first example below, we have used one JSON file to add two association derivation definitions, one from ride to ride_assign and one from ride_assign to ride.
Dev Tip It is best practice to add your solution name as a prefix to the name of both association declarations and association derivations (as seen in the examples below).
Now go ahead and create the association derivations for three of our entities.
/fsoc_projects/my_tenant/ugottaride/objects/model/association-derivations/ride_assign_ride-associationDerivations.json
[
{
"namespace": {
"name": "ugottaride",
"version": 1
},
"kind": "associationDerivation",
"name": "ugottaride_ride_to_ride_assign_association",
"displayName": "Derived Relationship between ride and ride_assign",
"associationType": "common:has",
"fromType": "ugottaride:ride",
"toType": "ugottaride:ride_assign",
"scopeFilter": "true",
"mappings": {
"attributes": {
"rideid": "this.attributes.'rideid'.value"
}
}
},
{
"namespace": {
"name": "ugottaride",
"version": 1
},
"kind": "associationDerivation",
"name": "ugottaride_ride_assign_to_ride_association",
"displayName": "Derived Relationship between ride_assign and ride",
"associationType": "common:has",
"fromType": "ugottaride:ride_assign",
"toType": "ugottaride:ride",
"scopeFilter": "true",
"mappings": {
"attributes": {
"rideid": "this.attributes.'rideid'.value"
}
}
}
]
/fsoc_projects/my_tenant/ugottaride/objects/model/association-derivations/ride_assign_driver-associationDerivations.json
[
{
"namespace": {
"name": "ugottaride",
"version": 1
},
"kind": "associationDerivation",
"name": "ugottaride_driver_to_ride_assign_association",
"displayName": "Derived Relationship between driver and ride_assign",
"associationType": "common:has",
"fromType": "ugottaride:driver",
"toType": "ugottaride:ride_assign",
"scopeFilter": "true",
"mappings": {
"attributes": {
"driverid": "this.attributes.'driverid'.value"
}
}
},
{
"namespace": {
"name": "ugottaride",
"version": 1
},
"kind": "associationDerivation",
"name": "ugottaride_ride_assign_to_driver_association",
"displayName": "Derived Relationship between ride_assign and driver",
"associationType": "common:has",
"fromType": "ugottaride:ride_assign",
"toType": "ugottaride:driver",
"scopeFilter": "true",
"mappings": {
"attributes": {
"driverid": "this.attributes.'driverid'.value"
}
}
}
]
/fsoc_projects/my_tenant/ugottaride/objects/model/association-derivations/ride_assign_vehicle-associationDerivations.json
[
{
"namespace": {
"name": "ugottaride",
"version": 1
},
"kind": "associationDerivation",
"name": "ugottaride_vehicle_to_ride_assign_to_association",
"displayName": "Derived Relationship between vehicle and ride_assign",
"associationType": "common:has",
"fromType": "ugottaride:vehicle",
"toType": "ugottaride:ride_assign",
"scopeFilter": "true",
"mappings": {
"attributes": {
"vin": "this.attributes.'vin'.value"
}
}
},
{
"namespace": {
"name": "ugottaride",
"version": 1
},
"kind": "associationDerivation",
"name": "ugottaride_ride_assign_to_vehicle_association",
"displayName": "Derived Relationship between ride_assign and vehicle",
"associationType": "common:has",
"fromType": "ugottaride:ride_assign",
"toType": "ugottaride:vehicle",
"scopeFilter": "true",
"mappings": {
"attributes": {
"vin": "this.attributes.'vin'.value"
}
}
}
]
We must manually update our manifest.json file since we manually created the association derivations. Otherwise the platform won’t know about our association derivations.
/fsoc_projects/my_tenant/ugottaride/manifest.json
{
"type": "fmm:associationDerivation",
"objectsDir": "objects/model/association-derivations"
}
We’ll manually create the entity priorities.