Operations and opTypes
Rules for MetaOperations, allowed opTypes, and rules for their use
General
Rules
Operation descriptions
Access Control
Open questions
General
The opTypes describe the different types of operation and what they do.
For most opTypes, MetaOperations are not entered in the model
description, but generated at the ModelAdapt stage of the generation
machinery - the MetaOperations are then used to generate the API
operations in later stages of the generation machinery. Only opTypes
that start with 'other' are not generated automatically and must be
explicitly entered. Automatically generated elements (MetaOperations,
MetaParameters or anything else) are set as implicit (isImplicit=True).
For opTypes that are normally autogenerated, it is possible to
override the automatic MetaOperation by entering an explicit
MetaOperation in the UML. Fo r these opTypes you can only put an implicit operation where there would otherwise have been an explicit one. For MetaOperations of
these opTypes all MetaParameters must be implicit, to ensure a
consistent interface.
OpTypes that start with 'other' ('other', 'otherQuery',
'otherModify', 'otherCreate' and 'otherDelete') are used for
MetaOperations that go beyond what can be autogenerated. These
operations can not be implicit and must be entered in the model by
hand. They can do anything you want them to, limited by
complicance to the chosen opType ('otherQuery' etc.). The base
version of these MetaOperations (opSubType=None, see below) may not
have implicit parameters.
System for operations and opTypes
Prepared for fine-grained access control, and new machinery.
MetaOperations have the following relevant elements:
container 1..1 ComplexDataType
opType 1..1 Token (enumerated)
target
0..1
ComplexDataType, ClassElement, MetaOperation
opSubType 0..1 Integer
The target ought to be 1..1, but is kept as 0..1, so you can postpone setting the targets until
the ModelAdapt stage.
Once targets are set, the combination container,opType,target,opSubType
identifies the MetaOperation uniquely.
OpSubTypes are used for overloading only - they represent different signatures for the same function. The MetaOperation with opSubType:None is the master version.
For each container,opType,target combination there must be one MetaOperation with opSubType==None.
Targets may be of four different kinds: ClassElement (or one of its subtypes), ChildClass (a class that has the container as parent class), the container, or the corresponding MetaOperation with subType==None (the master Op).
Operations with ClassElement or ChildClass targets are named according to the optype and target name. Operations with container target or
MetaOperation target have a name that is independent of the target.
Operations
with ClassElement, ChildClass or container targets are generated by
the generation software and will generally be implicit. The rules for
implicit and non-implicit MetaOperations are the same - if you cannot
have the one you cannot have the other. Whether implicit or not these
operations must have implicit parameters. Operations with
MetaOperation targets may not be implicit and the master version
(opSubType:None) may not have implicit parameters.
Operations are inherited to subclasses. Operations with a container target may be overwritten in the subclass and generally are (except for 'fullDelete'). Other operations may not be overwritten, unless they are abstract.
Most optypes are grouped in the groups: query, modify, create, delete. The 'modify' groups is further divided in modifyLink and modifyAttribute for access control purposes.
Only the 'other' optype is not in a group.
We may want to add an 'access' group, depending on how we decide to handle access control
opTypes and targets may only be combined according to the following table:
| optype | group | hicard | target | comment |
| get | query | any | ClassElement | |
| findFirst | query | !=1 | MetaRole or DataObjType attribute | |
| findAll | query | !=1 | MetaRole or DataObjType attribute | |
| sorted | query | !=1 | MetaRole | Values in sorted order. Either by local key (child links) or full key. |
| set | modify | any | ClassElement | may be override-only |
| add | modify | !=1 | ClassElement | not for frozen or n..n |
| remove | modify | !=1 | ClassElement | not for frozen or n..n |
| new | create | n/a | MetaClass | factory function |
| init | create | n/a | container | constructor |
| fullDelete | delete | n/a | container | cascading delete |
| singleDelete | delete | n/a | container | single object delete (impl.) |
| checkDelete | query | n/a | container | pre-delete check (impl.) |
| checkValid | query | n/a | container | object validity check |
| checkAllValid | query | n/a | container | recursive validity check |
| otherQuery | query | n/a | master MetaOp | Handcoded Modify nothing |
| otherModify | modify | n/a | master MetaOp | Handcoded. Modify anything |
| otherCreate | create | n/a | master MetaOp | Handcoded.Creates objects |
| otherDelete | delete | n/a | master MetaOp | Handcoded.Deletes objects |
| other | other | n/a | master MetaOp | Handcoded. do anything |
OpType 'other' is for handcoded operations that can not be (or have not been) classified more precisely. All the 'otherXXX' opTypes behave the same under code generation, the only difference is in access control.
Operation descriptions and parameters:
The exact parameters may vary between subtypes and between languages.
All modifying functions check for validity before modifying.
Returned
collections will be of the same type as the ClassElement target, unless
otherwise specified. Internal collections of objects are never exposed.
Collections returned from 'get' functions, but not from other queries,
will be immutable where the language allows.
OpTypes:
- get
- no input parameters
- returns value of element. In case of access violations will raise an error rather than return partial or incorrect results - findFirst
- Input a series of keyword=value parameters
- Returns first (if ordered) or a random object that satisfies all obj.keyword==value
Generally used with key parameters to get a unique object.
Will ignore objects where caller does not have access permission. - findAll
- Input a series of keyword=value parameters
- Returns collection of objects that satisfies all obj.keyword==value
Will ignore objects where caller does not have access permission. - sorted
- No input parameters
- Returns list of objects in link, sorted by local object key (for child links) or full key (for crosslinks).
As local object keys may contain links, also with hicard!=1, the sort order may depend on object addresses and so vary between sessions in some languages. It should be reproducible within a given session, though. - set
- Input value to set to. For collections must be a compatible collection. Individual languages may convert internally (e.g. from list to set).
- No return value. Existing values are replaced.
Setting a bidirectional link to (a permutation of) the objects already there has no effect (apart from the ordering). For ordered collections sets the order. set is the only way of controlling order in ordered elements. - add
- Input value to add to collection
- No return value - remove
- Input value to remove from collection
- No return value - new
- Input keyword=value pairs of attributes to set (like init).
- Returns new object
Factory function, creates new object with calling object as its parent. - init
- Input parent object, keyword=value pairs of attributes to set (like new).
- Returns new object
Constructor. First parameter is the parent object - fullDelete (function name: 'delete')
- No input parameters
- No return parameters
Cascading delete. Deletes object and, recursively, any object made invalid by the removal of the previous object(s).
If cascading delete is impossible for access control reasons, the function aborts. - singleDelete
Implementation function, called from fullDelete.
- Input and output parameters are implementation dependent
Deletes single object in context of cascading delete - checkDelete
Implementation function, called from fullDelete
- Input and output parameters are implementation dependent
Determines which further objects must be deleted in cascading delete, and checks access permissions. - checkValid
- Input Boolean 'complete', optional, defaults to False
- No return value
Checks object and raises an error if it is found invalid.
If complete=True carries out full checks, including checks that may trigger file loading in a file implementation - checkAllValid
- Input Boolean 'complete', optional, defaults to False
- No return value
Checks object and recursively checks its child objects, raising an error if it is found invalid.
If complete=True carries out full checks, including checks that may trigger file loading in a file implementation
- otherQuery
- Handcoded, special-purpose function
- No limits on parameters
Does not modify data. Is treated as a query for access control purposes - otherModifyy
- Handcoded, special-purpose function
- No limits on parameters
Does not create or delete objects. Is treated as a modify for access control purposes - otherCreate
- Handcoded, special-purpose function
- No limits on parameters
Creates objects. Is treated as a create for access control purposes - otherDelete
- Handcoded, special-purpose function
- No limits on parameters
Deletes objects. Is treated as a delete for access control purposes - other
- Handcoded, special-purpose function
- No limits on parameters
Has not been classified, or could not be fitted into one of the other groups. Could be a function that created and deleted objects, a special object-merge function, ...
Access control implications:
Access control is set on className,opType,targetName basis. This allows any
desired granularity. Permissions set for opType group names are valid
for the entire group.
Note that opTypes with target 'master MetaOp' pass the name of the
function as 'target name'. This allows per-function permission setting for
these operations.
For access control purposes, 'modify' permission would imply some sort of
'query' permission. There will be other similar cases. Details are left to
access control implementations.
For access control purposes MyClass.init(parent, **params) is treated as
parent.newMyClass(**params); there is no separate access control for opType 'init'.