Bug 551906 - [Moka] Send exception instead of managing this error in
aspects

Change-Id: I0257ce6b4301cb71f914534f3f24ef7569806956
Signed-off-by: Pauline DEVILLE <pauline.deville@cea.fr>
diff --git a/plugins/org.eclipse.papyrus.moka.engine.uml.scheduling/META-INF/MANIFEST.MF b/plugins/org.eclipse.papyrus.moka.engine.uml.scheduling/META-INF/MANIFEST.MF
index 8334b4a..6c8fb0b 100644
--- a/plugins/org.eclipse.papyrus.moka.engine.uml.scheduling/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.papyrus.moka.engine.uml.scheduling/META-INF/MANIFEST.MF
@@ -7,5 +7,9 @@
 Automatic-Module-Name: org.eclipse.papyrus.moka.engine.uml.scheduling
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Require-Bundle: org.eclipse.papyrus.moka.kernel.scheduling,
- org.eclipse.papyrus.moka.fuml.interfaces
+ org.eclipse.papyrus.moka.fuml.interfaces,
+ org.eclipse.papyrus.moka.kernel,
+ org.eclipse.papyrus.moka.kernel.debug,
+ org.eclipse.papyrus.moka.kernel.animation,
+ org.eclipse.papyrus.moka.engine.uml.debug
 Export-Package: org.eclipse.papyrus.moka.engine.uml.scheduling
diff --git a/plugins/org.eclipse.papyrus.moka.engine.uml.scheduling/src/org/eclipse/papyrus/moka/engine/uml/scheduling/UMLEventDispatchLoopExecution.java b/plugins/org.eclipse.papyrus.moka.engine.uml.scheduling/src/org/eclipse/papyrus/moka/engine/uml/scheduling/UMLEventDispatchLoopExecution.java
index b3f9752..a8836e4 100644
--- a/plugins/org.eclipse.papyrus.moka.engine.uml.scheduling/src/org/eclipse/papyrus/moka/engine/uml/scheduling/UMLEventDispatchLoopExecution.java
+++ b/plugins/org.eclipse.papyrus.moka.engine.uml.scheduling/src/org/eclipse/papyrus/moka/engine/uml/scheduling/UMLEventDispatchLoopExecution.java
@@ -10,18 +10,34 @@
  *
  * Contributors:
  *   CEA LIST - Initial API and implementation
+ *   CEA LIST - Bug 551906
  *   
  *****************************************************************************/
 
 package org.eclipse.papyrus.moka.engine.uml.scheduling;
 
+import java.util.Collection;
+import java.util.List;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.eclipse.papyrus.moka.animation.engine.AnimationService;
+import org.eclipse.papyrus.moka.animation.engine.rendering.AnimationEngine;
+import org.eclipse.papyrus.moka.animation.engine.rendering.DiagramHandler;
+import org.eclipse.papyrus.moka.debug.assistant.DebugAssistantException;
+import org.eclipse.papyrus.moka.debug.service.IDebugService;
+import org.eclipse.papyrus.moka.engine.uml.debug.listeners.UMLSemanticVisitorExecutionListener;
 import org.eclipse.papyrus.moka.fuml.commonbehavior.IClassifierBehaviorInvocationEventAccepter;
 import org.eclipse.papyrus.moka.fuml.commonbehavior.IObjectActivation;
+import org.eclipse.papyrus.moka.fuml.loci.ISemanticVisitor;
 import org.eclipse.papyrus.moka.fuml.simpleclassifiers.IValue;
 import org.eclipse.papyrus.moka.fuml.structuredclassifiers.IObject_;
+import org.eclipse.papyrus.moka.kernel.SuspensionReasons;
+import org.eclipse.papyrus.moka.kernel.assistant.Suspension;
+import org.eclipse.papyrus.moka.kernel.engine.IExecutionEngine;
 import org.eclipse.papyrus.moka.kernel.scheduling.control.IExecutionLoop;
+import org.eclipse.papyrus.moka.kernel.service.IExecutionEngineService;
+import org.eclipse.papyrus.moka.kernel.service.ServiceRegistry;
+import org.eclipse.uml2.uml.Element;
 
 public class UMLEventDispatchLoopExecution extends UMLTaskExecution implements IUMLEventDispatchLoopExecution {
 
@@ -58,11 +74,11 @@
 	@Override
 	public boolean canExecute() {
 		boolean canExecute = false;
-		if(!dispatchLoopLock.isHeldByCurrentThread()) {
+		if (!dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.lock();
 		}
 		canExecute = dispatchLoop != null;
-		if(dispatchLoopLock.isHeldByCurrentThread()) {
+		if (dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.unlock();
 		}
 		return canExecute;
@@ -72,14 +88,14 @@
 	 * @see IUMLEventDispatchLoopExecution#newSignalArrival()
 	 */
 	public void newSignalArrival() {
-		if(!signalCountLock.isHeldByCurrentThread()) {
+		if (!signalCountLock.isHeldByCurrentThread()) {
 			signalCountLock.lock();
 		}
 		signalCount++;
 		if (this.signalCount == 1) {
 			schedule();
 		}
-		if(signalCountLock.isHeldByCurrentThread()) {
+		if (signalCountLock.isHeldByCurrentThread()) {
 			signalCountLock.unlock();
 		}
 	}
@@ -88,20 +104,76 @@
 	 * @see IUMLEventDispatchLoopExecution#dispatchNextEvent()
 	 */
 	public void dispatchNextEvent() {
-		if(!dispatchLoopLock.isHeldByCurrentThread()) {
+		if (!dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.lock();
 		}
 		try {
 			dispatchLoop.dispatchNextEvent();
+		} catch (DebugAssistantException debugAssistantException) {
+			List<IExecutionEngineService<IExecutionEngine>> debugServices = ServiceRegistry.getInstance()
+					.getService(IDebugService.class);
+			if (!debugServices.isEmpty()) {
+				fireErrorDetectionError((IDebugService<?, ?>) debugServices.get(0), debugAssistantException);
+			}
+			// debugAssistantException.printStackTrace();
 		} catch (Exception e) {
-			// TODO : record exception in order to provide user feedback
+			// e.printStackTrace();
 		} finally {
-			if(dispatchLoopLock.isHeldByCurrentThread()) {
+			if (dispatchLoopLock.isHeldByCurrentThread()) {
 				dispatchLoopLock.unlock();
 			}
 		}
 	}
 
+	protected void fireErrorDetectionError(IDebugService<?, ?> executionEngineService,
+			DebugAssistantException debugAssistantException) {
+		Suspension suspension = new Suspension(debugAssistantException.getDebugAssistant(),
+				SuspensionReasons.ERROR_DETECTION);
+		if (executionEngineService.shouldContinueInDebugAssistant(suspension)) {
+			Element node = debugAssistantException.getVisitorNode();
+			ISemanticVisitor visitor = debugAssistantException.getVisitor();
+			if (node != null) {
+				// Open diagrams
+				DiagramHandler diagramManager = getDiagramHandler(debugAssistantException);
+				if (diagramManager != null) {
+					if (!diagramManager.hasOpenedDiagram(node)) {
+						diagramManager.openDiagrams(node);
+					} else {
+						diagramManager.selectDiagrams(node);
+					}
+				}
+
+				// Ask to every UMLSemanticVisitorExecution service to suspend
+				Collection<IExecutionEngineService<IExecutionEngine>> allServices = ServiceRegistry.getInstance()
+						.getAllServices();
+				for (IExecutionEngineService<IExecutionEngine> service : allServices) {
+					if (service instanceof UMLSemanticVisitorExecutionListener) {
+						if (!(service instanceof IDebugService)) {
+							((UMLSemanticVisitorExecutionListener) service).nodeSuspended(visitor, suspension);
+						}
+					}
+				}
+				// The debug service suspend the thread so it should works in last
+				if (executionEngineService instanceof UMLSemanticVisitorExecutionListener) {
+					((UMLSemanticVisitorExecutionListener) executionEngineService).nodeSuspended(visitor, suspension);
+				}
+			}
+		}
+	}
+
+	private DiagramHandler getDiagramHandler(DebugAssistantException debugAssistantException) {
+		List<IExecutionEngineService<IExecutionEngine>> animationServices = ServiceRegistry.getInstance()
+				.getService(AnimationService.class);
+		if (!animationServices.isEmpty()) {
+			AnimationService animationService = (AnimationService) animationServices.get(0);
+			AnimationEngine animationEngine = animationService.getEngine();
+			if (animationEngine != null) {
+				return animationEngine.getDiagramHandler();
+			}
+		}
+		return null;
+	}
+
 	/**
 	 * Dispatch the next event. If events remain to be dispatched then include this
 	 * execution to the loop
@@ -109,14 +181,14 @@
 	@Override
 	public void execute() {
 		dispatchNextEvent();
-		if(!signalCountLock.isHeldByCurrentThread()) {
+		if (!signalCountLock.isHeldByCurrentThread()) {
 			signalCountLock.lock();
 		}
 		signalCount--;
 		if (signalCount > 0) {
 			executionLoop.include(this);
 		}
-		if(signalCountLock.isHeldByCurrentThread()) {
+		if (signalCountLock.isHeldByCurrentThread()) {
 			signalCountLock.unlock();
 		}
 	}
@@ -136,7 +208,7 @@
 	@Override
 	public void suspend() {
 		System.out.println("Suspend -> " + this);
-		if(!dispatchLoopLock.isHeldByCurrentThread()) {
+		if (!dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.lock();
 		}
 		for (IClassifierBehaviorInvocationEventAccepter cbInvocation : dispatchLoop
@@ -144,11 +216,11 @@
 			// TODO - classifier behaviors shall be suspended
 			cbInvocation.getExecution();
 		}
-		if(dispatchLoopLock.isHeldByCurrentThread()) {
+		if (dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.unlock();
 		}
 	}
-	
+
 	@Override
 	public void resume() {
 		System.out.println("Resume -> " + this);
@@ -156,7 +228,7 @@
 
 	@Override
 	public void terminate() {
-		if(!dispatchLoopLock.isHeldByCurrentThread()) {
+		if (!dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.lock();
 		}
 		dispatchLoopLock.lock();
@@ -165,31 +237,31 @@
 			context.destroy();
 		}
 		dispatchLoop = null;
-		if(dispatchLoopLock.isHeldByCurrentThread()) {
+		if (dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.unlock();
 		}
 	}
 
 	@Override
 	public void setObjectActivation(IObjectActivation objectActivation) {
-		if(!dispatchLoopLock.isHeldByCurrentThread()) {
+		if (!dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.lock();
 		}
 		dispatchLoop = objectActivation;
-		if(dispatchLoopLock.isHeldByCurrentThread()) {
+		if (dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.unlock();
 		}
 	}
 
 	public IObject_ getContext() {
 		IObject_ context = null;
-		if(!dispatchLoopLock.isHeldByCurrentThread()) {
+		if (!dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.lock();
 		}
 		if (dispatchLoop != null) {
 			context = dispatchLoop.getObject();
 		}
-		if(dispatchLoopLock.isHeldByCurrentThread()) {
+		if (dispatchLoopLock.isHeldByCurrentThread()) {
 			dispatchLoopLock.unlock();
 		}
 		return context;
diff --git a/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/AbstractActivityNodeDebugAssistantProfiler.java b/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/AbstractActivityNodeDebugAssistantProfiler.java
index 21c3a8f..9b0b067 100644
--- a/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/AbstractActivityNodeDebugAssistantProfiler.java
+++ b/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/AbstractActivityNodeDebugAssistantProfiler.java
@@ -15,12 +15,13 @@
 
 import org.eclipse.papyrus.moka.fuml.activities.IActivityNodeActivation;
 import org.eclipse.papyrus.moka.fuml.loci.ISemanticVisitor;
+import org.eclipse.papyrus.moka.kernel.assistant.IDebugAssistant;
 import org.eclipse.uml2.uml.Element;
 
-public abstract class AbstractActivityNodeDebugAssistantProfiler extends AbstractDebugAssistantProfiler {
+public abstract class AbstractActivityNodeDebugAssistantProfiler implements IDebugAssistant {
 
 	@Override
-	protected Element getVisitorNode(ISemanticVisitor visitor) {
+	public Element getVisitorNode(ISemanticVisitor visitor) {
 		if(visitor instanceof IActivityNodeActivation) {
 			return ((IActivityNodeActivation) visitor).getNode();
 		}
diff --git a/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/AbstractDebugAssistantProfiler.java b/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/AbstractDebugAssistantProfiler.java
deleted file mode 100644
index e41e884..0000000
--- a/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/AbstractDebugAssistantProfiler.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*****************************************************************************
- * Copyright (c) 2019 CEA LIST.
- * 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License 2.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- *  CEA LIST Initial API and implementation
- *****************************************************************************/
-package org.eclipse.papyrus.moka.fuml.profiling.debug;
-
-import org.eclipse.papyrus.moka.animation.engine.rendering.DiagramHandler;
-import org.eclipse.papyrus.moka.debug.service.IDebugService;
-import org.eclipse.papyrus.moka.engine.uml.debug.listeners.UMLSemanticVisitorExecutionListener;
-import org.eclipse.papyrus.moka.fuml.loci.ISemanticVisitor;
-import org.eclipse.papyrus.moka.fuml.profiling.MokaObservable;
-import org.eclipse.papyrus.moka.kernel.SuspensionReasons;
-import org.eclipse.papyrus.moka.kernel.assistant.IDebugAssistant;
-import org.eclipse.papyrus.moka.kernel.assistant.Suspension;
-import org.eclipse.papyrus.moka.kernel.engine.IExecutionEngine;
-import org.eclipse.papyrus.moka.kernel.service.IExecutionEngineService;
-import org.eclipse.uml2.uml.Element;
-
-public abstract class AbstractDebugAssistantProfiler extends MokaObservable implements IDebugAssistant {
-
-	private DiagramHandler diagramHandler;
-
-	public AbstractDebugAssistantProfiler() {
-	}
-
-	protected void fireDebugEvent(ISemanticVisitor visitor) {
-		Suspension suspension = new Suspension(this, SuspensionReasons.ERROR_DETECTION);
-		if (shouldContinueInDebugAssistant(suspension)) {
-			Element node = getVisitorNode(visitor);
-			if (node != null) {
-				// Open diagrams
-				UMLSemanticVisitorExecutionListener debugService = null;
-				DiagramHandler diagramManager = getDiagramHandler(visitor);
-				if (!diagramManager.hasOpenedDiagram(node)) {
-					diagramManager.openDiagrams(node);
-				} else {
-					diagramManager.selectDiagrams(node);
-				}
-
-				// Ask to every UMLSemanticVisitorExecution service to suspend
-				for (IExecutionEngineService<IExecutionEngine> service : getListeners()) {
-					if (service instanceof UMLSemanticVisitorExecutionListener) {
-						if (service instanceof IDebugService) {
-							debugService = (UMLSemanticVisitorExecutionListener) service;
-						} else {
-							((UMLSemanticVisitorExecutionListener) service).nodeSuspended(visitor,
-									suspension);
-						}
-					}
-				}
-				if (debugService != null) {
-					// The debug service suspend the thread so it should works in last
-					debugService.nodeSuspended(visitor, suspension);
-				}
-			}
-		}
-	}
-
-	protected boolean shouldContinueInDebugAssistant(Suspension suspension) {
-		for (IExecutionEngineService<IExecutionEngine> service : getListeners()) {
-			if (service instanceof IDebugService) {
-				return ((IDebugService<?, ?>) service).shouldContinueInDebugAssistant(suspension);
-			}
-		}
-		return false;
-	}
-
-	protected DiagramHandler getDiagramHandler(ISemanticVisitor visitor) {
-		if (diagramHandler == null) {
-			diagramHandler = new DiagramHandler();
-			diagramHandler.init(getVisitorNode(visitor));
-		}
-		return diagramHandler;
-	}
-
-	/**
-	 * Get node for the visitor, this is the node which will be marked as suspended
-	 * 
-	 * @param visitor the current visitor
-	 * @return the node corresponding to the given visitor
-	 */
-	protected abstract Element getVisitorNode(ISemanticVisitor visitor);
-
-}
diff --git a/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/NullStructuredValueProfiler.aj b/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/NullStructuredValueProfiler.aj
index 58dd2db..7be3e65 100644
--- a/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/NullStructuredValueProfiler.aj
+++ b/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/NullStructuredValueProfiler.aj
@@ -13,6 +13,7 @@
  *****************************************************************************/
 package org.eclipse.papyrus.moka.fuml.profiling.debug;
 
+import org.eclipse.papyrus.moka.debug.assistant.DebugAssistantException;
 import org.eclipse.papyrus.moka.fuml.activities.IActivityNodeActivation;
 import org.eclipse.papyrus.moka.fuml.simpleclassifiers.IFeatureValue;
 import org.eclipse.papyrus.moka.fuml.simpleclassifiers.IStructuredValue;
@@ -34,7 +35,8 @@
 	after(IStructuredValue structuredValue, StructuralFeature feature) returning(IFeatureValue featureValue): getFeatureValue(structuredValue, feature){
 		if (featureValue == null) {
 			if (thisJoinPoint.getThis() instanceof IActivityNodeActivation) {
-				fireDebugEvent((IActivityNodeActivation)thisJoinPoint.getThis());
+				IActivityNodeActivation visitor = (IActivityNodeActivation) thisJoinPoint.getThis();
+				throw new DebugAssistantException(this, visitor);
 			}
 		}
 	}
diff --git a/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/NullTokenPropagationProfiler.aj b/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/NullTokenPropagationProfiler.aj
index 168e66c..d2c01fb 100644
--- a/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/NullTokenPropagationProfiler.aj
+++ b/plugins/org.eclipse.papyrus.moka.fuml/aspects/org/eclipse/papyrus/moka/fuml/profiling/debug/NullTokenPropagationProfiler.aj
@@ -15,6 +15,7 @@
 
 import java.util.List;
 
+import org.eclipse.papyrus.moka.debug.assistant.DebugAssistantException;
 import org.eclipse.papyrus.moka.fuml.actions.OutputPinActivation;
 import org.eclipse.papyrus.moka.fuml.activities.IObjectNodeActivation;
 import org.eclipse.papyrus.moka.fuml.activities.IToken;
@@ -34,10 +35,10 @@
 	
 	after(OutputPinActivation objectNode) returning(List<IToken> tokens): getUnofferedTokens(objectNode){
 		if(tokens.isEmpty() && ((OutputPin)objectNode.getNode()).getLower()> 0){
-			fireDebugEvent(objectNode);
+			throw new DebugAssistantException(this, objectNode);
 		}
 	}
-	
+
 	@Override
 	public String getAssistantID() {
 		return ASSISTANT_ID;
diff --git a/plugins/org.eclipse.papyrus.moka.kernel.animation/src/org/eclipse/papyrus/moka/animation/engine/AnimationService.java b/plugins/org.eclipse.papyrus.moka.kernel.animation/src/org/eclipse/papyrus/moka/animation/engine/AnimationService.java
index 85e8c24..838ec3b 100644
--- a/plugins/org.eclipse.papyrus.moka.kernel.animation/src/org/eclipse/papyrus/moka/animation/engine/AnimationService.java
+++ b/plugins/org.eclipse.papyrus.moka.kernel.animation/src/org/eclipse/papyrus/moka/animation/engine/AnimationService.java
@@ -10,6 +10,8 @@
  *
  * Contributors:
  *  CEA LIST Initial API and implementation
+ *  CEA List - Bug 551906
+ *  
  *****************************************************************************/
 package org.eclipse.papyrus.moka.animation.engine;
 
@@ -67,5 +69,9 @@
 		}
 		return animator;
 	}
+	
+	public AnimationEngine getEngine() {
+		return engine;
+	}
 
 }
diff --git a/plugins/org.eclipse.papyrus.moka.kernel.debug/META-INF/MANIFEST.MF b/plugins/org.eclipse.papyrus.moka.kernel.debug/META-INF/MANIFEST.MF
index 51181dd..2f6cc74 100644
--- a/plugins/org.eclipse.papyrus.moka.kernel.debug/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.papyrus.moka.kernel.debug/META-INF/MANIFEST.MF
@@ -27,6 +27,7 @@
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Export-Package: org.eclipse.papyrus.moka.debug,
+ org.eclipse.papyrus.moka.debug.assistant,
  org.eclipse.papyrus.moka.debug.breakpoint,
  org.eclipse.papyrus.moka.debug.communication,
  org.eclipse.papyrus.moka.debug.engine,
diff --git a/plugins/org.eclipse.papyrus.moka.kernel.debug/src/org/eclipse/papyrus/moka/debug/assistant/DebugAssistantException.java b/plugins/org.eclipse.papyrus.moka.kernel.debug/src/org/eclipse/papyrus/moka/debug/assistant/DebugAssistantException.java
new file mode 100644
index 0000000..90226a7
--- /dev/null
+++ b/plugins/org.eclipse.papyrus.moka.kernel.debug/src/org/eclipse/papyrus/moka/debug/assistant/DebugAssistantException.java
@@ -0,0 +1,131 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST.
+ * 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *  CEA LIST Initial API and implementation
+ *****************************************************************************/
+package org.eclipse.papyrus.moka.debug.assistant;
+
+import org.eclipse.papyrus.moka.fuml.loci.ISemanticVisitor;
+import org.eclipse.papyrus.moka.kernel.assistant.IDebugAssistant;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.NamedElement;
+
+public class DebugAssistantException extends RuntimeException {
+
+	private static final long serialVersionUID = 7505081361638138900L;
+
+	protected IDebugAssistant debugAssistant;
+
+	protected ISemanticVisitor visitor;
+
+	protected Element visitorNode;
+
+	protected String message;
+
+	/**
+	 * Constructor
+	 * 
+	 * @param visitor     the visitor
+	 * @param visitorNode the node corresponding to the visitor
+	 */
+	public DebugAssistantException(IDebugAssistant debugAssistant, ISemanticVisitor visitor) {
+		this(debugAssistant, visitor, null);
+	}
+
+	/**
+	 * Constructor
+	 * 
+	 * @param debugAssistant the debug assistant
+	 * @param visitor        the visitor
+	 * @param message        a message to use in the thread label
+	 */
+	public DebugAssistantException(IDebugAssistant debugAssistant, ISemanticVisitor visitor, String message) {
+		super();
+		this.debugAssistant = debugAssistant;
+		this.visitor = visitor;
+		this.visitorNode = this.debugAssistant.getVisitorNode(visitor);
+		this.message = message;
+	}
+
+	/**
+	 * @return the debugAssistant
+	 */
+	public IDebugAssistant getDebugAssistant() {
+		return debugAssistant;
+	}
+
+	/**
+	 * @param debugAssistant the debugAssistant to set
+	 */
+	public void setDebugAssistant(IDebugAssistant debugAssistant) {
+		this.debugAssistant = debugAssistant;
+	}
+
+	/**
+	 * @return the visitor
+	 */
+	public ISemanticVisitor getVisitor() {
+		return visitor;
+	}
+
+	/**
+	 * @param visitor the visitor to set
+	 */
+	public void setVisitor(ISemanticVisitor visitor) {
+		this.visitor = visitor;
+	}
+
+	/**
+	 * @return the visitorNode
+	 */
+	public Element getVisitorNode() {
+		return visitorNode;
+	}
+
+	/**
+	 * @param visitorNode the visitorNode to set
+	 */
+	public void setVisitorNode(Element visitorNode) {
+		this.visitorNode = visitorNode;
+	}
+
+	/**
+	 * @return the message
+	 */
+	public String getMessage() {
+		return message;
+	}
+
+	/**
+	 * @param message the message to set
+	 */
+	public void setMessage(String message) {
+		this.message = message;
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		if (message != null) {
+			builder.append(message);
+		} else {
+			builder.append("Missing expected tokens\n");
+		}
+		builder.append("Current visited node: ");
+		if (visitorNode instanceof NamedElement) {
+			builder.append(((NamedElement) visitorNode).getQualifiedName());
+		} else {
+			builder.append(visitorNode);
+		}
+		return builder.toString();
+	}
+
+}
diff --git a/plugins/org.eclipse.papyrus.moka.kernel/src/org/eclipse/papyrus/moka/kernel/assistant/IDebugAssistant.java b/plugins/org.eclipse.papyrus.moka.kernel/src/org/eclipse/papyrus/moka/kernel/assistant/IDebugAssistant.java
index 456e775..50b34d7 100644
--- a/plugins/org.eclipse.papyrus.moka.kernel/src/org/eclipse/papyrus/moka/kernel/assistant/IDebugAssistant.java
+++ b/plugins/org.eclipse.papyrus.moka.kernel/src/org/eclipse/papyrus/moka/kernel/assistant/IDebugAssistant.java
@@ -14,6 +14,9 @@
  *****************************************************************************/
 package org.eclipse.papyrus.moka.kernel.assistant;
 
+import org.eclipse.papyrus.moka.fuml.loci.ISemanticVisitor;
+import org.eclipse.uml2.uml.Element;
+
 public interface IDebugAssistant {
 
 	/**
@@ -23,4 +26,11 @@
 	 */
 	public String getAssistantID();
 	
+	/**
+	 * Get the node from the given visitor
+	 * @param visitor the visitor
+	 * @return the visitor node
+	 */
+	public Element getVisitorNode(ISemanticVisitor visitor);
+	
 }
diff --git a/plugins/org.eclipse.papyrus.moka.pscs/META-INF/MANIFEST.MF b/plugins/org.eclipse.papyrus.moka.pscs/META-INF/MANIFEST.MF
index 6796dd9..aeb336f 100644
--- a/plugins/org.eclipse.papyrus.moka.pscs/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.papyrus.moka.pscs/META-INF/MANIFEST.MF
@@ -4,7 +4,8 @@
  org.eclipse.papyrus.moka.pscs.interfaces,
  org.eclipse.papyrus.moka.kernel,
  org.aspectj.runtime;bundle-version="[1.9.0,2.0.0)",
- org.eclipse.debug.core;bundle-version="[3.12.0,4.0.0)"
+ org.eclipse.debug.core;bundle-version="[3.12.0,4.0.0)",
+ org.eclipse.papyrus.moka.kernel.debug
 Bundle-Vendor: Eclipse Modeling Project
 Bundle-ActivationPolicy: lazy
 Bundle-Version: 4.0.0.qualifier
diff --git a/plugins/org.eclipse.papyrus.moka.pscs/aspects/org/eclipse/papyrus/moka/pscs/profiling/debug/NullStructuredValueProfiler.aj b/plugins/org.eclipse.papyrus.moka.pscs/aspects/org/eclipse/papyrus/moka/pscs/profiling/debug/NullStructuredValueProfiler.aj
index a881dfd..f753926 100644
--- a/plugins/org.eclipse.papyrus.moka.pscs/aspects/org/eclipse/papyrus/moka/pscs/profiling/debug/NullStructuredValueProfiler.aj
+++ b/plugins/org.eclipse.papyrus.moka.pscs/aspects/org/eclipse/papyrus/moka/pscs/profiling/debug/NullStructuredValueProfiler.aj
@@ -13,6 +13,7 @@
  *****************************************************************************/
 package org.eclipse.papyrus.moka.pscs.profiling.debug;
 
+import org.eclipse.papyrus.moka.debug.assistant.DebugAssistantException;
 import org.eclipse.papyrus.moka.fuml.activities.IActivityNodeActivation;
 import org.eclipse.papyrus.moka.fuml.profiling.debug.AbstractActivityNodeDebugAssistantProfiler;
 import org.eclipse.papyrus.moka.fuml.simpleclassifiers.IFeatureValue;
@@ -22,7 +23,7 @@
 public aspect NullStructuredValueProfiler extends AbstractActivityNodeDebugAssistantProfiler {
 
 	public static final String ASSISTANT_ID = "org.eclipse.papyrus.moka.pscs.profiling.debug.NullStructuredValueProfiler";
-	
+
 	public NullStructuredValueProfiler() {
 		super();
 	}
@@ -35,11 +36,12 @@
 	after(IStructuredValue structuredValue, StructuralFeature feature) returning(IFeatureValue featureValue): getFeatureValue(structuredValue, feature){
 		if (featureValue == null) {
 			if (thisJoinPoint.getThis() instanceof IActivityNodeActivation) {
-				fireDebugEvent((IActivityNodeActivation)thisJoinPoint.getThis());
+				IActivityNodeActivation visitor = (IActivityNodeActivation) thisJoinPoint.getThis();
+				throw new DebugAssistantException(this, visitor);
 			}
 		}
 	}
-	
+
 	@Override
 	public String getAssistantID() {
 		return ASSISTANT_ID;