diff options
| author | Laurent Redor | 2021-02-17 11:13:31 +0000 |
|---|---|---|
| committer | Laurent Redor | 2021-02-18 14:17:06 +0000 |
| commit | 15457c81b870b93bb0a41d85a8b9a3ff186c012d (patch) | |
| tree | 0d4decf2127dada3126e5d50c0dd0974eba41b18 | |
| parent | 3d82623bd6613c7825bf0c4d1d15226db2a15ff1 (diff) | |
| download | org.eclipse.sirius-15457c81b870b93bb0a41d85a8b9a3ff186c012d.tar.gz org.eclipse.sirius-15457c81b870b93bb0a41d85a8b9a3ff186c012d.tar.xz org.eclipse.sirius-15457c81b870b93bb0a41d85a8b9a3ff186c012d.zip | |
[571249] Existing Note/Text in target diagram are now considered
Before this commit, a new Note/Text is systematically created, even if a
Node/Text already exist in the target diagram (same label and same
NoteAttachment target).
Bug: 571249
Change-Id: I9aed171142c20055508fe9b9a3d81b4eb16ae6a5
Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
4 files changed, 189 insertions, 35 deletions
diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/api/format/MappingBasedSiriusFormatManagerFactory.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/api/format/MappingBasedSiriusFormatManagerFactory.java index d9c49873f7..98f0ece7e9 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/api/format/MappingBasedSiriusFormatManagerFactory.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/api/format/MappingBasedSiriusFormatManagerFactory.java @@ -16,6 +16,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -30,12 +31,12 @@ import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint; -import org.eclipse.gmf.runtime.diagram.core.util.ViewType; import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart; import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditDomain; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.gmf.runtime.notation.Edge; import org.eclipse.gmf.runtime.notation.Node; +import org.eclipse.gmf.runtime.notation.Shape; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.sirius.business.api.dialect.DialectManager; import org.eclipse.sirius.business.api.session.CustomDataConstants; @@ -459,7 +460,7 @@ public class MappingBasedSiriusFormatManagerFactory { DiagramPlugin.getDefault() .logError(MessageFormat.format(Messages.MappingBasedSiriusFormatManagerFactory_ImpossibleToSuitableDescription, descs.stream().map(desc -> desc.getName()).collect(Collectors.joining(", ")), sourceDescName, //$NON-NLS-1$ - SiriusEditPlugin.getPlugin().getUiCallback().getSessionNameToDisplayWhileSaving(targetSession))); + SiriusEditPlugin.getPlugin().getUiCallback().getSessionNameToDisplayWhileSaving(targetSession))); } return null; } @@ -564,43 +565,68 @@ public class MappingBasedSiriusFormatManagerFactory { final Diagram sourceGMFDiagram = MappingBasedSiriusFormatManagerFactoryHelper.getGMFDiagram(sourceDiagram); final Diagram targetGMFDiagram = MappingBasedSiriusFormatManagerFactoryHelper.getGMFDiagram(targetDiagram); - // Get all notes - Collection<Node> sourceNotes = GMFNotationHelper.getNotes(sourceGMFDiagram); - sourceNotes.addAll(GMFNotationHelper.getTextNotes(sourceGMFDiagram)); - // Initialize and clear sourceToTargetNoteMap if (sourceToTargetNoteMap == null) { sourceToTargetNoteMap = new HashMap<Node, Node>(); } sourceToTargetNoteMap.clear(); + // Get all notes + Collection<Node> sourceNotes = GMFNotationHelper.getNotes(sourceGMFDiagram); + Collection<Node> targetNotes = GMFNotationHelper.getNotes(targetGMFDiagram); + // Duplicate notes into target diagram and apply source note style sourceNotes.forEach(sourceNote -> { - Node targetNote = null; - if (ViewType.NOTE.equals(sourceNote.getType())) { - // Handle notes - targetNote = GMFNotationHelper.createNote(targetGMFDiagram, GMFNotationHelper.getNoteDescription(sourceNote)); - } else { - // Handle text notes - View targetParentNode = null; - if (sourceNote.eContainer().equals(sourceGMFDiagram)) { - targetParentNode = targetGMFDiagram; + if (sourceNote instanceof Shape && ((Shape) sourceNote).getDescription() != null) { + String labelOfNote = ((Shape) sourceNote).getDescription(); + Optional<Node> existingTargetNote = search(targetNotes, (Shape) sourceNote, labelOfNote); + Node targetNote; + if (existingTargetNote.isPresent()) { + targetNote = existingTargetNote.get(); } else { - targetParentNode = MappingBasedSiriusFormatManagerFactoryHelper.getTargetDiagramTextNoteContainer(sourceNote, diagramContentDuplicationSwitch); + targetNote = GMFNotationHelper.createNote(targetGMFDiagram, GMFNotationHelper.getNoteDescription(sourceNote)); } - if (targetParentNode != null) { - targetNote = GMFNotationHelper.createTextNote(targetParentNode, GMFNotationHelper.getNoteDescription(sourceNote)); - } else { - DiagramPlugin.getDefault().logInfo(MessageFormat.format(Messages.MappingBasedSiriusFormatManagerFactory_ImpossibleToFindTargetTextNoteContainer, sourceNote)); - return; + targetNote.setLayoutConstraint(EcoreUtil.copy(sourceNote.getLayoutConstraint())); + if (sourceNote.isSetElement()) { + targetNote.setElement(sourceNote.getElement()); } + formatDataManager.copyGMFStyle(sourceNote, targetNote); + sourceToTargetNoteMap.put(sourceNote, targetNote); + } + }); + + // Get all texts + Collection<Node> sourceTexts = GMFNotationHelper.getTextNotes(sourceGMFDiagram); + Collection<Node> targetTexts = GMFNotationHelper.getTextNotes(targetGMFDiagram); + + // Duplicate texts into target diagram and apply source text style + sourceTexts.forEach(sourceText -> { + View targetParentNode = null; + if (sourceText.eContainer().equals(sourceGMFDiagram)) { + targetParentNode = targetGMFDiagram; + } else { + targetParentNode = MappingBasedSiriusFormatManagerFactoryHelper.getTargetDiagramTextNoteContainer(sourceText, diagramContentDuplicationSwitch); } - targetNote.setLayoutConstraint(EcoreUtil.copy(sourceNote.getLayoutConstraint())); - if (sourceNote.isSetElement()) { - targetNote.setElement(sourceNote.getElement()); + if (targetParentNode == null) { + DiagramPlugin.getDefault().logInfo(MessageFormat.format(Messages.MappingBasedSiriusFormatManagerFactory_ImpossibleToFindTargetTextNoteContainer, sourceText)); + return; + } + if (sourceText instanceof Shape && ((Shape) sourceText).getDescription() != null) { + String labelOfText = ((Shape) sourceText).getDescription(); + Optional<Node> existingTargetText = search(targetTexts, (Shape) sourceText, labelOfText); + Node targetText; + if (existingTargetText.isPresent()) { + targetText = existingTargetText.get(); + } else { + targetText = GMFNotationHelper.createTextNote(targetParentNode, labelOfText); + } + targetText.setLayoutConstraint(EcoreUtil.copy(sourceText.getLayoutConstraint())); + if (sourceText.isSetElement()) { + targetText.setElement(sourceText.getElement()); + } + formatDataManager.copyGMFStyle(sourceText, targetText); + sourceToTargetNoteMap.put(sourceText, targetText); } - formatDataManager.copyGMFStyle(sourceNote, targetNote); - sourceToTargetNoteMap.put(sourceNote, targetNote); }); // Duplicate note attachments if possible @@ -613,9 +639,96 @@ public class MappingBasedSiriusFormatManagerFactory { noteIsSource = false; } MappingBasedSiriusFormatManagerFactoryHelper.duplicateNoteAttachment(attach, sourceToTargetNoteMap.get(nodeAttachment), targetSession, noteIsSource, diagramContentDuplicationSwitch, - sourceToTargetNoteMap, formatDataManager); + sourceToTargetNoteMap, formatDataManager, targetGMFDiagram); }); + } + /** + * Search in <code>nodes</code> a Node (Text or Note) with the same label (<code>searchedLabel</code>) and the same + * attachments than the <code>sourceNode</code>. + * + * @param nodes + * List in which to search + * @param sourceNode + * The node to compare attachments with. + * @param searchedLabel + * The searched label + * @return An optional with the corresponding node if any. + */ + private Optional<Node> search(Collection<Node> nodes, Shape sourceNode, String searchedLabel) { + List<Node> matchingNodes = new ArrayList<Node>(); + // Get the nodes with same description (same label) as the <code>searchedLabel</code> + for (Node node : nodes) { + if (node instanceof Shape) { + if (searchedLabel.equals(((Shape) node).getDescription())) { + matchingNodes.add(node); + } + } + } + // Remove elements that have not the same attachment on source side + matchingNodes = removeNotSameAttachment(sourceNode, matchingNodes, true); + // Remove elements that have not the same attachment on target side + matchingNodes = removeNotSameAttachment(sourceNode, matchingNodes, false); + // Only the first is considered. At this step, if several nodes remain, we are in a case not handled by the + // Copy/Paste format API. + return matchingNodes.stream().findFirst(); + } + + /** + * Search in <code>nodesCandidates</code> which candidate has the same source/target attachments. + * + * @param nodeToCompareWith + * the node to use as comparator + * @param nodesCandidates + * list of nodes + * @param testSource + * true if the attachment on source side must bu tested, false if the attachment on target side must be + * tested. + * @return a sub list of nodesCandidates + */ + protected List<Node> removeNotSameAttachment(Shape nodeToCompareWith, List<Node> nodesCandidates, boolean testSource) { + List<Node> matchingNodes; + boolean hasAttachment = testSource ? nodeToCompareWith.getSourceEdges().size() != 0 : nodeToCompareWith.getTargetEdges().size() != 0; + if (!hasAttachment) { + // Select only nodes without source/target attachment + if (testSource) { + matchingNodes = nodesCandidates.stream().filter(node -> node.getSourceEdges().size() == 0).collect(Collectors.toList()); + } else { + matchingNodes = nodesCandidates.stream().filter(node -> node.getTargetEdges().size() == 0).collect(Collectors.toList()); + } + } else { + // Select nodes that have the same source/target attachments + matchingNodes = new ArrayList<Node>(nodesCandidates); + for (Iterator<Node> iterator = matchingNodes.iterator(); iterator.hasNext(); /* */) { + Node node = iterator.next(); + boolean sameAttachments = true; + + for (Iterator<Edge> edgesIterators = testSource ? ((List<Edge>) nodeToCompareWith.getSourceEdges()).iterator() + : ((List<Edge>) nodeToCompareWith.getTargetEdges()).iterator(); edgesIterators.hasNext(); /* */ ) { + Edge e = edgesIterators.next(); + // Get the target DDiagramElement corresponding to the copy of the other extremity of the + // NoteAttachment. + EObject otherExtremityElement = testSource ? e.getTarget().getElement() : e.getSource().getElement(); + DDiagramElement targetDiagramElement = diagramContentDuplicationSwitch.getSourceDDiagramElementToTargetDDiagramElementMap().get(otherExtremityElement); + if (targetDiagramElement != null && targetDiagramElement.eResource() != null) { + if (testSource) { + sameAttachments = sameAttachments && node.getSourceEdges().stream().anyMatch(edge -> ((Edge) edge).getTarget().getElement().equals(targetDiagramElement)); + } else { + sameAttachments = sameAttachments && node.getTargetEdges().stream().anyMatch(edge -> ((Edge) edge).getSource().getElement().equals(targetDiagramElement)); + } + } else { + // Here, either the target of the note attachment is not present in the target diagram or + // the source/target semantic has not been added to the semantic map while source element + // being represented by a synchronized mapping. + DiagramPlugin.getDefault().logInfo(MessageFormat.format(Messages.MappingBasedSiriusFormatManagerFactory_ImpossibleToCopyNoteInNonExistingOrUnreachableTarget, e.getTarget())); + } + } + if (!sameAttachments) { + iterator.remove(); + } + } + } + return matchingNodes; } /** diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/format/semantic/diagram/util/MappingBasedSiriusFormatManagerFactoryHelper.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/format/semantic/diagram/util/MappingBasedSiriusFormatManagerFactoryHelper.java index d0ea5b201b..0fe275164a 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/format/semantic/diagram/util/MappingBasedSiriusFormatManagerFactoryHelper.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/tools/internal/format/semantic/diagram/util/MappingBasedSiriusFormatManagerFactoryHelper.java @@ -207,9 +207,13 @@ public final class MappingBasedSiriusFormatManagerFactoryHelper { * The mapping between source diagram notes nodes and target diagram notes nodes * @param formatDataManager * The format data manager to apply format + * @param targetGMFDiagram + * the GMF diagram where note attachment should be duplicated */ + // CHECKSTYLE:OFF public static void duplicateNoteAttachment(Edge edge, Node targetNote, Session targetSession, boolean targetNoteIsSource, - MappingBasedDiagramContentDuplicationSwitch diagramContentDuplicationSwitch, Map<Node, Node> sourceToTargetNoteMap, MappingBasedSiriusFormatDataManager formatDataManager) { + MappingBasedDiagramContentDuplicationSwitch diagramContentDuplicationSwitch, Map<Node, Node> sourceToTargetNoteMap, MappingBasedSiriusFormatDataManager formatDataManager, + Diagram targetGMFDiagram) { View sourceEdgeOtherBoundView = targetNoteIsSource ? edge.getTarget() : edge.getSource(); EObject sourceEdgeOtherBoundElement = sourceEdgeOtherBoundView.getElement(); View matchingTargetElement = null; @@ -229,11 +233,18 @@ public final class MappingBasedSiriusFormatManagerFactoryHelper { } } if (matchingTargetElement != null) { + Collection<Edge> targetNotesAttachments = GMFNotationHelper.getNotesAttachments(targetGMFDiagram); Edge noteAttachmentEdge = null; if (targetNoteIsSource) { - noteAttachmentEdge = ViewService.createEdge(targetNote, matchingTargetElement, ViewType.NOTEATTACHMENT, PreferencesHint.USE_DEFAULTS); + noteAttachmentEdge = searchNoteAttachment(targetNotesAttachments, targetNote, matchingTargetElement); + if (noteAttachmentEdge == null) { + noteAttachmentEdge = ViewService.createEdge(targetNote, matchingTargetElement, ViewType.NOTEATTACHMENT, PreferencesHint.USE_DEFAULTS); + } } else { - noteAttachmentEdge = ViewService.createEdge(matchingTargetElement, targetNote, ViewType.NOTEATTACHMENT, PreferencesHint.USE_DEFAULTS); + noteAttachmentEdge = searchNoteAttachment(targetNotesAttachments, matchingTargetElement, targetNote); + if (noteAttachmentEdge == null) { + noteAttachmentEdge = ViewService.createEdge(matchingTargetElement, targetNote, ViewType.NOTEATTACHMENT, PreferencesHint.USE_DEFAULTS); + } } copyEdgeFormatAndStyle(edge, noteAttachmentEdge, formatDataManager); @@ -244,6 +255,27 @@ public final class MappingBasedSiriusFormatManagerFactoryHelper { DiagramPlugin.getDefault().logInfo(MessageFormat.format(Messages.MappingBasedSiriusFormatManagerFactory_ImpossibleToResolveOtherBoundTargetNote, sourceEdgeOtherBoundView)); } } + // CHECKSTYLE:ON + + /** + * Search a corresponding note attachment in the list <code>targetNotesAttachments</code>. + * + * @param targetNotesAttachments + * List of note attachments in which to search. + * @param sourceView + * the source view of the searched note attachment + * @param targetView + * the target view of the searched note attachment + * @return the found note attachment or null if any + */ + private static Edge searchNoteAttachment(Collection<Edge> targetNotesAttachments, View sourceView, View targetView) { + for (Edge edge : targetNotesAttachments) { + if (sourceView != null && sourceView.equals(edge.getSource()) && targetView != null && targetView.equals(edge.getTarget())) { + return edge; + } + } + return null; + } /** * A simple duplication for the format and the style of {@code sourceEdge} to {@code targetEdge} diff --git a/plugins/org.eclipse.sirius.doc/doc/developer/copy_paste_format_new_semantic.html b/plugins/org.eclipse.sirius.doc/doc/developer/copy_paste_format_new_semantic.html index 3dc50963cc..664d3b433a 100644 --- a/plugins/org.eclipse.sirius.doc/doc/developer/copy_paste_format_new_semantic.html +++ b/plugins/org.eclipse.sirius.doc/doc/developer/copy_paste_format_new_semantic.html @@ -45,6 +45,7 @@ </pre> <p>This first method will perform the copy-paste format from a source diagram to an existing target diagram. The target elements on which the layout and style will be applied are retrieved by using the source-target correspondence map. </p> <p>Note that if an element in the target diagram has no corresponding source element in the source diagram, this element will keep its current style and layout.</p> + <p>Elements not visible in the source diagram (hidden by user, because of a deactivated layer or because of a filter) are not considered by the copy-paste.</p> <h3 id="Applythecopypastefromasourcediagramtoanewtargetdiagram">Apply the copy-paste from a source diagram to a new target diagram</h3> <pre> /** * Apply format on a new {@link DDiagram} for name {@code targetDiagramName} based on the {@code sourceDiagram}. @@ -78,12 +79,14 @@ </pre> <p>This method will create a new diagram, based on the correspondence map. The new diagram will be created only if the same source diagram description can be applied on the new semantic target. Once the new target diagram is created, the format from the source diagram is applied in the same way than the first method.</p> <p>Only diagram elements for which an entry exists in the correspondence map will be created. If the new target diagram description has synchronized mapping (that means graphical elements are automatically created according to the mappings defined in the VSM), new graphical elements might appear. If those new graphical elements semantic targets have no entry in the correspondence map, they will not be formatted and will keep their default style and layout.</p> + <p>Elements not visible in the source diagram (hidden by user, because of a deactivated layer or because of a filter) are not considered by the copy-paste.</p> <h3 id="FiltersandLayers">Filters and Layers</h3> <p>Filters and layers activated in the source diagram are automatically activated in the target diagram.</p> - <h3 id="Notes">Notes</h3> - <p>If this option is activated ( - <code>copyNotes</code> parameter), existing notes in the source diagram are copied in the target diagram. If a note attachment exists in the source diagram, this one is also created in the target diagram, if the graphical target exists. + <h3 id="NotesandTexts">Notes and Texts</h3> + <p>If the corresponding option is activated ( + <code>copyNotes</code> parameter), existing notes and texts in the source diagram are copied in the target diagram. If a note attachment exists in the source diagram, this one is also created in the target diagram, if the graphical target exists. </p> + <p>The label of Note/Text and target of attachment are used to retrieve a potential existing Note/Text in the target diagram. In other words, if the label is different or if the target of attachment is different, a new Node/Text will be created. </p> <h2 id="Sequencediagrams">Sequence diagrams</h2> <p>The sequence diagram layout is linked to the semantic model: the vertical or horizontal graphical ordering perfectly match the semantic ordering. <br/>Because of this constraint, this feature can only be applied between sequence diagrams with a perfect match between their semantic models. That means the target semantic model, on which the existing target sequence diagram or the new one are based on, has to be the exact copy of the source semantic model. All target semantic elements have to be present in the corresponding map and all source semantic elements have to be present in the map. diff --git a/plugins/org.eclipse.sirius.doc/doc/developer/copy_paste_format_new_semantic.textile b/plugins/org.eclipse.sirius.doc/doc/developer/copy_paste_format_new_semantic.textile index d12785ecdc..a621948c1a 100644 --- a/plugins/org.eclipse.sirius.doc/doc/developer/copy_paste_format_new_semantic.textile +++ b/plugins/org.eclipse.sirius.doc/doc/developer/copy_paste_format_new_semantic.textile @@ -47,6 +47,8 @@ p. This first method will perform the copy-paste format from a source diagram to p. Note that if an element in the target diagram has no corresponding source element in the source diagram, this element will keep its current style and layout. +p. Elements not visible in the source diagram (hidden by user, because of a deactivated layer or because of a filter) are not considered by the copy-paste. + h3. Apply the copy-paste from a source diagram to a new target diagram pre.. @@ -83,13 +85,17 @@ p. This method will create a new diagram, based on the correspondence map. The n p. Only diagram elements for which an entry exists in the correspondence map will be created. If the new target diagram description has synchronized mapping (that means graphical elements are automatically created according to the mappings defined in the VSM), new graphical elements might appear. If those new graphical elements semantic targets have no entry in the correspondence map, they will not be formatted and will keep their default style and layout. +p. Elements not visible in the source diagram (hidden by user, because of a deactivated layer or because of a filter) are not considered by the copy-paste. + h3. Filters and Layers Filters and layers activated in the source diagram are automatically activated in the target diagram. -h3. Notes +h3. Notes and Texts + +If the corresponding option is activated (@copyNotes@ parameter), existing notes and texts in the source diagram are copied in the target diagram. If a note attachment exists in the source diagram, this one is also created in the target diagram, if the graphical target exists. -If this option is activated (@copyNotes@ parameter), existing notes in the source diagram are copied in the target diagram. If a note attachment exists in the source diagram, this one is also created in the target diagram, if the graphical target exists. +The label of Note/Text and target of attachment are used to retrieve a potential existing Note/Text in the target diagram. In other words, if the label is different or if the target of attachment is different, a new Node/Text will be created. h2. Sequence diagrams |
