Instance Assignment - modelint/xuml-populate GitHub Wiki
We split the assigment statement on the assignment operator (.= or ..= in Scrall) to obtain the left and right hand sides (lhs, rhs)
We also note the cardinality of the assignment as one or many instances assigned.
Next we create a Flow_ap named tuple for the executing instance flow.
Now we need to be careful here, because an assigner does not have an executing instance. So the xi_instance_flow is None in the case of an assigner Activity.
Now we process the rhs of our statement which, in the case of an instance assignment, will always be an instance set.
We careate an instance of Instance Set which sets some initial self attributes and then we process.
(These are split out since we need some return values from process)
Instance Set.process(...)
The self.component flow attribute represents the current input to our data flow in process. This is either the executing instance or, if this is an assigner, it is None.
The first action we parse out is a special case, so we use a boolean first_action initially set to True
Now we iterate through the components of the iset parse.
For our example, we have this:
PATH_a(hops=[R_a(rnum='R2'), R_a(rnum='R28'), N_a(name='Shaft Level'), R_a(rnum='R3'), N_a(name='Accessible Shaft Level')])
And for reference, the corresponding scrall is:
/R2/R28/Shaft Level/R3/Accessible Shaft Level
So there is only one component to the instance set which happens to be a Path_a named tuple.
Since the path begins with a '/' it requires an executing instance as the starting point. This is allowed only in a Lifecycle State or Method Activity. We can tell if the path is the very first component in the instance set that it is intending to traverse from the executing instance. So if that's the case, we verify that if we have a State activity, that State is not in an Assigner State Model, otherwise we raise an exception.
Otherwise, we execute the 'PATH_a' case which tells us to populate a Traverse Action.
The Traverse Action validates the path, raising an exception if there is any inconsistency with the user (domain) class model and then we obtain the action id as well as the output flow named tuple from the Traverse Action.
For our example its ACTN1 and F3 many-instance flow of type Accessible Shaft Level
We check our first_action flag, which is True and, since it is, we set our self.initial_action to ACTN1 since that's the boundary input action of our instance set data flow.
We also check the count of components and see that this is also that ACTN1 is the final boundary action as well. In other words, our instance set was populated as a single Traversal Action.
So now we bounce back to the instance assignment to deal with the LHS and we return our boundary action which is both initial and final as well as the resultant component flow named tuple (F3).
Instance Assignment (after RHS processed)
The output of the RHS is assigned to the iset_instance_flow variable and we check to make sure that its multiplicity matches that of the assignment operator. So if we were expecting to assign at most a single instance and the flow variable is defined as having many instances, we raise an exception.
For our example, we are expecting zero to many, so we are good with the many instance flow that was returned.
We check to see if we need to prefix the labeled output flow (name on the RHS) with a case prefix and we don't since we aren't part of a switch action in this example.
Finally we ensure that the type of the LHS and RHS flows match (same class).
If the assignemnt is valid, and in our example it is, we label the output flow of the InstanceSet to the name specfied on the LHS. This is done by migrating the already populated Unlabled Flow to a Labled Flow.
Note that an Instance Assignment never outputs more than one final flow and this means that the LHS can specify at most one destination label.
So you can't do this:
a, b = /R1/R2/classA, /R1/R5/classB // This is NOT supported
Therefore we know that we are returning at most one initial and at most one final boundary action as a result of our Instance Set population.
In our example, we're returnign ACTN1 as both the initial and the final as single element sets.