|
21 | 21 | import java.util.Set; |
22 | 22 | import java.util.stream.Collectors; |
23 | 23 |
|
| 24 | +import org.eclipse.emf.common.util.EList; |
24 | 25 | import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext; |
25 | 26 | import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramDescriptionService; |
26 | 27 | import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramQueryService; |
|
44 | 45 | import org.eclipse.syson.services.NodeDescriptionService; |
45 | 46 | import org.eclipse.syson.services.UtilService; |
46 | 47 | import org.eclipse.syson.services.api.SiriusWebCoreServices; |
| 48 | +import org.eclipse.syson.sysml.ActionUsage; |
| 49 | +import org.eclipse.syson.sysml.AllocationUsage; |
47 | 50 | import org.eclipse.syson.sysml.BindingConnectorAsUsage; |
48 | 51 | import org.eclipse.syson.sysml.ConnectionUsage; |
49 | 52 | import org.eclipse.syson.sysml.Connector; |
|
53 | 56 | import org.eclipse.syson.sysml.Feature; |
54 | 57 | import org.eclipse.syson.sysml.FeatureMembership; |
55 | 58 | import org.eclipse.syson.sysml.FlowUsage; |
| 59 | +import org.eclipse.syson.sysml.IncludeUseCaseUsage; |
56 | 60 | import org.eclipse.syson.sysml.InterfaceUsage; |
| 61 | +import org.eclipse.syson.sysml.Membership; |
57 | 62 | import org.eclipse.syson.sysml.Namespace; |
| 63 | +import org.eclipse.syson.sysml.OwningMembership; |
58 | 64 | import org.eclipse.syson.sysml.PartUsage; |
59 | 65 | import org.eclipse.syson.sysml.PortUsage; |
| 66 | +import org.eclipse.syson.sysml.ReferenceSubsetting; |
| 67 | +import org.eclipse.syson.sysml.ReferenceUsage; |
60 | 68 | import org.eclipse.syson.sysml.RequirementUsage; |
61 | 69 | import org.eclipse.syson.sysml.SatisfyRequirementUsage; |
62 | 70 | import org.eclipse.syson.sysml.StateDefinition; |
63 | 71 | import org.eclipse.syson.sysml.StateUsage; |
| 72 | +import org.eclipse.syson.sysml.Succession; |
| 73 | +import org.eclipse.syson.sysml.SuccessionAsUsage; |
64 | 74 | import org.eclipse.syson.sysml.SysmlFactory; |
65 | 75 | import org.eclipse.syson.sysml.Type; |
| 76 | +import org.eclipse.syson.sysml.TransitionUsage; |
66 | 77 | import org.eclipse.syson.sysml.Usage; |
| 78 | +import org.eclipse.syson.sysml.UseCaseUsage; |
67 | 79 | import org.eclipse.syson.sysml.ViewUsage; |
68 | 80 | import org.eclipse.syson.sysml.metamodel.helper.EMFUtils; |
69 | 81 | import org.eclipse.syson.sysml.metamodel.services.ElementInitializerSwitch; |
@@ -701,6 +713,185 @@ public SatisfyRequirementUsage reconnectSatisfyRequirementTarget(SatisfyRequirem |
701 | 713 | return sru; |
702 | 714 | } |
703 | 715 |
|
| 716 | + /** |
| 717 | + * Reconnects the source of an allocate edge. |
| 718 | + * |
| 719 | + * @param allocationUsage |
| 720 | + * the allocate edge to reconnect |
| 721 | + * @param newSource |
| 722 | + * the new source |
| 723 | + * @return the allocate edge |
| 724 | + */ |
| 725 | + public Element reconnectSourceAllocateEdge(AllocationUsage allocationUsage, Element newSource) { |
| 726 | + if (newSource instanceof Usage usage) { |
| 727 | + var features = this.getAllocateEdgeFeatures(allocationUsage); |
| 728 | + if (features.size() == 2) { |
| 729 | + var reference = features.getFirst().getOwnedReferenceSubsetting(); |
| 730 | + if (reference != null) { |
| 731 | + reference.setReferencedFeature(usage); |
| 732 | + } |
| 733 | + } |
| 734 | + } |
| 735 | + return allocationUsage; |
| 736 | + } |
| 737 | + |
| 738 | + /** |
| 739 | + * Reconnects the target of an allocate edge. |
| 740 | + * |
| 741 | + * @param allocationUsage |
| 742 | + * the allocate edge to reconnect |
| 743 | + * @param newTarget |
| 744 | + * the new target |
| 745 | + * @return the allocate edge |
| 746 | + */ |
| 747 | + public Element reconnectTargetAllocateEdge(AllocationUsage allocationUsage, Element newTarget) { |
| 748 | + if (newTarget instanceof Usage usage) { |
| 749 | + var features = this.getAllocateEdgeFeatures(allocationUsage); |
| 750 | + if (features.size() == 2) { |
| 751 | + var reference = features.get(1).getOwnedReferenceSubsetting(); |
| 752 | + if (reference != null) { |
| 753 | + reference.setReferencedFeature(usage); |
| 754 | + } |
| 755 | + } |
| 756 | + } |
| 757 | + return allocationUsage; |
| 758 | + } |
| 759 | + |
| 760 | + /** |
| 761 | + * Reconnects the source of a succession edge. |
| 762 | + * |
| 763 | + * @param succession |
| 764 | + * the succession edge |
| 765 | + * @param oldSource |
| 766 | + * the previous source |
| 767 | + * @param newSource |
| 768 | + * the new source |
| 769 | + * @return the succession edge |
| 770 | + */ |
| 771 | + public Element reconnectSourceSuccessionEdge(SuccessionAsUsage succession, Element oldSource, Element newSource) { |
| 772 | + EList<Feature> ends = succession.getConnectorEnd(); |
| 773 | + if (!ends.isEmpty()) { |
| 774 | + this.setConnectorEndFeature(ends.getFirst(), newSource); |
| 775 | + } |
| 776 | + return succession; |
| 777 | + } |
| 778 | + |
| 779 | + /** |
| 780 | + * Reconnects the target of a succession edge. |
| 781 | + * |
| 782 | + * @param succession |
| 783 | + * the succession edge |
| 784 | + * @param oldTarget |
| 785 | + * the previous target |
| 786 | + * @param newTarget |
| 787 | + * the new target |
| 788 | + * @return the succession edge |
| 789 | + */ |
| 790 | + public Element reconnectTargetSuccessionEdge(SuccessionAsUsage succession, Element oldTarget, Element newTarget) { |
| 791 | + EList<Feature> ends = succession.getConnectorEnd(); |
| 792 | + if (ends.size() > 1) { |
| 793 | + this.setConnectorEndFeature(ends.get(1), newTarget); |
| 794 | + } |
| 795 | + return succession; |
| 796 | + } |
| 797 | + |
| 798 | + /** |
| 799 | + * Reconnects the source of a transition edge. |
| 800 | + * |
| 801 | + * @param transition |
| 802 | + * the transition to reconnect |
| 803 | + * @param newSource |
| 804 | + * the new source |
| 805 | + * @return the transition |
| 806 | + */ |
| 807 | + public TransitionUsage reconnectSourceTransitionEdge(TransitionUsage transition, ActionUsage newSource) { |
| 808 | + if (newSource instanceof TransitionUsage || !this.isValidTransitionTarget(newSource, transition.getTarget())) { |
| 809 | + this.feedbackMessageService.addFeedbackMessage(new Message("Invalid new source for transition", MessageLevel.WARNING)); |
| 810 | + return transition; |
| 811 | + } |
| 812 | + transition.getOwnedMembership().stream() |
| 813 | + .filter(Membership.class::isInstance) |
| 814 | + .findFirst() |
| 815 | + .ifPresent(membership -> membership.setMemberElement(newSource)); |
| 816 | + |
| 817 | + Succession succession = transition.getSuccession(); |
| 818 | + succession.getFeatureMembership().stream() |
| 819 | + .filter(EndFeatureMembership.class::isInstance) |
| 820 | + .map(EndFeatureMembership.class::cast) |
| 821 | + .findFirst() |
| 822 | + .ifPresent(endFeatureMembership -> endFeatureMembership.getOwnedRelatedElement().stream() |
| 823 | + .findFirst() |
| 824 | + .ifPresent(feature -> feature.getOwnedRelationship().stream() |
| 825 | + .filter(ReferenceSubsetting.class::isInstance) |
| 826 | + .map(ReferenceSubsetting.class::cast) |
| 827 | + .findFirst() |
| 828 | + .ifPresent(referenceSubsetting -> referenceSubsetting.setReferencedFeature(newSource)))); |
| 829 | + return transition; |
| 830 | + } |
| 831 | + |
| 832 | + /** |
| 833 | + * Reconnects the target of a transition edge. |
| 834 | + * |
| 835 | + * @param transition |
| 836 | + * the transition to reconnect |
| 837 | + * @param newTarget |
| 838 | + * the new target |
| 839 | + * @return the transition |
| 840 | + */ |
| 841 | + public TransitionUsage reconnectTargetTransitionEdge(TransitionUsage transition, ActionUsage newTarget) { |
| 842 | + if (newTarget instanceof TransitionUsage || !this.isValidTransitionTarget(transition.getSource(), newTarget)) { |
| 843 | + this.feedbackMessageService.addFeedbackMessage(new Message("Invalid new target for transition", MessageLevel.WARNING)); |
| 844 | + return transition; |
| 845 | + } |
| 846 | + Succession succession = transition.getSuccession(); |
| 847 | + List<EndFeatureMembership> successionFeatureMemberships = succession.getFeatureMembership().stream() |
| 848 | + .filter(EndFeatureMembership.class::isInstance) |
| 849 | + .map(EndFeatureMembership.class::cast) |
| 850 | + .toList(); |
| 851 | + if (successionFeatureMemberships.size() > 1) { |
| 852 | + successionFeatureMemberships.get(1).getOwnedRelatedElement().stream() |
| 853 | + .findFirst() |
| 854 | + .ifPresent(feature -> feature.getOwnedRelationship().stream() |
| 855 | + .filter(ReferenceSubsetting.class::isInstance) |
| 856 | + .map(ReferenceSubsetting.class::cast) |
| 857 | + .findFirst() |
| 858 | + .ifPresent(referenceSubsetting -> referenceSubsetting.setReferencedFeature(newTarget))); |
| 859 | + } |
| 860 | + return transition; |
| 861 | + } |
| 862 | + |
| 863 | + /** |
| 864 | + * Reconnects the source of an include use case edge. |
| 865 | + * |
| 866 | + * @param includeUseCaseUsage |
| 867 | + * the include use case edge |
| 868 | + * @param newSource |
| 869 | + * the new source |
| 870 | + * @return the include use case edge |
| 871 | + */ |
| 872 | + public IncludeUseCaseUsage reconnectSourceIncludeUseCaseUsage(IncludeUseCaseUsage includeUseCaseUsage, UseCaseUsage newSource) { |
| 873 | + OwningMembership owningMembership = includeUseCaseUsage.getOwningMembership(); |
| 874 | + newSource.getOwnedRelationship().add(owningMembership); |
| 875 | + return includeUseCaseUsage; |
| 876 | + } |
| 877 | + |
| 878 | + /** |
| 879 | + * Reconnects the target of an include use case edge. |
| 880 | + * |
| 881 | + * @param includeUseCaseUsage |
| 882 | + * the include use case edge |
| 883 | + * @param newTarget |
| 884 | + * the new target |
| 885 | + * @return the include use case edge |
| 886 | + */ |
| 887 | + public IncludeUseCaseUsage reconnectTargetIncludeUseCaseUsage(IncludeUseCaseUsage includeUseCaseUsage, UseCaseUsage newTarget) { |
| 888 | + ReferenceSubsetting referenceSubsetting = includeUseCaseUsage.getOwnedReferenceSubsetting(); |
| 889 | + if (referenceSubsetting != null) { |
| 890 | + referenceSubsetting.setReferencedFeature(newTarget); |
| 891 | + } |
| 892 | + return includeUseCaseUsage; |
| 893 | + } |
| 894 | + |
704 | 895 | /** |
705 | 896 | * Creates a {@link BindingConnectorAsUsage}. |
706 | 897 | * |
@@ -927,4 +1118,45 @@ private Optional<Namespace> getConnectorContainer(Node sourceNode, Node targetNo |
927 | 1118 | } |
928 | 1119 | return namespaceOwner; |
929 | 1120 | } |
| 1121 | + |
| 1122 | + private List<Feature> getAllocateEdgeFeatures(AllocationUsage allocationUsage) { |
| 1123 | + return allocationUsage.getOwnedFeatureMembership().stream() |
| 1124 | + .filter(EndFeatureMembership.class::isInstance) |
| 1125 | + .map(EndFeatureMembership.class::cast) |
| 1126 | + .flatMap(endFeatureMembership -> endFeatureMembership.getOwnedRelatedElement().stream()) |
| 1127 | + .filter(Feature.class::isInstance) |
| 1128 | + .map(Feature.class::cast) |
| 1129 | + .toList(); |
| 1130 | + } |
| 1131 | + |
| 1132 | + private void setConnectorEndFeature(Feature sourceEnd, Element newTargetFeature) { |
| 1133 | + if (sourceEnd instanceof ReferenceUsage referenceUsage) { |
| 1134 | + ReferenceSubsetting referenceSubsetting = sourceEnd.getOwnedReferenceSubsetting(); |
| 1135 | + if (referenceSubsetting == null || referenceSubsetting.isIsImplied()) { |
| 1136 | + referenceSubsetting = SysmlFactory.eINSTANCE.createReferenceSubsetting(); |
| 1137 | + referenceSubsetting.setSubsettingFeature(referenceUsage); |
| 1138 | + } |
| 1139 | + this.getAction(newTargetFeature).ifPresent(referenceSubsetting::setReferencedFeature); |
| 1140 | + } |
| 1141 | + } |
| 1142 | + |
| 1143 | + private Optional<ActionUsage> getAction(Element element) { |
| 1144 | + Optional<ActionUsage> result = Optional.empty(); |
| 1145 | + if (element instanceof Membership membership) { |
| 1146 | + if (membership.getMemberElement() instanceof ActionUsage actionUsage) { |
| 1147 | + result = Optional.of(actionUsage); |
| 1148 | + } |
| 1149 | + } else if (element instanceof ActionUsage actionUsage) { |
| 1150 | + result = Optional.of(actionUsage); |
| 1151 | + } |
| 1152 | + return result; |
| 1153 | + } |
| 1154 | + |
| 1155 | + private boolean isValidTransitionTarget(Element source, Element target) { |
| 1156 | + boolean sameParent = false; |
| 1157 | + if (source instanceof ActionUsage sourceAction && target instanceof ActionUsage targetAction) { |
| 1158 | + sameParent = sourceAction.getOwner() == targetAction.getOwner(); |
| 1159 | + } |
| 1160 | + return sameParent && !this.utilService.isParallelState(source.getOwner()); |
| 1161 | + } |
930 | 1162 | } |
0 commit comments