diff options
| author | Laurent Redor | 2015-01-16 12:24:07 +0000 |
|---|---|---|
| committer | Laurent Redor | 2015-01-22 17:37:22 +0000 |
| commit | 9211b37ab242747dd461fdff9783118c14352c3c (patch) | |
| tree | 0498b549b91ca1d83aaf6d70d749213b11a156d7 | |
| parent | a1ff9f6a16f34781b89b0263d441dcf5cd0527fe (diff) | |
| download | org.eclipse.sirius-9211b37ab242747dd461fdff9783118c14352c3c.tar.gz org.eclipse.sirius-9211b37ab242747dd461fdff9783118c14352c3c.tar.xz org.eclipse.sirius-9211b37ab242747dd461fdff9783118c14352c3c.zip | |
[457678] Add cache in SequenceDiagram
Several caches have been added in SequenceDiagram to add cache
capability for RefreshLayoutCommand: this avoids to compute
ordered lists of elements several times. There is 2 levels of cache
** one for the list itself (not changed during one layout)
** another for the sorted list (can change during one layout)
Some methods now returns a boolean to indicate if they made changes
(RefreshGraphicalOrderingOperation,
SynchronizeGraphicalOrderingOperation, and
RefreshSemanticOrderingsOperation are now
AbstractModelChangeOperation<Boolean> instead of
AbstractModelChangeOperation<Void>).
Bug: 457678
Change-Id: I41950a134c26e97c8f07b3bf88067c796761897c
Signed-off-by: Laurent Redor <laurent.redor@obeo.fr>
7 files changed, 530 insertions, 149 deletions
diff --git a/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/layout/SequenceLayoutProvider.java b/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/layout/SequenceLayoutProvider.java index 940b3583ff..3f89a1ba28 100644 --- a/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/layout/SequenceLayoutProvider.java +++ b/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/layout/SequenceLayoutProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 THALES GLOBAL SERVICES. + * Copyright (c) 2009, 2015 THALES GLOBAL SERVICES. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -64,7 +64,7 @@ public class SequenceLayoutProvider extends AbstractLayoutProvider { TransactionalEditingDomain transactionalEditingDomain = sdep.getEditingDomain(); SequenceDiagram sequenceDiagram = sdep.getSequenceDiagram(); SequenceDDiagram sequenceDDiagram = (SequenceDDiagram) sdep.resolveSemanticElement(); - Collection<AbstractModelChangeOperation<Void>> operations = new ArrayList<AbstractModelChangeOperation<Void>>(); + Collection<AbstractModelChangeOperation<Boolean>> operations = new ArrayList<AbstractModelChangeOperation<Boolean>>(); operations.add(new RefreshGraphicalOrderingOperation(sequenceDiagram)); operations.add(new RefreshSemanticOrderingsOperation(sequenceDDiagram)); diff --git a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/elements/SequenceDiagram.java b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/elements/SequenceDiagram.java index b2537ce829..4e9d85d0b6 100644 --- a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/elements/SequenceDiagram.java +++ b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/elements/SequenceDiagram.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2012 THALES GLOBAL SERVICES. + * Copyright (c) 2010, 2015 THALES GLOBAL SERVICES. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,6 +13,7 @@ package org.eclipse.sirius.diagram.sequence.business.internal.elements; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -85,6 +86,59 @@ public class SequenceDiagram extends AbstractSequenceElement { } /** + * Indicate if this class should use cache or not. Use + * {@link #useCache(boolean))} to enable/disable this mode and { + * {@link #clearAllCaches()} to clear caches. + */ + private boolean useCache; + + private List<AbstractNodeEvent> allAbstractNodeEventsCache; + + private List<CombinedFragment> allCombinedFragmentsCache; + + private Set<EndOfLife> allEndOfLifesCache; + + private List<Execution> allExecutionsCache; + + private List<AbstractFrame> allFramesCache; + + private Collection<InstanceRole> allInstanceRolesCache; + + private List<InteractionUse> allInteractionUsesCache; + + private List<Lifeline> allLifelinesCache; + + private Collection<LostMessageEnd> allLostMessageEndCache; + + private List<Message> allMessagesCache; + + private Collection<ObservationPoint> allObservationPointsCache; + + private List<Operand> allOperandsCache; + + private List<State> allStatesCache; + + private LinkedHashSet<AbstractNodeEvent> allOrderedAbstractNodeEventsCache; + + private LinkedHashSet<CombinedFragment> allOrderedCombinedFragmentsCache; + + private Set<ISequenceEvent> allOrderedDelimitedSequenceEventsCache; + + private LinkedHashSet<Execution> allOrderedExecutionsCache; + + private LinkedHashSet<AbstractFrame> allOrderedFramesCache; + + private LinkedHashSet<InteractionUse> allOrderedInteractionUsesCache; + + private List<Lifeline> allOrderedLifelinesCache; + + private LinkedHashSet<Message> allOrderedMessagesCache; + + private LinkedHashSet<Operand> allOrderedOperandsCache; + + private LinkedHashSet<State> allOrderedStatesCache; + + /** * Constructor. * * @param diagram @@ -170,16 +224,27 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return . */ public Collection<InstanceRole> getAllInstanceRoles() { - Collection<InstanceRole> result = Lists.newArrayList(); - for (View child : Iterables.filter(getNotationView().getChildren(), View.class)) { - if (InstanceRole.notationPredicate().apply(child)) { - Option<InstanceRole> instanceRole = ISequenceElementAccessor.getInstanceRole(child); - if (instanceRole.some()) { - result.add(instanceRole.get()); + Collection<InstanceRole> allInstanceRoles = null; + if (useCache) { + // Initialize from cache + allInstanceRoles = allInstanceRolesCache; + } + if (allInstanceRoles == null) { + allInstanceRoles = Lists.newArrayList(); + for (View child : Iterables.filter(getNotationView().getChildren(), View.class)) { + if (InstanceRole.notationPredicate().apply(child)) { + Option<InstanceRole> instanceRole = ISequenceElementAccessor.getInstanceRole(child); + if (instanceRole.some()) { + allInstanceRoles.add(instanceRole.get()); + } } } + if (useCache) { + // Store the result + allInstanceRolesCache = allInstanceRoles; + } } - return result; + return allInstanceRoles; } /** @@ -188,15 +253,32 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return . */ public List<Lifeline> getAllLifelines() { - Collection<InstanceRole> allInstanceRoles = getAllInstanceRoles(); - Function<ISequenceNode, Lifeline> lifelineFunction = new Function<ISequenceNode, Lifeline>() { - public Lifeline apply(ISequenceNode from) { - return from.getLifeline().get(); + List<Lifeline> allLifelines = null; + if (useCache) { + // Initialize from cache + if (allLifelinesCache != null) { + allLifelines = Lists.newArrayList(allLifelinesCache); } - }; - List<Lifeline> result = Lists.newArrayList(Iterables.transform(allInstanceRoles, lifelineFunction)); - Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); - return result; + } + if (allOrderedLifelinesCache == null) { + if (allLifelines == null) { + allLifelines = Lists.newArrayList(); + Collection<InstanceRole> allInstanceRoles = getAllInstanceRoles(); + Function<ISequenceNode, Lifeline> lifelineFunction = new Function<ISequenceNode, Lifeline>() { + public Lifeline apply(ISequenceNode from) { + return from.getLifeline().get(); + } + }; + allLifelines = Lists.newArrayList(Iterables.transform(allInstanceRoles, lifelineFunction)); + if (useCache) { + // Store the result + allLifelinesCache = allLifelines; + } + } + Collections.sort(allLifelines, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); + allOrderedLifelinesCache = Lists.newArrayList(allLifelines); + } + return allOrderedLifelinesCache; } /** @@ -208,16 +290,27 @@ public class SequenceDiagram extends AbstractSequenceElement { * not a sequence diagram. */ public Collection<ObservationPoint> getAllObservationPoints() { - Collection<ObservationPoint> result = Lists.newArrayList(); - for (View child : Iterables.filter(getNotationView().getChildren(), View.class)) { - if (ObservationPoint.notationPredicate().apply(child)) { - Option<ObservationPoint> obsPoint = ISequenceElementAccessor.getObservationPoint(child); - if (obsPoint.some()) { - result.add(obsPoint.get()); + Collection<ObservationPoint> allObservationPoints = null; + if (useCache) { + // Initialize from cache + allObservationPoints = allObservationPointsCache; + } + if (allObservationPoints == null) { + allObservationPoints = Lists.newArrayList(); + for (View child : Iterables.filter(getNotationView().getChildren(), View.class)) { + if (ObservationPoint.notationPredicate().apply(child)) { + Option<ObservationPoint> obsPoint = ISequenceElementAccessor.getObservationPoint(child); + if (obsPoint.some()) { + allObservationPoints.add(obsPoint.get()); + } } } + if (useCache) { + // Store the result + allObservationPointsCache = allObservationPoints; + } } - return result; + return allObservationPoints; } /** @@ -229,16 +322,27 @@ public class SequenceDiagram extends AbstractSequenceElement { * a sequence diagram. */ public Collection<LostMessageEnd> getAllLostMessageEnds() { - Collection<LostMessageEnd> result = Lists.newArrayList(); - for (View child : Iterables.filter(getNotationView().getChildren(), View.class)) { - if (LostMessageEnd.notationPredicate().apply(child)) { - Option<LostMessageEnd> lostMessageEnd = ISequenceElementAccessor.getLostMessageEnd(child); - if (lostMessageEnd.some()) { - result.add(lostMessageEnd.get()); + Collection<LostMessageEnd> allLostMessageEnd = null; + if (useCache) { + // Initialize from cache + allLostMessageEnd = allLostMessageEndCache; + } + if (allLostMessageEnd == null) { + allLostMessageEnd = Lists.newArrayList(); + for (View child : Iterables.filter(getNotationView().getChildren(), View.class)) { + if (LostMessageEnd.notationPredicate().apply(child)) { + Option<LostMessageEnd> lostMessageEnd = ISequenceElementAccessor.getLostMessageEnd(child); + if (lostMessageEnd.some()) { + allLostMessageEnd.add(lostMessageEnd.get()); + } } } + if (useCache) { + // Store the result + allLostMessageEndCache = allLostMessageEnd; + } } - return result; + return allLostMessageEnd; } /** @@ -250,14 +354,36 @@ public class SequenceDiagram extends AbstractSequenceElement { * diagram. */ public Set<Message> getAllMessages() { - List<Message> result = Lists.newArrayList(); - for (Edge edge : Iterables.filter(Iterables.filter(getNotationDiagram().getEdges(), Edge.class), Message.notationPredicate())) { - Option<Message> message = ISequenceElementAccessor.getMessage(edge); - assert message.some() : INTERNAL_ERROR; - result.add(message.get()); + List<Message> allMessages = null; + LinkedHashSet<Message> allOrderedMessages = null; + if (useCache) { + // Initialize from cache + if (allMessagesCache != null) { + allMessages = Lists.newArrayList(allMessagesCache); + } + allOrderedMessages = allOrderedMessagesCache; } - Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); - return Sets.newLinkedHashSet(result); + if (allOrderedMessages == null) { + if (allMessages == null) { + allMessages = Lists.newArrayList(); + for (Edge edge : Iterables.filter(Iterables.filter(getNotationDiagram().getEdges(), Edge.class), Message.notationPredicate())) { + Option<Message> message = ISequenceElementAccessor.getMessage(edge); + assert message.some() : INTERNAL_ERROR; + allMessages.add(message.get()); + } + if (useCache) { + // Store the result + allMessagesCache = allMessages; + } + } + Collections.sort(allMessages, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); + allOrderedMessages = Sets.newLinkedHashSet(allMessages); + if (useCache) { + // Store the result + allOrderedMessagesCache = allOrderedMessages; + } + } + return allOrderedMessages; } /** @@ -266,14 +392,36 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return all AbstractNodeEvent on the given diagram. */ public Set<AbstractNodeEvent> getAllAbstractNodeEvents() { - List<AbstractNodeEvent> result = Lists.newArrayList(); - for (Node node : Iterables.filter(Iterables.filter(AllContents.of(getNotationDiagram()), Node.class), AbstractNodeEvent.notationPredicate())) { - Option<AbstractNodeEvent> exec = ISequenceElementAccessor.getAbstractNodeEvent(node); - assert exec.some() : INTERNAL_ERROR; - result.add(exec.get()); + List<AbstractNodeEvent> allAbstractNodeEvents = null; + LinkedHashSet<AbstractNodeEvent> allOrderedAbstractNodeEvents = null; + if (useCache) { + // Initialize from cache + if (allAbstractNodeEventsCache != null) { + allAbstractNodeEvents = Lists.newArrayList(allAbstractNodeEventsCache); + } + allOrderedAbstractNodeEvents = allOrderedAbstractNodeEventsCache; } - Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); - return Sets.newLinkedHashSet(result); + if (allOrderedAbstractNodeEvents == null) { + if (allAbstractNodeEvents == null) { + allAbstractNodeEvents = Lists.newArrayList(); + for (Node node : Iterables.filter(Iterables.filter(AllContents.of(getNotationDiagram()), Node.class), AbstractNodeEvent.notationPredicate())) { + Option<AbstractNodeEvent> exec = ISequenceElementAccessor.getAbstractNodeEvent(node); + assert exec.some() : INTERNAL_ERROR; + allAbstractNodeEvents.add(exec.get()); + } + if (useCache) { + // Store the result + allAbstractNodeEventsCache = allAbstractNodeEvents; + } + } + Collections.sort(allAbstractNodeEvents, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); + allOrderedAbstractNodeEvents = Sets.newLinkedHashSet(allAbstractNodeEvents); + if (useCache) { + // Store the result + allOrderedAbstractNodeEventsCache = allOrderedAbstractNodeEvents; + } + } + return allOrderedAbstractNodeEvents; } /** @@ -282,14 +430,36 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return all executions on the given diagram. */ public Set<Execution> getAllExecutions() { - List<Execution> result = Lists.newArrayList(); - for (Node node : Iterables.filter(Iterables.filter(AllContents.of(getNotationDiagram()), Node.class), Execution.notationPredicate())) { - Option<Execution> exec = ISequenceElementAccessor.getExecution(node); - assert exec.some() : INTERNAL_ERROR; - result.add(exec.get()); + List<Execution> allExecutions = null; + LinkedHashSet<Execution> allOrderedExecutions = null; + if (useCache) { + // Initialize from cache + if (allExecutionsCache != null) { + allExecutions = Lists.newArrayList(allExecutionsCache); + } + allOrderedExecutions = allOrderedExecutionsCache; } - Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); - return Sets.newLinkedHashSet(result); + if (allOrderedExecutions == null) { + if (allExecutions == null) { + allExecutions = Lists.newArrayList(); + for (Node node : Iterables.filter(Iterables.filter(AllContents.of(getNotationDiagram()), Node.class), Execution.notationPredicate())) { + Option<Execution> exec = ISequenceElementAccessor.getExecution(node); + assert exec.some() : INTERNAL_ERROR; + allExecutions.add(exec.get()); + } + if (useCache) { + // Store the result + allExecutionsCache = allExecutions; + } + } + Collections.sort(allExecutions, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); + allOrderedExecutions = Sets.newLinkedHashSet(allExecutions); + if (useCache) { + // Store the result + allOrderedExecutionsCache = allOrderedExecutions; + } + } + return allOrderedExecutions; } /** @@ -298,14 +468,36 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return all executions on the given diagram. */ public Set<State> getAllStates() { - List<State> result = Lists.newArrayList(); - for (Node node : Iterables.filter(Iterables.filter(AllContents.of(getNotationDiagram()), Node.class), State.notationPredicate())) { - Option<State> exec = ISequenceElementAccessor.getState(node); - assert exec.some() : INTERNAL_ERROR; - result.add(exec.get()); + List<State> allStates = null; + LinkedHashSet<State> allOrderedStates = null; + if (useCache) { + // Initialize from cache + if (allOperandsCache != null) { + allStates = Lists.newArrayList(allStatesCache); + } + allOrderedStates = allOrderedStatesCache; } - Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); - return Sets.newLinkedHashSet(result); + if (allOrderedStates == null) { + if (allStates == null) { + allStates = Lists.newArrayList(); + for (Node node : Iterables.filter(Iterables.filter(AllContents.of(getNotationDiagram()), Node.class), State.notationPredicate())) { + Option<State> exec = ISequenceElementAccessor.getState(node); + assert exec.some() : INTERNAL_ERROR; + allStates.add(exec.get()); + } + if (useCache) { + // Store the result + allStatesCache = allStates; + } + } + Collections.sort(allStates, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); + allOrderedStates = Sets.newLinkedHashSet(allStates); + if (useCache) { + // Store the result + allOrderedStatesCache = allOrderedStates; + } + } + return allOrderedStates; } /** @@ -314,16 +506,38 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return all frames on the given diagram. */ public Collection<AbstractFrame> getAllFrames() { - List<AbstractFrame> result = Lists.newArrayList(); - for (Node node : Iterables.filter(Iterables.filter(getNotationDiagram().getChildren(), Node.class), AbstractFrame.notationPredicate())) { - Option<ISequenceEvent> exec = ISequenceElementAccessor.getISequenceEvent(node); - assert exec.some() : INTERNAL_ERROR; - if (exec.get() instanceof AbstractFrame) { - result.add((AbstractFrame) exec.get()); + List<AbstractFrame> allFrames = null; + LinkedHashSet<AbstractFrame> allOrderedFrames = null; + if (useCache) { + // Initialize from cache + if (allExecutionsCache != null) { + allFrames = Lists.newArrayList(allFramesCache); } + allOrderedFrames = allOrderedFramesCache; } - Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); - return Sets.newLinkedHashSet(result); + if (allOrderedFrames == null) { + if (allFrames == null) { + allFrames = Lists.newArrayList(); + for (Node node : Iterables.filter(Iterables.filter(getNotationDiagram().getChildren(), Node.class), AbstractFrame.notationPredicate())) { + Option<ISequenceEvent> exec = ISequenceElementAccessor.getISequenceEvent(node); + assert exec.some() : INTERNAL_ERROR; + if (exec.get() instanceof AbstractFrame) { + allFrames.add((AbstractFrame) exec.get()); + } + } + if (useCache) { + // Store the result + allFramesCache = allFrames; + } + } + Collections.sort(allFrames, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); + allOrderedFrames = Sets.newLinkedHashSet(allFrames); + if (useCache) { + // Store the result + allOrderedFramesCache = allOrderedFrames; + } + } + return allOrderedFrames; } /** @@ -332,14 +546,36 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return all interaction uses on the given diagram. */ public Set<InteractionUse> getAllInteractionUses() { - List<InteractionUse> result = Lists.newArrayList(); - for (Node node : Iterables.filter(Iterables.filter(getNotationDiagram().getChildren(), Node.class), InteractionUse.notationPredicate())) { - Option<InteractionUse> exec = ISequenceElementAccessor.getInteractionUse(node); - assert exec.some() : INTERNAL_ERROR; - result.add(exec.get()); + List<InteractionUse> allInteractionUses = null; + LinkedHashSet<InteractionUse> allOrderedInteractionUses = null; + if (useCache) { + // Initialize from cache + if (allInteractionUsesCache != null) { + allInteractionUses = Lists.newArrayList(allInteractionUsesCache); + } + allOrderedInteractionUses = allOrderedInteractionUsesCache; } - Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); - return Sets.newLinkedHashSet(result); + if (allOrderedInteractionUses == null) { + if (allInteractionUses == null) { + allInteractionUses = Lists.newArrayList(); + for (Node node : Iterables.filter(Iterables.filter(getNotationDiagram().getChildren(), Node.class), InteractionUse.notationPredicate())) { + Option<InteractionUse> exec = ISequenceElementAccessor.getInteractionUse(node); + assert exec.some() : INTERNAL_ERROR; + allInteractionUses.add(exec.get()); + } + if (useCache) { + // Store the result + allInteractionUsesCache = allInteractionUses; + } + } + Collections.sort(allInteractionUses, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); + allOrderedInteractionUses = Sets.newLinkedHashSet(allInteractionUses); + if (useCache) { + // Store the result + allOrderedInteractionUsesCache = allOrderedInteractionUses; + } + } + return allOrderedInteractionUses; } /** @@ -348,14 +584,36 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return all combined fragments on the given diagram. */ public Set<CombinedFragment> getAllCombinedFragments() { - List<CombinedFragment> result = Lists.newArrayList(); - for (Node node : Iterables.filter(Iterables.filter(getNotationDiagram().getChildren(), Node.class), CombinedFragment.notationPredicate())) { - Option<CombinedFragment> exec = ISequenceElementAccessor.getCombinedFragment(node); - assert exec.some() : INTERNAL_ERROR; - result.add(exec.get()); + List<CombinedFragment> allCombinedFragments = null; + LinkedHashSet<CombinedFragment> allOrderedCombinedFragments = null; + if (useCache) { + // Initialize from cache + if (allCombinedFragmentsCache != null) { + allCombinedFragments = Lists.newArrayList(allCombinedFragmentsCache); + } + allOrderedCombinedFragments = allOrderedCombinedFragmentsCache; } - Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); - return Sets.newLinkedHashSet(result); + if (allOrderedCombinedFragments == null) { + if (allCombinedFragments == null) { + allCombinedFragments = Lists.newArrayList(); + for (Node node : Iterables.filter(Iterables.filter(getNotationDiagram().getChildren(), Node.class), CombinedFragment.notationPredicate())) { + Option<CombinedFragment> exec = ISequenceElementAccessor.getCombinedFragment(node); + assert exec.some() : INTERNAL_ERROR; + allCombinedFragments.add(exec.get()); + } + if (useCache) { + // Store the result + allCombinedFragmentsCache = allCombinedFragments; + } + } + Collections.sort(allCombinedFragments, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); + allOrderedCombinedFragments = Sets.newLinkedHashSet(allCombinedFragments); + if (useCache) { + // Store the result + allOrderedCombinedFragmentsCache = allOrderedCombinedFragments; + } + } + return allOrderedCombinedFragments; } /** @@ -364,14 +622,36 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return all operands on the given diagram. */ public Set<Operand> getAllOperands() { - List<Operand> result = Lists.newArrayList(); - for (Node node : Iterables.filter(Iterables.filter(AllContents.of(getNotationDiagram()), Node.class), Operand.notationPredicate())) { - Option<Operand> exec = ISequenceElementAccessor.getOperand(node); - assert exec.some() : INTERNAL_ERROR; - result.add(exec.get()); + List<Operand> allOperands = null; + LinkedHashSet<Operand> allOrderedOperands = null; + if (useCache) { + // Initialize from cache + if (allOperandsCache != null) { + allOperands = Lists.newArrayList(allOperandsCache); + } + allOrderedOperands = allOrderedOperandsCache; } - Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); - return Sets.newLinkedHashSet(result); + if (allOrderedOperands == null) { + if (allOperands == null) { + allOperands = Lists.newArrayList(); + for (Node node : Iterables.filter(Iterables.filter(AllContents.of(getNotationDiagram()), Node.class), Operand.notationPredicate())) { + Option<Operand> exec = ISequenceElementAccessor.getOperand(node); + assert exec.some() : INTERNAL_ERROR; + allOperands.add(exec.get()); + } + if (useCache) { + // Store the result + allOperandsCache = allOperands; + } + } + Collections.sort(allOperands, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); + allOrderedOperands = Sets.newLinkedHashSet(allOperands); + if (useCache) { + // Store the result + allOrderedOperandsCache = allOrderedOperands; + } + } + return allOrderedOperands; } /** @@ -380,10 +660,21 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return all endOfLifes on the given diagram. */ public Set<EndOfLife> getAllEndOfLifes() { - Set<EndOfLife> allEndOfLifes = new HashSet<EndOfLife>(); - for (Lifeline lifeline : getAllLifelines()) { - if (lifeline.getEndOfLife().some()) { - allEndOfLifes.add(lifeline.getEndOfLife().get()); + Set<EndOfLife> allEndOfLifes = null; + if (useCache) { + // Initialize from cache + allEndOfLifes = allEndOfLifesCache; + } + if (allEndOfLifes == null) { + allEndOfLifes = new HashSet<EndOfLife>(); + for (Lifeline lifeline : getAllLifelines()) { + if (lifeline.getEndOfLife().some()) { + allEndOfLifes.add(lifeline.getEndOfLife().get()); + } + } + if (useCache) { + // Store the result + allEndOfLifesCache = allEndOfLifes; } } return allEndOfLifes; @@ -396,11 +687,23 @@ public class SequenceDiagram extends AbstractSequenceElement { * @return all sequence events on the given diagram. */ public Set<ISequenceEvent> getAllOrderedDelimitedSequenceEvents() { - List<ISequenceEvent> result = Lists.newArrayList(); - Iterables.addAll(result, getAllDelimitedSequenceEvents()); - - Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); - return Sets.newLinkedHashSet(result); + Set<ISequenceEvent> allOrderedDelimitedSequenceEvents = null; + if (useCache) { + // Initialize from cache + allOrderedDelimitedSequenceEvents = allOrderedDelimitedSequenceEventsCache; + } + if (allOrderedDelimitedSequenceEvents == null) { + List<ISequenceEvent> result = Lists.newArrayList(); + Iterables.addAll(result, getAllDelimitedSequenceEvents()); + + Collections.sort(result, RangeHelper.lowerBoundOrdering().onResultOf(ISequenceEvent.VERTICAL_RANGE)); + allOrderedDelimitedSequenceEvents = Sets.newLinkedHashSet(result); + if (useCache) { + // Store the result + allOrderedDelimitedSequenceEventsCache = allOrderedDelimitedSequenceEvents; + } + } + return allOrderedDelimitedSequenceEvents; } /** @@ -459,4 +762,51 @@ public class SequenceDiagram extends AbstractSequenceElement { return new Rectangle(0, 0, 0, 0); } + /** + * Enable/Disable the cache mode. + * + * @param newStatus + * the new status for the cache mode + */ + public void useCache(boolean newStatus) { + this.useCache = newStatus; + } + + /** + * Clear all the caches. + */ + public void clearAllCaches() { + this.allAbstractNodeEventsCache = null; + this.allCombinedFragmentsCache = null; + this.allEndOfLifesCache = null; + this.allExecutionsCache = null; + this.allFramesCache = null; + this.allInstanceRolesCache = null; + this.allInteractionUsesCache = null; + this.allLifelinesCache = null; + this.allLostMessageEndCache = null; + this.allMessagesCache = null; + this.allObservationPointsCache = null; + this.allOperandsCache = null; + this.allStatesCache = null; + clearOrderedCaches(); + } + + /** + * Clear all the ordered caches. The order has been changed and it must be + * computed again. + */ + public void clearOrderedCaches() { + this.allOrderedAbstractNodeEventsCache = null; + this.allOrderedCombinedFragmentsCache = null; + this.allOrderedDelimitedSequenceEventsCache = null; + this.allOrderedExecutionsCache = null; + this.allOrderedFramesCache = null; + this.allOrderedInteractionUsesCache = null; + this.allOrderedLifelinesCache = null; + this.allOrderedMessagesCache = null; + this.allOrderedOperandsCache = null; + this.allOrderedStatesCache = null; + } + } diff --git a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/RefreshGraphicalOrderingOperation.java b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/RefreshGraphicalOrderingOperation.java index 2f69c30331..d23ec4f782 100644 --- a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/RefreshGraphicalOrderingOperation.java +++ b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/RefreshGraphicalOrderingOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 THALES GLOBAL SERVICES. + * Copyright (c) 2010, 2015 THALES GLOBAL SERVICES. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -42,7 +42,7 @@ import com.google.common.collect.Ordering; * * @author pcdavid, smonnier */ -public class RefreshGraphicalOrderingOperation extends AbstractModelChangeOperation<Void> { +public class RefreshGraphicalOrderingOperation extends AbstractModelChangeOperation<Boolean> { private final SequenceDDiagram sequenceDiagram; /** @@ -61,18 +61,19 @@ public class RefreshGraphicalOrderingOperation extends AbstractModelChangeOperat * {@inheritDoc} */ @Override - public Void execute() { + public Boolean execute() { EventEndsOrdering graphicalOrdering = sequenceDiagram.getGraphicalOrdering(); if (graphicalOrdering != null) { - refreshGlobalOrdering(graphicalOrdering); + return refreshGlobalOrdering(graphicalOrdering); } - return null; + return false; } - private void refreshGlobalOrdering(EventEndsOrdering graphicalOrdering) { + private boolean refreshGlobalOrdering(EventEndsOrdering graphicalOrdering) { if (graphicalOrdering.eContainer() instanceof SequenceDDiagram) { - refreshGlobalOrdering(graphicalOrdering, new CustomVerticalPositionFunction(sequenceDiagram)); + return refreshGlobalOrdering(graphicalOrdering, new CustomVerticalPositionFunction(sequenceDiagram)); } + return false; } /** @@ -85,7 +86,7 @@ public class RefreshGraphicalOrderingOperation extends AbstractModelChangeOperat * the function to use to obtain the vertical position of the * event ends. */ - private void refreshGlobalOrdering(EventEndsOrdering graphicalOrdering, VerticalPositionFunction verticalPosition) { + private boolean refreshGlobalOrdering(EventEndsOrdering graphicalOrdering, VerticalPositionFunction verticalPosition) { final LoadingCache<EventEnd, Integer> positions = CacheBuilder.newBuilder().build(CacheLoader.from(verticalPosition)); Predicate<EventEnd> isValidEnd = new Predicate<EventEnd>() { public boolean apply(EventEnd input) { @@ -108,7 +109,7 @@ public class RefreshGraphicalOrderingOperation extends AbstractModelChangeOperat } } })); - RefreshOrderingHelper.updateIfNeeded(graphicalOrdering.getEventEnds(), allEnds); + return RefreshOrderingHelper.updateIfNeeded(graphicalOrdering.getEventEnds(), allEnds); } /** diff --git a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/RefreshSemanticOrderingsOperation.java b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/RefreshSemanticOrderingsOperation.java index 05eddc3ce2..dfededfa2d 100644 --- a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/RefreshSemanticOrderingsOperation.java +++ b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/RefreshSemanticOrderingsOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 THALES GLOBAL SERVICES. + * Copyright (c) 2010, 2015 THALES GLOBAL SERVICES. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -51,7 +51,7 @@ import com.google.common.collect.Maps; * * @author pcdavid, smonnier */ -public class RefreshSemanticOrderingsOperation extends AbstractModelChangeOperation<Void> { +public class RefreshSemanticOrderingsOperation extends AbstractModelChangeOperation<Boolean> { /** * The name of the variable used to pass event ends to sort to * user-specified expressions. @@ -75,27 +75,28 @@ public class RefreshSemanticOrderingsOperation extends AbstractModelChangeOperat * {@inheritDoc} */ @Override - public Void execute() { + public Boolean execute() { + boolean changed = false; EventEndsOrdering semanticOrdering = sequenceDDiagram.getSemanticOrdering(); if (semanticOrdering != null) { - refreshGlobalOrdering(semanticOrdering); + changed = refreshGlobalOrdering(semanticOrdering) || changed; } InstanceRolesOrdering irSemanticOrdering = sequenceDDiagram.getInstanceRoleSemanticOrdering(); if (semanticOrdering != null) { - refreshGlobalOrdering(irSemanticOrdering); + changed = refreshGlobalOrdering(irSemanticOrdering) || changed; } - return null; + return changed; } /** * Refreshes the semantic ordering of all the events in the diagram. - * <p> - * {@inheritDoc} + * + * @return true if there is changes during this refresh, false otherwise. */ - private void refreshGlobalOrdering(EventEndsOrdering semanticOrdering) { + private boolean refreshGlobalOrdering(EventEndsOrdering semanticOrdering) { Iterable<? extends EventEnd> allEnds = RefreshOrderingHelper.getAllEventEnds(sequenceDDiagram); - RefreshOrderingHelper.updateIfNeeded(semanticOrdering.getEventEnds(), computeEventEndsOrdering(semanticOrdering, allEnds)); + return RefreshOrderingHelper.updateIfNeeded(semanticOrdering.getEventEnds(), computeEventEndsOrdering(semanticOrdering, allEnds)); } private List<EventEnd> computeEventEndsOrdering(EventEndsOrdering semanticOrdering, Iterable<? extends EventEnd> allEnds) { @@ -124,10 +125,12 @@ public class RefreshSemanticOrderingsOperation extends AbstractModelChangeOperat /** * Refreshes the semantic ordering of all the instance roles in the diagram. + * + * @return true if there is changes during this refresh, false otherwise. */ - private void refreshGlobalOrdering(InstanceRolesOrdering semanticOrdering) { + private boolean refreshGlobalOrdering(InstanceRolesOrdering semanticOrdering) { Iterable<? extends DNode> allInstanceRoles = Iterables.filter(sequenceDDiagram.getNodes(), InstanceRole.viewpointElementPredicate()); - RefreshOrderingHelper.updateIfNeeded(semanticOrdering.getSemanticInstanceRoles(), computeInstanceRolesOrdering(semanticOrdering, allInstanceRoles)); + return RefreshOrderingHelper.updateIfNeeded(semanticOrdering.getSemanticInstanceRoles(), computeInstanceRolesOrdering(semanticOrdering, allInstanceRoles)); } private List<EObject> computeInstanceRolesOrdering(InstanceRolesOrdering semanticOrdering, Iterable<? extends DNode> allInstanceRoles) { diff --git a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/SynchronizeGraphicalOrderingOperation.java b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/SynchronizeGraphicalOrderingOperation.java index 3ffe39acdb..c031147cbf 100644 --- a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/SynchronizeGraphicalOrderingOperation.java +++ b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/operation/SynchronizeGraphicalOrderingOperation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2012 THALES GLOBAL SERVICES. + * Copyright (c) 2010, 2015 THALES GLOBAL SERVICES. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -23,14 +23,14 @@ import com.google.common.base.Preconditions; * Refreshes the graphical locations of the elements in a sequence diagram to * reflect the current semantic ordering. This command assumes that the * {@link org.eclipse.sirius.diagram.sequence.ordering.GraphicalOrdering} and - * the {@link org.eclipse.sirius.diagram.sequence.ordering.SemanticOrdering} - * are up to date according to the current visual (resp. semantic) order but - * that when they do not match, the semantic ordering is the authoritative one - * and the graphical ordering should be changed to match it. + * the {@link org.eclipse.sirius.diagram.sequence.ordering.SemanticOrdering} are + * up to date according to the current visual (resp. semantic) order but that + * when they do not match, the semantic ordering is the authoritative one and + * the graphical ordering should be changed to match it. * * @author pcdavid, smonnier */ -public class SynchronizeGraphicalOrderingOperation extends AbstractModelChangeOperation<Void> { +public class SynchronizeGraphicalOrderingOperation extends AbstractModelChangeOperation<Boolean> { private final Diagram sequenceDiagram; @@ -54,7 +54,8 @@ public class SynchronizeGraphicalOrderingOperation extends AbstractModelChangeOp * {@inheritDoc} */ @Override - public Void execute() { + public Boolean execute() { + boolean result = false; Preconditions.checkNotNull(sequenceDiagram); SequenceLayout sequenceLayout = new SequenceLayout(sequenceDiagram); Option<SequenceDiagram> sd = sequenceLayout.getSequenceDiagram(); @@ -64,15 +65,25 @@ public class SynchronizeGraphicalOrderingOperation extends AbstractModelChangeOp if (diagram != null && (diagram.getGraphicalOrdering().getEventEnds().size() == diagram.getSemanticOrdering().getEventEnds().size())) { boolean verticalLayout = sequenceLayout.verticalLayout(pack); + if (verticalLayout) { + sd.get().clearOrderedCaches(); + } boolean horizontalLayout = sequenceLayout.horizontalLayout(pack); + if (horizontalLayout) { + sd.get().clearOrderedCaches(); + } boolean observationLayout = sequenceLayout.observationLayout(pack); + if (observationLayout) { + sd.get().clearOrderedCaches(); + } // Refresh flags when a layout made modifications. if (verticalLayout || horizontalLayout || observationLayout) { sequenceLayout.flagSequenceEvents(); + result = true; } } } - return null; + return result; } } diff --git a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/ordering/RefreshOrderingHelper.java b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/ordering/RefreshOrderingHelper.java index 33360f3509..99e2dbe59c 100644 --- a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/ordering/RefreshOrderingHelper.java +++ b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/ordering/RefreshOrderingHelper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 THALES GLOBAL SERVICES. + * Copyright (c) 2010, 2015 THALES GLOBAL SERVICES. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -52,7 +52,8 @@ import com.google.common.collect.Sets; */ public final class RefreshOrderingHelper { @SuppressWarnings("unchecked") - private static final Predicate<DDiagramElement> DELIMITED_EVENT_PREDICATE = Predicates.or(AbstractNodeEvent.viewpointElementPredicate(), State.viewpointElementPredicate(), InteractionUse.viewpointElementPredicate(), CombinedFragment.viewpointElementPredicate(), Operand.viewpointElementPredicate()); + private static final Predicate<DDiagramElement> DELIMITED_EVENT_PREDICATE = Predicates.or(AbstractNodeEvent.viewpointElementPredicate(), State.viewpointElementPredicate(), + InteractionUse.viewpointElementPredicate(), CombinedFragment.viewpointElementPredicate(), Operand.viewpointElementPredicate()); private RefreshOrderingHelper() { // Prevent instantiation. @@ -68,12 +69,15 @@ public final class RefreshOrderingHelper { * the old list of values. Modified in place if necessary. * @param newValue * the new list of values. Not modified. + * @return true if the content is updated, false otherwise. */ - public static <T> void updateIfNeeded(List<T> oldValue, List<T> newValue) { + public static <T> boolean updateIfNeeded(List<T> oldValue, List<T> newValue) { if (RefreshOrderingHelper.differentContents(oldValue, newValue)) { oldValue.clear(); oldValue.addAll(newValue); + return true; } + return false; } /** diff --git a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/refresh/RefreshLayoutCommand.java b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/refresh/RefreshLayoutCommand.java index 21c95471da..f539d8e1ff 100644 --- a/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/refresh/RefreshLayoutCommand.java +++ b/plugins/org.eclipse.sirius.diagram.sequence/src/org/eclipse/sirius/diagram/sequence/business/internal/refresh/RefreshLayoutCommand.java @@ -64,28 +64,40 @@ public class RefreshLayoutCommand extends RecordingCommand { protected void doExecute() { DslCommonPlugin.PROFILER.startWork(REFRESH_LAYOUT); SequenceDiagram sequenceDiagram = ISequenceElementAccessor.getSequenceDiagram(diagram).get(); - SequenceDDiagram sequenceDDiagram = sequenceDiagram.getSequenceDDiagram(); + sequenceDiagram.useCache(true); + try { + SequenceDDiagram sequenceDDiagram = sequenceDiagram.getSequenceDDiagram(); - /* - * Everything has been committed, so we should be in a stable state - * where it is safe to refresh both orderings. - */ - AbstractModelChangeOperation<Void> refreshSemanticOrderingOperation = new RefreshSemanticOrderingsOperation(sequenceDDiagram); - refreshSemanticOrderingOperation.execute(); - AbstractModelChangeOperation<Void> refreshGraphicalOrderingOperation = new RefreshGraphicalOrderingOperation(sequenceDiagram); - refreshGraphicalOrderingOperation.execute(); - - if (refreshDiagram) { - /* - * Launch a non-packing layout - */ - AbstractModelChangeOperation<Void> synchronizeGraphicalOrderingOperation = new SynchronizeGraphicalOrderingOperation(diagram, false); - synchronizeGraphicalOrderingOperation.execute(); /* - * The layout has probably changed graphical positions: re-compute - * the ordering to make sure it is up-to-date. + * Everything has been committed, so we should be in a stable state + * where it is safe to refresh both orderings. */ - refreshGraphicalOrderingOperation.execute(); + AbstractModelChangeOperation<Boolean> refreshSemanticOrderingOperation = new RefreshSemanticOrderingsOperation(sequenceDDiagram); + if (refreshSemanticOrderingOperation.execute()) { + sequenceDiagram.clearOrderedCaches(); + } + AbstractModelChangeOperation<Boolean> refreshGraphicalOrderingOperation = new RefreshGraphicalOrderingOperation(sequenceDiagram); + if (refreshGraphicalOrderingOperation.execute()) { + sequenceDiagram.clearOrderedCaches(); + } + + if (refreshDiagram) { + /* + * Launch a non-packing layout + */ + AbstractModelChangeOperation<Boolean> synchronizeGraphicalOrderingOperation = new SynchronizeGraphicalOrderingOperation(diagram, false); + synchronizeGraphicalOrderingOperation.execute(); + /* + * The layout has probably changed graphical positions: + * re-compute the ordering to make sure it is up-to-date. + */ + if (refreshGraphicalOrderingOperation.execute()) { + sequenceDiagram.clearOrderedCaches(); + } + } + } finally { + sequenceDiagram.useCache(false); + sequenceDiagram.clearAllCaches(); } DslCommonPlugin.PROFILER.stopWork(REFRESH_LAYOUT); } |
