[163331] Ensuring redefinitions are treated as transitive by state machine validation rules.
diff --git a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/RedefinableElementOperations.java b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/RedefinableElementOperations.java
index 72c7f48..f2fe451 100644
--- a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/RedefinableElementOperations.java
+++ b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/RedefinableElementOperations.java
@@ -8,7 +8,7 @@
  * Contributors:
  *   IBM - initial API and implementation
  *
- * $Id: RedefinableElementOperations.java,v 1.7 2006/03/13 20:50:41 khussey Exp $
+ * $Id: RedefinableElementOperations.java,v 1.7.2.1 2006/11/28 16:29:42 khussey Exp $
  */
 package org.eclipse.uml2.uml.internal.operations;
 
@@ -19,6 +19,7 @@
 import org.eclipse.emf.common.util.Diagnostic;
 import org.eclipse.emf.common.util.DiagnosticChain;
 import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.UniqueEList;
 
 import org.eclipse.uml2.uml.Classifier;
 import org.eclipse.uml2.uml.RedefinableElement;
@@ -201,4 +202,50 @@
 		return false;
 	}
 
-} // RedefinableElementOperations
\ No newline at end of file
+	protected static EList getAllRedefinedElements(
+			RedefinableElement redefinableElement, EList allRedefinedElements) {
+
+		for (Iterator redefinedElements = redefinableElement
+			.getRedefinedElements().iterator(); redefinedElements.hasNext();) {
+
+			Object redefinedElement = redefinedElements.next();
+
+			if (allRedefinedElements.add(redefinedElement)) {
+				getAllRedefinedElements((RedefinableElement) redefinedElement,
+					allRedefinedElements);
+			}
+		}
+
+		return allRedefinedElements;
+	}
+
+	protected static EList getAllRedefinedElements(
+			RedefinableElement redefinableElement) {
+		return getAllRedefinedElements(redefinableElement,
+			new UniqueEList.FastCompare());
+	}
+
+	protected static EList excludeRedefinedElements(EList redefineableElements) {
+		EList allRedefinedElements = new UniqueEList.FastCompare();
+
+		for (Iterator re = redefineableElements.iterator(); re.hasNext();) {
+			Object redefineableElement = re.next();
+
+			if (redefineableElement instanceof RedefinableElement) {
+				getAllRedefinedElements(
+					(RedefinableElement) redefineableElement,
+					allRedefinedElements);
+			}
+		}
+
+		for (Iterator re = redefineableElements.iterator(); re.hasNext();) {
+
+			if (allRedefinedElements.contains(re.next())) {
+				re.remove();
+			}
+		}
+
+		return redefineableElements;
+	}
+
+} // RedefinableElementOperations
diff --git a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/RegionOperations.java b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/RegionOperations.java
index 1080276..9d7e7ad 100644
--- a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/RegionOperations.java
+++ b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/RegionOperations.java
@@ -8,7 +8,7 @@
  * Contributors:
  *   IBM - initial API and implementation
  *
- * $Id: RegionOperations.java,v 1.8 2006/01/05 22:43:25 khussey Exp $
+ * $Id: RegionOperations.java,v 1.8.2.1 2006/11/28 16:29:42 khussey Exp $
  */
 package org.eclipse.uml2.uml.internal.operations;
 
@@ -19,6 +19,7 @@
 import org.eclipse.emf.common.util.Diagnostic;
 import org.eclipse.emf.common.util.DiagnosticChain;
 import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.UniqueEList;
 
 import org.eclipse.uml2.uml.BehavioredClassifier;
 import org.eclipse.uml2.uml.Classifier;
@@ -238,17 +239,23 @@
 	 */
 	public static boolean isRedefinitionContextValid(Region region,
 			Region redefined) {
-		StateMachine stateMachine = region.getStateMachine();
 
-		if (stateMachine != null) {
-			return stateMachine.getExtendedStateMachines().contains(
-				redefined.getStateMachine());
-		} else {
-			State state = redefined.getState();
+		if (redefined != null) {
+			StateMachine stateMachine = region.getStateMachine();
 
-			return state != null
-				&& state.getRedefinedState() == redefined.getState();
+			if (stateMachine != null) {
+				return StateMachineOperations.getAllExtendedStateMachines(
+					stateMachine).contains(redefined.getStateMachine());
+			} else {
+				State state = region.getState();
+
+				return state != null
+					&& StateOperations.getAllRedefinedStates(state).contains(
+						redefined.getState());
+			}
 		}
+
+		return false;
 	}
 
 	/**
@@ -320,38 +327,93 @@
 	public static boolean isConsistentWith(Region region,
 			RedefinableElement redefinee) {
 
-		if (redefinee.isRedefinitionContextValid(region)) {
+		if (redefinee != null && redefinee.isRedefinitionContextValid(region)) {
 			Region redefineeRegion = (Region) redefinee;
 
-			EList subvertices = region.getSubvertices();
+			EList allSubvertices = getAllSubvertices(region);
 
 			for (Iterator redefineeSubvertices = redefineeRegion
 				.getSubvertices().iterator(); redefineeSubvertices.hasNext();) {
 
-				Vertex subvertex = (Vertex) redefineeSubvertices.next();
+				Vertex redefineeSubvertex = (Vertex) redefineeSubvertices
+					.next();
 
-				if (subvertex instanceof State
-					&& subvertices.contains(((State) subvertex)
-						.getRedefinedState())) {
+				if (redefineeSubvertex instanceof State) {
+					State redefinedState = ((State) redefineeSubvertex)
+						.getRedefinedState();
 
-					return true;
+					if (redefinedState != null
+						&& !allSubvertices.contains(redefinedState)) {
+
+						return false;
+					}
 				}
 			}
 
-			EList transitions = region.getTransitions();
+			EList allTransitions = getAllTransitions(region);
 
 			for (Iterator redefineeTransitions = redefineeRegion
 				.getTransitions().iterator(); redefineeTransitions.hasNext();) {
 
-				if (transitions.contains(((Transition) redefineeTransitions
-					.next()).getRedefinedTransition())) {
+				Transition redefinedTransition = ((Transition) redefineeTransitions
+					.next()).getRedefinedTransition();
 
-					return true;
+				if (redefinedTransition != null
+					&& !allTransitions.contains(redefinedTransition)) {
+
+					return false;
 				}
 			}
+
+			return true;
 		}
 
 		return false;
 	}
 
-} // RegionOperations
\ No newline at end of file
+	protected static EList getAllExtendedRegions(Region region,
+			EList allExtendedRegions) {
+		Region extendedRegion = region.getExtendedRegion();
+
+		if (extendedRegion != null && allExtendedRegions.add(extendedRegion)) {
+			getAllExtendedRegions(extendedRegion, allExtendedRegions);
+		}
+
+		return allExtendedRegions;
+	}
+
+	protected static EList getAllExtendedRegions(Region region) {
+		return getAllExtendedRegions(region, new UniqueEList.FastCompare());
+	}
+
+	protected static EList getAllSubvertices(Region region) {
+		EList allSubvertices = new UniqueEList.FastCompare(region
+			.getSubvertices());
+
+		for (Iterator allExtendedRegions = getAllExtendedRegions(region)
+			.iterator(); allExtendedRegions.hasNext();) {
+
+			allSubvertices.addAll(((Region) allExtendedRegions.next())
+				.getSubvertices());
+		}
+
+		return RedefinableElementOperations
+			.excludeRedefinedElements(allSubvertices);
+	}
+
+	protected static EList getAllTransitions(Region region) {
+		EList allTransitions = new UniqueEList.FastCompare(region
+			.getTransitions());
+
+		for (Iterator allExtendedRegions = getAllExtendedRegions(region)
+			.iterator(); allExtendedRegions.hasNext();) {
+
+			allTransitions.addAll(((Region) allExtendedRegions.next())
+				.getTransitions());
+		}
+
+		return RedefinableElementOperations
+			.excludeRedefinedElements(allTransitions);
+	}
+
+} // RegionOperations
diff --git a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/StateMachineOperations.java b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/StateMachineOperations.java
index 94a9f2a..b77a5c1 100644
--- a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/StateMachineOperations.java
+++ b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/StateMachineOperations.java
@@ -8,17 +8,18 @@
  * Contributors:
  *   IBM - initial API and implementation
  *
- * $Id: StateMachineOperations.java,v 1.9.2.1 2006/11/08 19:11:48 khussey Exp $
+ * $Id: StateMachineOperations.java,v 1.9.2.2 2006/11/28 16:29:42 khussey Exp $
  */
 package org.eclipse.uml2.uml.internal.operations;
 
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
 import org.eclipse.emf.common.util.BasicDiagnostic;
 import org.eclipse.emf.common.util.Diagnostic;
 import org.eclipse.emf.common.util.DiagnosticChain;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.UniqueEList;
 
 import org.eclipse.uml2.uml.BehavioredClassifier;
 import org.eclipse.uml2.uml.Namespace;
@@ -308,10 +309,12 @@
 	public static boolean isConsistentWith(StateMachine stateMachine,
 			RedefinableElement redefinee) {
 
-		if (redefinee.isRedefinitionContextValid(stateMachine)) {
+		if (redefinee != null
+			&& redefinee.isRedefinitionContextValid(stateMachine)) {
+
 			StateMachine redefineeStateMachine = (StateMachine) redefinee;
 
-			List regions = stateMachine.getRegions();
+			EList allRegions = getAllRegions(stateMachine);
 
 			for (Iterator redefineeRegions = redefineeStateMachine.getRegions()
 				.iterator(); redefineeRegions.hasNext();) {
@@ -319,7 +322,7 @@
 				Region redefineeRegion = (Region) redefineeRegions.next();
 				Region extendedRegion = redefineeRegion.getExtendedRegion();
 
-				if (regions.contains(extendedRegion)
+				if (allRegions.contains(extendedRegion)
 					&& !extendedRegion.isConsistentWith(redefineeRegion)) {
 
 					return false;
@@ -332,4 +335,43 @@
 		return false;
 	}
 
+	protected static EList getAllExtendedStateMachines(
+			StateMachine stateMachine, EList allExtendedStateMachines) {
+
+		for (Iterator extendedStateMachines = stateMachine
+			.getExtendedStateMachines().iterator(); extendedStateMachines
+			.hasNext();) {
+
+			StateMachine extendedStateMachine = (StateMachine) extendedStateMachines
+				.next();
+
+			if (allExtendedStateMachines.add(extendedStateMachine)) {
+				getAllExtendedStateMachines(extendedStateMachine,
+					allExtendedStateMachines);
+			}
+		}
+
+		return allExtendedStateMachines;
+	}
+
+	protected static EList getAllExtendedStateMachines(StateMachine stateMachine) {
+		return getAllExtendedStateMachines(stateMachine,
+			new UniqueEList.FastCompare());
+	}
+
+	protected static EList getAllRegions(StateMachine stateMachine) {
+		EList allRegions = new UniqueEList.FastCompare(stateMachine
+			.getRegions());
+
+		for (Iterator allExtendedStateMachines = getAllExtendedStateMachines(
+			stateMachine).iterator(); allExtendedStateMachines.hasNext();) {
+
+			allRegions.addAll(((StateMachine) allExtendedStateMachines.next())
+				.getRegions());
+		}
+
+		return RedefinableElementOperations
+			.excludeRedefinedElements(allRegions);
+	}
+
 } // StateMachineOperations
\ No newline at end of file
diff --git a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/StateOperations.java b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/StateOperations.java
index 8383b98..d12802d 100644
--- a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/StateOperations.java
+++ b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/StateOperations.java
@@ -8,7 +8,7 @@
  * Contributors:
  *   IBM - initial API and implementation
  *
- * $Id: StateOperations.java,v 1.7 2006/04/05 13:50:02 khussey Exp $
+ * $Id: StateOperations.java,v 1.7.2.1 2006/11/28 16:29:42 khussey Exp $
  */
 package org.eclipse.uml2.uml.internal.operations;
 
@@ -19,6 +19,7 @@
 import org.eclipse.emf.common.util.Diagnostic;
 import org.eclipse.emf.common.util.DiagnosticChain;
 import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.UniqueEList;
 
 import org.eclipse.uml2.uml.BehavioredClassifier;
 import org.eclipse.uml2.uml.Classifier;
@@ -319,10 +320,14 @@
 	 */
 	public static boolean isRedefinitionContextValid(State state,
 			State redefined) {
-		Region container = state.getContainer();
 
-		if (container != null && redefined != null) {
-			return container.getExtendedRegion() == redefined.getContainer();
+		if (redefined != null) {
+			Region container = state.getContainer();
+
+			if (container != null) {
+				return RegionOperations.getAllExtendedRegions(container)
+					.contains(redefined.getContainer());
+			}
 		}
 
 		return false;
@@ -340,29 +345,25 @@
 	public static boolean isConsistentWith(State state,
 			RedefinableElement redefinee) {
 
-		if (redefinee.isRedefinitionContextValid(state)) {
+		if (redefinee != null && redefinee.isRedefinitionContextValid(state)) {
 			State redefineeState = (State) redefinee;
 
-			if (state.isSimple()) {
-				return redefineeState.isComposite();
-			} else if (state.isComposite()) {
-				EList regions = state.getRegions();
+			EList allRegions = getAllRegions(state);
 
-				for (Iterator redefineeRegions = redefineeState.getRegions()
-					.iterator(); redefineeRegions.hasNext();) {
+			for (Iterator redefineeRegions = redefineeState.getRegions()
+				.iterator(); redefineeRegions.hasNext();) {
 
-					Region redefineeRegion = (Region) redefineeRegions.next();
-					Region extendedRegion = redefineeRegion.getExtendedRegion();
+				Region redefineeRegion = (Region) redefineeRegions.next();
+				Region extendedRegion = redefineeRegion.getExtendedRegion();
 
-					if (regions.contains(extendedRegion)
-						&& !extendedRegion.isConsistentWith(redefineeRegion)) {
+				if (allRegions.contains(extendedRegion)
+					&& !extendedRegion.isConsistentWith(redefineeRegion)) {
 
-						return false;
-					}
+					return false;
 				}
-
-				return true;
 			}
+
+			return true;
 		}
 
 		return false;
@@ -385,4 +386,32 @@
 			: container.containingStateMachine();
 	}
 
-} // StateOperations
\ No newline at end of file
+	protected static EList getAllRedefinedStates(State state,
+			EList allRedefinedStates) {
+		State redefinedState = state.getRedefinedState();
+
+		if (redefinedState != null && allRedefinedStates.add(redefinedState)) {
+			getAllRedefinedStates(redefinedState, allRedefinedStates);
+		}
+
+		return allRedefinedStates;
+	}
+
+	protected static EList getAllRedefinedStates(State state) {
+		return getAllRedefinedStates(state, new UniqueEList.FastCompare());
+	}
+
+	protected static EList getAllRegions(State state) {
+		EList allRegions = new UniqueEList.FastCompare(state.getRegions());
+
+		for (Iterator allRedefinedStates = getAllRedefinedStates(state)
+			.iterator(); allRedefinedStates.hasNext();) {
+
+			allRegions.addAll(((State) allRedefinedStates).getRegions());
+		}
+
+		return RedefinableElementOperations
+			.excludeRedefinedElements(allRegions);
+	}
+
+} // StateOperations
diff --git a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/TransitionOperations.java b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/TransitionOperations.java
index 5cb5517..9c6224c 100644
--- a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/TransitionOperations.java
+++ b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/operations/TransitionOperations.java
@@ -8,7 +8,7 @@
  * Contributors:
  *   IBM - initial API and implementation
  *
- * $Id: TransitionOperations.java,v 1.7.2.2 2006/07/28 21:38:59 khussey Exp $
+ * $Id: TransitionOperations.java,v 1.7.2.3 2006/11/28 16:29:42 khussey Exp $
  */
 package org.eclipse.uml2.uml.internal.operations;
 
@@ -17,6 +17,8 @@
 import org.eclipse.emf.common.util.BasicDiagnostic;
 import org.eclipse.emf.common.util.Diagnostic;
 import org.eclipse.emf.common.util.DiagnosticChain;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.UniqueEList;
 
 import org.eclipse.uml2.uml.BehavioredClassifier;
 import org.eclipse.uml2.uml.Classifier;
@@ -24,6 +26,7 @@
 import org.eclipse.uml2.uml.Region;
 import org.eclipse.uml2.uml.StateMachine;
 import org.eclipse.uml2.uml.Transition;
+import org.eclipse.uml2.uml.Vertex;
 
 import org.eclipse.uml2.uml.util.UMLValidator;
 
@@ -354,13 +357,51 @@
 	public static boolean isConsistentWith(Transition transition,
 			RedefinableElement redefinee) {
 
-		if (redefinee.isRedefinitionContextValid(transition)) {
-			Transition trans = (Transition) redefinee;
-			return transition.getSource() == trans.getSource()
-				&& transition.getTriggers().equals(trans.getTriggers());
+		if (redefinee != null
+			&& redefinee.isRedefinitionContextValid(transition)) {
+
+			Transition redefineeTransition = (Transition) redefinee;
+
+			EList sources = new UniqueEList.FastCompare();
+
+			Vertex source = transition.getSource();
+
+			if (source != null) {
+				sources.add(source);
+			}
+
+			Vertex redefineeSource = redefineeTransition.getSource();
+
+			if (redefineeSource != null) {
+				sources.add(redefineeSource);
+			}
+
+			return RedefinableElementOperations.excludeRedefinedElements(
+				sources).size() < 2
+				&& transition.getTriggers().equals(
+					redefineeTransition.getTriggers());
 		}
 
 		return false;
 	}
 
+	protected static EList getAllRedefinedTransitions(Transition transition,
+			EList allRedefinedTransitions) {
+		Transition redefinedTransition = transition.getRedefinedTransition();
+
+		if (redefinedTransition != null
+			&& allRedefinedTransitions.add(redefinedTransition)) {
+
+			getAllRedefinedTransitions(redefinedTransition,
+				allRedefinedTransitions);
+		}
+
+		return allRedefinedTransitions;
+	}
+
+	protected static EList getAllRedefinedTransitions(Transition transition) {
+		return getAllRedefinedTransitions(transition,
+			new UniqueEList.FastCompare());
+	}
+
 } // TransitionOperations
\ No newline at end of file