Skip to content

635 Add support for parameterized activity to the uml2cif translators#637

Open
darets97 wants to merge 12 commits intomainfrom
635-add-parameterization-support-to-the-cif-translator
Open

635 Add support for parameterized activity to the uml2cif translators#637
darets97 wants to merge 12 commits intomainfrom
635-add-parameterization-support-to-the-cif-translator

Conversation

@darets97
Copy link
Collaborator

@darets97 darets97 commented Nov 12, 2025

This PR works towards #635.

The all lower case folder names for tests were inspired by petrify2uml
The TemplateParameterFlattener is a simpler implementation of the CompositeDataTypeFlattener. The regression tests happen in the activity flattener since flattening call behaviors happens during activity flattening and can hardly be taken separately in a full transformation.
To prevent templated activities from containing references to template parameters that cannot be represented down the synthesis chain all templated activities are removed after the flattening process.

@darets97 darets97 requested a review from AndreaPuffo November 12, 2025 12:48
@darets97 darets97 linked an issue Nov 12, 2025 that may be closed by this pull request
@dhendriks dhendriks changed the title 635 add parameterization support to the cif translator WIP 635 add parameterization support to the cif translator Nov 14, 2025
@dhendriks
Copy link
Collaborator

I've marked this as WIP. It is not done yet.

@darets97 darets97 changed the title WIP 635 add parameterization support to the cif translator 635 add parameterization support to the cif translator Nov 17, 2025
@darets97
Copy link
Collaborator Author

Ready for review

@darets97 darets97 changed the title 635 add parameterization support to the cif translator 635 add parameterization support to the uml2cif translator Nov 18, 2025
@darets97 darets97 changed the title 635 add parameterization support to the uml2cif translator 635 Add support for parameterized activity to the uml2cif translators Nov 18, 2025
import com.google.common.base.Verify;

/** Template parameter flattener. */
public class TemplateParameterFlattener {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I see quite a big overlap with CompositeDataTypeFlattener, I wonder if we should have some more structure between these two files. Maybe having a Flattener class, that includes activities, composite data types, and templates. Perhaps to be discussed with Dennis Hendriks and/or Wytse.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The similarity is largely by design; The two classes traverse the parse trees in a very similar manner. Ordinarily I'd argue we should use the CifObjectWalker or CifObjectVisitor (or I misunderstood the purpose of the Flattener?). In my opinion we should look into improving those classes to simplify manipulating the parse tree, right now using those two classes for generic traversal adds complexity rather than reduce it.

@AndreaPuffo
Copy link
Collaborator

I couldn't easily parse the new regression tests. Can you please past here a couple of pictures of the activity diagrams before/after of the new template flattener tests?

@darets97 darets97 requested a review from dhendriks November 18, 2025 19:26
@darets97
Copy link
Collaborator Author

Ready for next review. All comments should be resolved, but I've opted to leave them open to make the discussion easier to see.

@AndreaPuffo
Copy link
Collaborator

Looks good to me. Maybe also @dhendriks wants to have a look.

@dhendriks
Copy link
Collaborator

It's on my list to take a look.

Comment on lines -251 to -253
if (context.hasParameterizedActivities()) {
throw new RuntimeException("Translating parameterized activities to CIF is unsupported.");
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd restore this check, after the conditional call to the flattener. If we flatten, there should be no parameterized activities left. If we don't, there should also not be any (already flattened before). It then states the invariant as a sanity check.

@@ -72,9 +81,21 @@ private void transform(Element element) {
if (element instanceof Activity activityElement) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transform/destroyParameterizedActivities: I dislike the 'activityElement' etc names. It sounds like they are elements of an activity, while it is the activity itself. So, name them 'activity', 'class' (or rather 'cls' to prevent using Java keyword), etc.

// considered leaves, as are call behavior actions that call opaque behaviors.
if (behavior instanceof Activity activity && action.getAppliedStereotypes().isEmpty()) {
if (behavior instanceof Activity activity && action.getAppliedStereotypes().stream()
.filter(s -> !PokaYokeUmlProfileUtil.FORMAL_CALL_BEHAVIOR_ACTION_STEREOTYPE
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This checks if no stereotype other than the formal call behavior action stereotype is present. It should instead check for that stereotype not being present, right? So, remove the ! operator? How come this works now, and the tests don't show this issue?

// considered leaves, as are call behavior actions that call opaque behaviors.
if (behavior instanceof Activity activity && action.getAppliedStereotypes().isEmpty()) {
if (behavior instanceof Activity activity && action.getAppliedStereotypes().stream()
.filter(s -> !PokaYokeUmlProfileUtil.FORMAL_CALL_BEHAVIOR_ACTION_STEREOTYPE
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we add a method like PokaYokeUmlProfileUtil.isFormalElement to check for this, rather than doing the name check?

AExpression unfoldedOutgoing = unfoldAExpression(outgoingGuard, nameToArgument);
PokaYokeUmlProfileUtil.setOutgoingGuard(controlEdge, ACifObjectToString.toString(unfoldedOutgoing));
}
} else if (ownedElement instanceof CallBehaviorAction callBehavior) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert that the call behavior has no arguments, as then something is wrong in the flattening order?

} else if (ownedElement instanceof OpaqueAction internalAction) {
unfoldRedefinableElement(internalAction, nameToArgument);
} else if (ownedElement instanceof Constraint) {
// Constraints cannot be parameterized.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Constraints cannot be parameterized.
// Constraints cannot refer to activity parameters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants