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
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} }}
In the first part of the KEYED BY statement above, KEYED BY {"Brand":"Make", we state that the “Car Version” value we are entering 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 that we are in - “Car Model”. Note that the actual value is a definition of type “Car Brand”; the KEYED BY statement lists names of properties, not definition types.
If the referenced property (“Brand”) and referencing key property (“Make”) above were the same, we would not need to specify both; that is, if they were both “Brand”, you would only have to type:
KEYED BY {"Brand", ....
In the second part of the KEYED BY statement above, "Car Model":Name, we state that the “Car Version” value we are entering 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 that we are in - the name of this “Car Model” definition we have open.
In the third and final part of the KEYED BY statement above, Name, we specify that the last key of the “Car Version” value we are entering is keyed by its own name, as any definition is.
So if we have a “Car Model” definition open called Mustang, which has a key property “Make” filled in with Ford, we simply need to type in GT in the LIST OF “Car Version” property, and the new definition Ford.Mustang.GT will be added to the encyclopedia.
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 only happens 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 we add a new “Car Version” definition, we are asked to specify a “Car Model” property. We 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.