Data Types having Dimensions
In the LN Studio, repeatable attributes are modeled by setting the ‘dimensions’ for a data type. Repeatable attributes are attributes that can occur multiple times within their parent. This concept is comparable to array columns as used in the LN data model.
In a business interface implementation, the following can be modeled for LN:
- One-to-one mapping:
Use an attribute having n dimensions, use an array column having the same number dimensions, use an attribute implementation having the same number of dimensions. In theory an attribute (and attribute implementation) can have more dimensions if it is input-only. And an attribute (and attribute implementation) can have fewer dimensions if it is output-only. But these situations are unsupported in a one-to-one mapping. In such cases a calculation (see below) must be used instead.
- Element mapping:
Use an array column (data type of table column has multiple dimensions) and map one or more elements to attribute implementations. This is done through the ‘Additional Instructions’ property. For example, a table has a column prcs (Prices). Three attributes are defined, being costPrice, localPrice and cataloguePrice. These attributes must be mapped to the first three array elements of the prcs column. In that case, map costPrice to column prcs and in the Additional Instruction for the attribute implementation, fill in “1”. For localPrice fill in “2” and for cataloguePrice use “3”. The attributes and attribute implementations use a data type with no dimensions. Only the table column will use dimensions.
- Using a calculation:
- On get hook, calculated attribute implementation has dimensions, and used attributes have no dimensions.
- On get hook, calculated attribute implementation has dimensions, and used attributes have one or more dimensions.
- On get hook, calculated attribute implementation has no dimensions, and one or more used attributes have multiple dimensions
- On set hook, attribute implementation has multiple dimensions, and used attributes have no dimensions.
- On get hook, attribute implementation has multiple dimensions, and used attributes have one or more dimensions.
- On set hook, attribute implementation has no dimensions, and one or more used attributes have multiple dimensions
It is not possible to map a repeatable attribute directly to separate rows of a table for the component. For example, component Order maps to the Order table. Attribute Order.note having multiple dimensions maps to the rows of an OrderNotes table. In such case, the note attribute implementation must be implemented using an on get and on set hook, which reads and updates the table (through its DAL).
The same domain can be used in LN for table fields with or without dimensions. In that case multiple datatypes are needed, one for every combination of domain (native data type) and dimensions value. Each data type must have a unique name, but the native data type will then be the same. For example:
Datatype without dimensions | Datatype having 3 dimensions | |
---|---|---|
Datatype | ppmmmvalu (or any other name) | ppmmmvalu3 (or any other name) |
Native data type | ppmmmvalu | ppmmmvalu |
Dimensions | empty | 3 |
When using repeatable attributes, the constraint are applicable for LN:
- In case of a ‘one-to-one mapping’, the value of the dimensions property must match.
- In case of an ‘element mapping’, the specified element must exist. In other words, the element must be greater than 0 and less than or equal to the number of elements for the array column.
- If filled, the dimension must always contain a number. Other values (including for example multi-dimensional arrays such as “10, 20”) are not allowed.
- A dimension can only be used for a leaf attribute. So it cannot be used for a ‘complex’ data type or for an attribute group.
- A qualifier cannot be repeatable.
A repeatable attribute can be defined as dynamic by setting the dimension to 0. In that case the number of repeatable elements does not need to be known at beforehand. This is useful for processing incoming BODs.
Developing Hooks
The use of dimensions impacts the interface for hooks.
For set/get hooks, the interface is for example, an on set hook defined for an attribute implementation 'note' having dimension 5. Three used attributes are specified. The first attribute 'optionalNote' has no dimension and the other ones ('extraNotes' and 'numbers') have dimension 2. The last one ('numbers') is a long array, while the other ones are strings.
In that case the hook content for the on set hook is for example:
if i.optionalNote.iSet then
o.note(1,1) = i.optionalNote
else
io.note.isSet(1) = false
endif
o.note(1,2) = i.extraNotes(1,1)
o.note(1,3) = i.extraNotes(1,2)
o.note(1,4) = str$(i.numbers(1))
o.note(1,5) = str$(i.numbers(2))
return(0) | OK
Note that strings have an extra dimension.
For method hooks (before/on/after get/set), the interface is comparable.
This is an example of a before execute hook:
if not i.code.isSet(1) or not i.code.isSet(2) then
io.cancel = true
endif
return(0) | OK
This is an example of an on execute method hook:
#pragma used dll oppmmmdll0001
return( ppmmmdll0001.calculate.quantites.and.add.notes(i.item, i.item.isSet,
i.description(1,1), i.description.isSet(1),
i.description(1,2), i.description.isSet(2),
io.quantity(1), io.quantity.isSet(1),
io.quantity(2), io.quantity.isSet(2),
o.note(1,1), io.note.isSet(1),
o.note(1,2), io.note.isSet(2)) )