Skip to content

#683 Add activity constraints#684

Open
AndreaPuffo wants to merge 26 commits intomainfrom
683-add-activity-constraints
Open

#683 Add activity constraints#684
AndreaPuffo wants to merge 26 commits intomainfrom
683-add-activity-constraints

Conversation

@AndreaPuffo
Copy link
Collaborator

Closes #683.

I will add a regression test once the changes are approved.

@AndreaPuffo AndreaPuffo linked an issue Feb 11, 2026 that may be closed by this pull request
@AndreaPuffo
Copy link
Collaborator Author

Documentation to be updated as well.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Need to update the method JavaDoc.

}

// Translate activity requirements.
for (Constraint umlConstraint: activity.getOwnedRules()) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it sufficient to translate the requirements like this? Should we also include all requirements of other activities that we call, etc? (all other 'relevant' activities)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I did this to be consistent with the occurrence constraints: these are considered only during the activity synthesis, not when an activity is called. Better to have a conversation offline about this.

return constraint.getContext() instanceof PrimitiveType;
}

public static boolean isActivityRequirement(Constraint constraint) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Move isActivityRequirement to just after isActivityPostconditionConstraint.

return constraint.getContext() instanceof PrimitiveType;
}

public static boolean isActivityRequirement(Constraint constraint) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Rename isActivityRequirement to isActivityRequirementConstraint, to match other methods?


public static boolean isActivityRequirement(Constraint constraint) {
return constraint.getContext() instanceof Activity activity
// It is the correct type of constraint.
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 check that it is a FormalConstraint?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It was my first choice, but I then wrote it this way to be consistent with the rest of the class and structure that we have e.g., in the validator. To be honest, if I write a isRequirementConstraint method in PokaYokeUmlProfileUtil, this method in CifContext is not needed at all. But it will not be consistent with the rest of validation, for instance.
I will remove this method and add a new one in PokaYokeUmlProfileUtil, and let's see how it looks. I think it looks better; but if consistency with the rest is more important we can revert back to this.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Rename to isClassRequirementConstraint?

.filter(r -> CifContext.isActivityRequirement(r)).map(Constraint.class::cast)
.collect(Collectors.toCollection(LinkedHashSet::new));

if (!members.equals(Sets.union(Sets.union(preAndPostconditions, intervalConstraints), activityRequirements))) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think Sets.union supports also giving 3 sets instead of 2, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not sure how to make it work, so I created a set union with stream.

checkValidActivityPrePostconditionConstraint(constraint);
} else if (CifContext.isClassConstraint(constraint)) {
checkValidClassConstraint(constraint);
} else if (CifContext.isClassConstraint(constraint) || (CifContext.isActivityRequirement(constraint))) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does it still make sense to have CifContext.isClassConstraint? Should we rename it to CifContext.isClassRequirementConstraint?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

See previous comments.

}

private void checkValidClassConstraint(Constraint constraint) {
private void checkValidClassOrActivityConstraint(Constraint constraint) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is only requirements, from classes and activities, right? So, maybe rename to checkValidRequirementConstraint?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why check this with a global scope? Why not in the scope of the activity, if it is in an activity?

@dhendriks
Copy link
Collaborator

Does editing these new constraints with the SynthML tab work?

@AndreaPuffo
Copy link
Collaborator Author

AndreaPuffo commented Feb 25, 2026

Does editing these new constraints with the SynthML tab work?

A quick example of how this works. This is the model: 2 class requirements and 2 activities, each with its own activity requirements.
Screenshot 2026-02-25 093817

Editing one activity constraint looks like this:
Screenshot 2026-02-25 100309

And finally the CIF translation of the activities (Activity1 top, Activity 2 bottom):
Screenshot 2026-02-25 093838
Screenshot 2026-02-25 093856

@@ -529,7 +528,7 @@ public static List<Stereotype> getSupportedConstraintStereotypes(Constraint cons
} else if (isPostconditionConstraint(constraint)) {
return List.of(getStereotype(constraint, ST_POSTCONDITION));
} else if (isClassRequirement(constraint)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I always forget that Activity inherits from Class. Super non-intuitive. I'd maybe rename the method to isClassOrActivityRequirementConstraint, and there add a comment in the body like // Note that 'Activity' inherits from 'Class'. or so?

return appliedStereotypes.get(0).getName().equals(ST_USAGE_PRECONDITION);
}

public static boolean isRequirementConstraint(Constraint constraint) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe move isPostconditionConstraint and isClassRequirement to just above isSynthesisPrecondition, to have methods with similar implementation close together?

return appliedStereotypes.get(0).getName().equals(ST_USAGE_PRECONDITION);
}

public static boolean isRequirementConstraint(Constraint constraint) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

There are three methods for 'where' the constraint is (precondition/postcondition of activity, rule of a class/activity), and three methods about what kind (synthesis pre, usage pre, requirement).
I'm thinking the names could be clearer. Maybe:

  • isSynthesisPreconditionConstraint/isUsagePreconditionConstraint/isRequirementConstraint to just check the stereotype that is applied, more or less as we have now (but all end their name with Constraint).
  • isPreconditionConstraint/isPostconditionConstraint/isClassRequirementConstraint -> isContainedAsActivityPrecondition/isContainedAsActivityPostcondition/isContainedAsClassOrActivityOwnedRule to see where they are contained in the model. That distinguishes their names better.

} else if (CifContext.isClassConstraint(constraint)) {
checkValidClassConstraint(constraint);
} else if (CifContext.isClassConstraint(constraint)
|| (PokaYokeUmlProfileUtil.isRequirementConstraint(constraint)))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can it ever be a requirement constraint and not a class constraint? What constraints that we support are allowed in classes that are not requirements?
In other words, can't we only check for being a requirement constraint, as that also matches checkValidRequirementConstraint?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This should be fixed with the new methods.

}

@Check
private void checkValidConstraint(Constraint constraint) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if we should check here for what kind of constraint it is, and then in the methods we invoke, that they are in the right place (a supported place), maybe? Now it seems mixed.
Together with the renaming of the 6 methods in PokaYokeUmlProfileUtil (see other comment), I think we could probably remove the CifContext methods, and make it a lot cleaner. I don't think it would give a lot of changes in many places. Maybe a few of the context methods need an extra method in the profile util then, though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added new methods in PokaYokeUmlProfileUtil and removed a few from CifContext.

AndreaPuffo and others added 9 commits March 9, 2026 14:13
Co-authored-by: Dennis Hendriks <dh_tue@hotmail.com>
UmlToCifTranslator, FlattenUmlActivity: rename methods
- make methods public
- add occurrence constraint and primitive type constraint methods
PokaYokeProfileValidator: use the new methods
UmlToCameoTransformer, Uml2GalTranslator, PokaYokeProfileValidator: use
the PokaYokeUmlProfileUtil method
AbstractActivityDependencyOrderer: use the PokaYokeUmlProfileUtil method
constraint
PokaYokeProfileValidator: use the PokaYokeUmlProfileUtil methods
@AndreaPuffo
Copy link
Collaborator Author

Ready for review, best commit-by-commit.

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.

Add activity constraints

2 participants