package org.eclipse.uml2.diagram.sequence.model.builder; import java.util.HashMap; import java.util.Iterator; import org.eclipse.uml2.uml.CombinedFragment; import org.eclipse.uml2.uml.ExecutionSpecification; import org.eclipse.uml2.uml.Interaction; import org.eclipse.uml2.uml.InteractionFragment; import org.eclipse.uml2.uml.InteractionOperand; import org.eclipse.uml2.uml.OccurrenceSpecification; public class StartAndFinishRegistry { private HashMap<OccurrenceSpecification, ExecutionSpecification> myStarts; private HashMap<OccurrenceSpecification, ExecutionSpecification> myFinishes; private final Interaction myInteraction; public StartAndFinishRegistry(Interaction interaction){ myInteraction = interaction; } public void forceRemap(){ myStarts = null; myFinishes = null; } public ExecutionSpecification findStartedExecution(OccurrenceSpecification occurrence){ if (myStarts == null || myFinishes == null){ doRemap(); } return myStarts.get(occurrence); } public ExecutionSpecification findFinishedExecution(OccurrenceSpecification occurrence){ if (myStarts == null || myFinishes == null){ doRemap(); } return myFinishes.get(occurrence); } public ExecutionSpecification findExecution(OccurrenceSpecification occurrence){ if (myStarts == null || myFinishes == null){ doRemap(); } ExecutionSpecification startedAt = myStarts.get(occurrence); if (startedAt != null){ return startedAt; } return (startedAt != null) ? startedAt : myFinishes.get(occurrence); } private void doRemap(){ myStarts = new HashMap<OccurrenceSpecification, ExecutionSpecification>(); myFinishes = new HashMap<OccurrenceSpecification, ExecutionSpecification>(); doRemap(myInteraction.getFragments().iterator()); } private void doRemap(Iterator<InteractionFragment> fragments){ while (fragments.hasNext()){ InteractionFragment next = fragments.next(); if (next instanceof ExecutionSpecification){ ExecutionSpecification nextExecution = (ExecutionSpecification)next; checkDistinctEnds(nextExecution); OccurrenceSpecification start = nextExecution.getStart(); OccurrenceSpecification finish = nextExecution.getFinish(); checkTwoOwnersSameKind(start, nextExecution, myStarts.get(start), true); checkTwoOwnersSameKind(finish, nextExecution, myFinishes.get(finish), false); checkTwoOwnersDifferentKinds(start, nextExecution, myFinishes.get(start)); checkTwoOwnersDifferentKinds(finish, myStarts.get(finish), nextExecution); myStarts.put(start, nextExecution); myFinishes.put(finish, nextExecution); } if (next instanceof CombinedFragment){ CombinedFragment nextCombined = (CombinedFragment)next; for (InteractionOperand nextOperand : nextCombined.getOperands()){ doRemap(nextOperand.getFragments().iterator()); } } } } private void checkDistinctEnds(ExecutionSpecification execution) { if (execution.getStart() == null){ throw new IllegalStateException("Execution without a start: " + execution); } if (execution.getFinish() == null){ throw new IllegalStateException("Execution without a finish: " + execution); } if (execution.getStart() == execution.getFinish()){ throw new IllegalStateException("The same start and finish found for execution : " + execution); } } private void checkTwoOwnersSameKind(OccurrenceSpecification problem, ExecutionSpecification firstOwner, ExecutionSpecification secondOwner, boolean bothStartsNotFinishes){ if (secondOwner != null && secondOwner != firstOwner){ throw new IllegalStateException(// "OccurrenceSpecification: " + problem + " is " + (bothStartsNotFinishes ? "start" : "finish") + " for more than one Executions: " + firstOwner + ", and: " + secondOwner); } } private void checkTwoOwnersDifferentKinds(OccurrenceSpecification problem, ExecutionSpecification knownStart, ExecutionSpecification knownFinish){ if (knownStart != null && knownFinish != null){ throw new IllegalStateException(// "OccurrenceSpecification: " + problem + " is start for : " + knownStart + ", but finish for: " + knownFinish); } } }