« Back to University of Vienna - OMILAB

Creating Predefined Elements on Drawing Area

Combination View Flat View Tree View
Threads [ Previous | Next ]
toggle
Dear ADOxx Team!

I want to create modelling elements which can only be placed on other modelling elements. I think of e.g. process elements which can only be placed on swimlanes elemements but not outside of them. What is the most elegant way to do this? Do you have example code?
How can I detect which elements are placed on a certain model element?

Thank you!

Kind regards

RE: Creating Predefined Elements on Drawing Area
Answer
8/16/16 8:48 AM as a reply to Anonymous.
Hi,

in the following, please find your question "sliced" into 2 elements: a) preventing the creation of instances based on some arbitrary condition and b) identifying the containment of objects. In case you have a swimlane instead of a container/aggregation, have a look at the "Allowed objects" attribute as described in c).

a) Prevent instance creation:
It is possible to implement such a functionality by listening to the "AfterCreateModelingNode" event. Details on the event can be found here. This event distinguishes different ways how the object has been created (modelled, copy/cut-paste, undo). You can therefore use this origin parameter to handle different user interactions accordingly. To prevent the creation, you can use the preset parameters to delete the object after its creation again.
An example snipplet of the event to prevent any kind of instance creation can be found below. To try it out, copy/paste it in the Library attribute "External coupling" of the dynamic library.

1ON_EVENT "AfterCreateModelingNode" {
2   # preset variables by event: modelid, objid, classid, origin, where origin is 0 for modelled instances, 1 for copy/cut-paste instances and 2 for undo created instances
3   # in order to handle instances of different classes or origins differently, conditions need to be added here.
4   CC "Core" DELETE_OBJ modelid: (modelid) objid: (objid)
5   CC "AdoScript" ERRORBOX "Instance creation is prohibited!"
6}

An example snipplet of the event with conditions can be found below

 1ON_EVENT "AfterCreateModelingNode" {
 2   # preset variables by event: modelid, objid, classid, origin, where origin is 0 for modelled instances, 1 for copy/cut-paste instances and 2 for undo created instances
 3   # in order to handle instances of different classes or origins differently, conditions need to be added here.
 4   # example: check for class name and allow only classes of type "Allowed"
 5   CC "Core" GET_CLASS_NAME classid: (classid)
 6   SET sCurrentClassName: (classname)
 7   IF (sCurrentClassName <> "Allowed") {
 8     CC "Core" DELETE_OBJ modelid: (modelid) objid: (objid)
 9     CC "AdoScript" ERRORBOX "Instance creation is prohibited!"
10   }
11}

In the screenshot below you can see the code in operation: Instances of classes in green of type "Allowed" can be created, instances of class "Example class" are not possible. Further details are also available in the FAQ post here.

b) Detect containment relation (for containers, NOT swimlanes)
The "Is inside" relation of ADOxx can be used to detect a containment relation. This relation is a platform relation class, invisible to the user and established between any class inherited from __D-construct__ and the classes inherited from __D_aggregation__. You therefore need to check whether your container is inherting this functionality from the __D_aggregation__ by looking at the class hierarchy in the Development toolkit. As soon as this is ok, a condition can be developed for that using an AQL expression.
Example AQL checking whether the instance "Allowed-628200" is connected with the "Is inside relation"
1({"Allowed-628200":"Allowed"}->"Is inside")

This can be added to the above code to prevent creation by using the AdoScript command CC "AQL" EVAL_AQL_EXPRESSION expr:"<\"Activity\">" modelid: (modelid) (ATTENTION: make sure you mask all quotes with a backslash). In case the returned list of objects is empty, this would mean that the object is created outside of the container.

 1ON_EVENT "AfterCreateModelingNode" {
 2   # preset variables by event: modelid, objid, classid, origin, where origin is 0 for modelled instances, 1 for copy/cut-paste instances and 2 for undo created instances
 3   # in order to handle instances of different classes or origins differently, conditions need to be added here.
 4   # example: check if created in a container
 5   CC "Core" GET_OBJ_NAME objid: (objid)
 6   SET sCurrentObjName: (objname)
 7   CC "Core" GET_CLASS_NAME classid: (classid)
 8   SET sCurrentClassName: (classname)
 9   CC "AQL" EVAL_AQL_EXPRESSION expr: ("({\""+sCurrentObjName+"\":\""+sCurrentClassName+"\"}->\"Is inside\")") modelid: (modelid)
10   IF (tokcnt(objids) = 0 ) {
11     CC "Core" DELETE_OBJ modelid: (modelid) objid: (objid)
12     CC "AdoScript" ERRORBOX "Instance creation is prohibited outside of containers!"
13   }
14}

c) "Allowed objects" for Swimlanes
In case your container is a swimlane, you can use a simplifed approach by specifying the allowed objects similar as you declare modeltype containment in the "Allowed objects" platform attribute

Syntax:
1AllowedObjects :  ALLOWED from:Basis
2{ InclOrExclClass } .
3Basis :     all | none .
4InclOrExclClass :     INCL className |
5EXCL className .
Example
1ALLOWED from:none
2INCL "Allowed class"
3INCL "Example class"
Please find enclosed an example library used for the screenshot.
Attachment

Attachments: Example_prevent.PNG (55.8k), Prevent Instance Creation Experimentation Library.abl (11.4k)