Customizing the metamodel > Specifying key and keyed by properties > Examples of key and keyed by > Adding the KEYED BY statement
  
Adding the KEYED BY statement
Following on from the example in Creating a list of a keyed definition, add the KEYED BY statement to the Property “Version” statement to spell this out.
DEFINITION "Car Model"
{
Property "Make"
{ KEY EDIT ONEOF "Car Brand" RELATE BY "is keyed by" REQUIRED}
Property "Versions"
{ EDIT LISTOF "Car Version"
KEYED BY {"Brand":"Make", "Car Model":Name, Name}
}
}
First part of the KEYED BY statement
The first part of the KEYED BY statement, KEYED BY {"Brand":"Make", states that the “Car Version” value has a key property called Brand that must be filled in. This property will be filled with a value that is obtained from the “Make” property of the current definition, “Car Model”. The actual value is a definition of type “Car Brand”; the KEYED BY statement lists names of properties, not definition types.
This graphic is described in the surrounding text.
If the referenced property (“Brand”) and referencing key property (“Make”) were the same, you would not need to specify both; that is, if they were both “Brand”, you would have to type only:
KEYED BY {"Brand", ....
Second part of the KEYED BY statement
The second part of the KEYED BY statement, "Car Model":Name, states that the “Car Version” value has a second key property called “Car Model” that must be filled in. This property will be filled in with a value that is obtained by the Name of the current definition: the name of this “Car Model” definition.
Third part of the KEYED BY statement
The third and final part of the KEYED BY statement, Name, specifies that the last key of the “Car Version” value is keyed by its own name, as any definition is.
So if you have a “Car Model” definition open called Mustang, which has a key property “Make” filled in with Ford, you type GT in the LIST OF “Car Version” property, and the new definition Ford.Mustang.GT is added to the encyclopedia.
Adding more definitions
There is still a problem. As you add new “Car Version” definitions into the encyclopedia, “Car Model” definitions are being input that have a null property for “Car Brand”.
This graphic is described in the surrounding text.
This happens only when you add a new “Car Version” definition directly (by using the New Definition command in the explorer); not by using the ListOf dialog in the “Car Model” definition.
The reason is that the “Car Version” definition specifies that one of its key properties is “Car Model”, but does not specify that property has its own key property (“Car Brand”) that needs to be filled in with a value. Every time that you add a new “Car Version” definition, you are asked to specify a “Car Model” property. You specify that “Car Model” property, but do not specify where it gets its key “Car Brand” property value from. So nothing gets filled in for it.
To fix this, you must specify in the “Car Version” definition that its “Car Model” key property is itself keyed by properties, which must be filled in with values. Add the clause:
KEYED BY {"Make":"Brand", Name}
which means that the “Car Model” definition has a property called “Make” that will be filled in with the value in the current definition's “Brand” property.
Definition "Car Version"
{
Property "Car Model"
{ Key Edit oneOf "Car Model" KEYED BY {"Make":"Brand", Name }
RELATE BY "is keyed by" }
Property "Brand"
{ KEY EDIT OneOf "Car Brand" RELATE BY "is keyed by" }
}
Now when you add a new “Car Version” to the encyclopedia, you do not get any inadvertent null “Car Brand” definitions.
See also
Examples of key and keyed by