Просмотр исходного кода

Migrated traffic light example to sgraph model changes.
Refactoring of event based statemachine approach.

markus.muehlbrandt@itemis.de 14 лет назад
Родитель
Сommit
adc17e1bf2

+ 3 - 3
examples/org.yakindu.sct.generator.java.trafficlight/.settings/org.eclipse.core.resources.prefs

@@ -1,3 +1,3 @@
-#Wed Nov 16 11:31:56 CET 2011
-eclipse.preferences.version=1
-encoding/TrafficLightWaiting.sct=UTF-8
+#Fri Dec 09 13:24:37 CET 2011
+eclipse.preferences.version=1
+encoding/TrafficLightWaiting.sct=UTF-8

+ 7 - 7
examples/org.yakindu.sct.generator.java.trafficlight/TrafficLightWaiting.sct

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:sgraph="http://www.yakindu.org/sct/2.0.0" xmlns:stext="http://www.yakindu.org/sct/statechart/SText">
+<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:sgraph="http://www.yakindu.org/sct/sgraph/2.0.0" xmlns:stext="http://www.yakindu.org/sct/statechart/SText">
   <sgraph:Statechart xmi:id="_NPjBgBA-EeGQ0KsLDV4EFg" name="TrafficLightWaiting" expression="interface TrafficLight:&#xD;&#xA;&#x9;var red:boolean&#xD;&#xA;&#x9;var yellow:boolean&#xD;&#xA;&#x9;var green:boolean&#xD;&#xA;&#xD;&#xA;interface Pedestrian:&#xD;&#xA;&#x9;var request:boolean&#xD;&#xA;&#x9;var red:boolean&#xD;&#xA;&#x9;var green:boolean&#xD;&#xA;&#xD;&#xA;interface:&#xD;&#xA;&#x9;in event keypress1&#xD;&#xA;&#x9;in event keypress2">
     <scopes xsi:type="stext:InterfaceScope" xmi:id="_TnWbMBzuEeGEC4raFz1JbQ" name="TrafficLight">
       <declarations xsi:type="stext:VariableDefinition" xmi:id="_TnWbMRzuEeGEC4raFz1JbQ" name="red" type="boolean"/>
@@ -26,7 +26,7 @@
             <triggers xsi:type="stext:RegularEventSpec" xmi:id="_TnbTsRzuEeGEC4raFz1JbQ" event="_TnWbOhzuEeGEC4raFz1JbQ"/>
           </trigger>
         </outgoingTransitions>
-        <subRegions xmi:id="_vZz18BA_EeGQ0KsLDV4EFg" name="r1">
+        <regions xmi:id="_vZz18BA_EeGQ0KsLDV4EFg" name="r1">
           <vertices xsi:type="sgraph:State" xmi:id="_w8meYBA_EeGQ0KsLDV4EFg" expression="entry / TrafficLight.red = false; &#xD;&#xA;&#x9;TrafficLight.yellow = false;&#xD;&#xA;&#x9;TrafficLight.green = true;&#xD;&#xA;&#x9;Pedestrian.red = true;&#xD;&#xA;&#x9;Pedestrian.green = false;&#xD;&#xA;&#x9;Pedestrian.request = false;" name="StreetGreen" incomingTransitions="_pddaABBEEeGQ0KsLDV4EFg _yYuD0BBPEeGQ0KsLDV4EFg">
             <scopes xmi:id="_Tne-EBzuEeGEC4raFz1JbQ">
               <declarations xsi:type="stext:LocalReaction" xmi:id="_Tne-ERzuEeGEC4raFz1JbQ">
@@ -93,7 +93,7 @@
                 <triggers xsi:type="stext:TimeEventSpec" xmi:id="_Tn7C8RzuEeGEC4raFz1JbQ" value="7"/>
               </trigger>
             </outgoingTransitions>
-            <subRegions xmi:id="_iAKe0hBAEeGQ0KsLDV4EFg" name="r1">
+            <regions xmi:id="_iAKe0hBAEeGQ0KsLDV4EFg" name="r1">
               <vertices xsi:type="sgraph:State" xmi:id="_mjm00BBAEeGQ0KsLDV4EFg" expression="entry / &#xD;&#xA;Pedestrian.request = true;" name="waitOn" incomingTransitions="_wTHnEBBAEeGQ0KsLDV4EFg _OXpxsBBBEeGQ0KsLDV4EFg">
                 <scopes xmi:id="_Tn7qABzuEeGEC4raFz1JbQ">
                   <declarations xsi:type="stext:LocalReaction" xmi:id="_Tn7qARzuEeGEC4raFz1JbQ">
@@ -139,7 +139,7 @@
               <vertices xsi:type="sgraph:Entry" xmi:id="_pqXxcBBAEeGQ0KsLDV4EFg">
                 <outgoingTransitions xmi:id="_wTHnEBBAEeGQ0KsLDV4EFg" target="_mjm00BBAEeGQ0KsLDV4EFg"/>
               </vertices>
-            </subRegions>
+            </regions>
           </vertices>
           <vertices xsi:type="sgraph:State" xmi:id="_SKct4BBBEeGQ0KsLDV4EFg" expression="entry / TrafficLight.red = false;&#xD;&#xA;&#x9;TrafficLight.yellow = true;&#xD;&#xA;&#x9;TrafficLight.green = false;" name="StreetAttention" incomingTransitions="_LDXEgBBDEeGQ0KsLDV4EFg">
             <scopes xmi:id="_ToC-wBzuEeGEC4raFz1JbQ">
@@ -289,7 +289,7 @@
           <vertices xsi:type="sgraph:Entry" xmi:id="_xz0nABBPEeGQ0KsLDV4EFg">
             <outgoingTransitions xmi:id="_yYuD0BBPEeGQ0KsLDV4EFg" target="_w8meYBA_EeGQ0KsLDV4EFg"/>
           </vertices>
-        </subRegions>
+        </regions>
       </vertices>
       <vertices xsi:type="sgraph:State" xmi:id="_MF4mkBBFEeGQ0KsLDV4EFg" expression="entry / TrafficLight.red = false;&#xD;&#xA;&#x9;TrafficLight.green = false;&#xD;&#xA;&#x9;TrafficLight.yellow = false;&#xD;&#xA;&#x9;Pedestrian.red = false;&#xD;&#xA;&#x9;Pedestrian.green = false;" name="off" incomingTransitions="_XlIREBBFEeGQ0KsLDV4EFg">
         <scopes xmi:id="_TopbsBzuEeGEC4raFz1JbQ">
@@ -331,7 +331,7 @@
             <triggers xsi:type="stext:RegularEventSpec" xmi:id="_To1o8RzuEeGEC4raFz1JbQ" event="_TnWbOhzuEeGEC4raFz1JbQ"/>
           </trigger>
         </outgoingTransitions>
-        <subRegions xmi:id="_xHG2gBBFEeGQ0KsLDV4EFg" name="r1">
+        <regions xmi:id="_xHG2gBBFEeGQ0KsLDV4EFg" name="r1">
           <vertices xsi:type="sgraph:State" xmi:id="_BVnsgBBGEeGQ0KsLDV4EFg" expression="entry / &#xA;&#x9;TrafficLight.yellow = true;&#xA;" name="YellowOn" incomingTransitions="_EwURwBBGEeGQ0KsLDV4EFg _S4HWoBzuEeGEC4raFz1JbQ">
             <scopes xmi:id="_To4sQBzuEeGEC4raFz1JbQ">
               <declarations xsi:type="stext:LocalReaction" xmi:id="_To4sQRzuEeGEC4raFz1JbQ">
@@ -377,7 +377,7 @@
               </trigger>
             </outgoingTransitions>
           </vertices>
-        </subRegions>
+        </regions>
       </vertices>
     </regions>
   </sgraph:Statechart>

+ 72 - 0
examples/org.yakindu.sct.generator.java.trafficlight/src-gen/org/yakindu/sct/runtime/java/trafficlightwaiting/TrafficLightWaitingEventBasedStatemachine.java

@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2011 committers of YAKINDU and others.
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     committers of YAKINDU - initial API and implementation
+ */
+package org.yakindu.sct.runtime.java.trafficlightwaiting;
+
+import java.util.LinkedList;
+
+import org.yakindu.sct.runtime.java.Event;
+
+public class TrafficLightWaitingEventBasedStatemachine
+		extends
+			TrafficLightWaitingCycleBasedStatemachine {
+
+	private LinkedList<Event<? extends Enum<?>>> eventQueue;
+
+	private Thread runtimeThread;
+
+	private long cyclePeriod;
+
+	public TrafficLightWaitingEventBasedStatemachine(long cyclePeriod) {
+		eventQueue = new LinkedList<Event<? extends Enum<?>>>();
+		this.cyclePeriod = cyclePeriod;
+	}
+
+	@Override
+	protected LinkedList<Event<? extends Enum<?>>> getOccuredEvents() {
+		return eventQueue;
+	}
+
+	@Override
+	protected boolean eventOccured() {
+		return !eventQueue.isEmpty();
+	}
+
+	public void start() {
+		runtimeThread = new Thread() {
+			@Override
+			public void run() {
+				long startTime;
+				while (!isInterrupted()) {
+					startTime = System.currentTimeMillis();
+					if (eventOccured()) {
+						Event<? extends Enum<?>> event = getOccuredEvents()
+								.poll();
+						TrafficLightWaitingEventBasedStatemachine.super
+								.getOccuredEvents().add(event);
+						runCycle();
+					}
+					try {
+						Thread.sleep(cyclePeriod - System.currentTimeMillis()
+								+ startTime);
+					} catch (InterruptedException e) {
+						interrupt();
+					}
+				}
+			}
+		};
+		runtimeThread.start();
+	}
+
+	public boolean stop() {
+		runtimeThread.interrupt();
+		return runtimeThread.isAlive();
+	}
+}

+ 3 - 1
examples/org.yakindu.sct.generator.java.trafficlight/src/org/yakindu/sct/examples/java/trafficlight/CrossingDemo.java

@@ -33,7 +33,7 @@ import org.eclipse.swt.widgets.Shell;
 import org.yakindu.sct.runtime.java.TimerHandler;
 import org.yakindu.sct.runtime.java.trafficlightwaiting.TrafficLightWaitingCycleBasedStatemachine;
 
-public class CrossingDemo {
+public class CrossingDemoCycleBased {
 
 	public static void main(String[] args) {
 
@@ -62,6 +62,8 @@ public class CrossingDemo {
 		crossing.add(pl);
 		crossing.getLayoutManager().setConstraint(pl,
 				new Rectangle(50, 10, 70, 20));
+		
+		statemachine.setTimerHandler(new TimerHandler());
 
 		Thread thread = new Thread() {
 			@Override

+ 152 - 0
examples/org.yakindu.sct.generator.java.trafficlight/src/org/yakindu/sct/examples/java/trafficlight/CrossingDemoEventBased.java

@@ -0,0 +1,152 @@
+/**
+ * Copyright (c) 2011 committers of YAKINDU and others.
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ * Contributors:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.sct.examples.java.trafficlight;
+
+/**
+ * Example to show how to integrate the generated statemachine code into existing projects.
+ * 
+ * @author a.nyssen - initial API and implementation
+ * @author m.muehlbrandt - adaptions to new statemachine code.
+ */
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.LightweightSystem;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.yakindu.sct.runtime.java.TimerHandler;
+import org.yakindu.sct.runtime.java.trafficlightwaiting.TrafficLightWaitingCycleBasedStatemachine;
+import org.yakindu.sct.runtime.java.trafficlightwaiting.TrafficLightWaitingEventBasedStatemachine;
+
+public class CrossingDemoEventBased {
+
+	public static void main(String[] args) {
+
+		final TrafficLightWaitingEventBasedStatemachine statemachine = new TrafficLightWaitingEventBasedStatemachine(100);
+
+		// create display and shell
+		Display display = Display.getDefault();
+		Shell shell = new Shell(display);
+		shell.setSize(400, 400);
+		shell.setText("Traffic Light Demo");
+		GridLayout shellLayout = new GridLayout();
+		shellLayout.numColumns = 1;
+		shell.setLayout(shellLayout);
+
+		LightweightSystem lws = createLightweightsystem(shell);
+		createButtonComposite(statemachine, shell);
+
+		CrossingFigure crossing = new CrossingFigure();
+		lws.setContents(crossing);
+		final TrafficLightFigure tl = new TrafficLightFigure();
+		crossing.add(tl);
+		crossing.getLayoutManager().setConstraint(tl,
+				new Rectangle(275, 75, 35, 90));
+
+		final PedestrianLightFigure pl = new PedestrianLightFigure();
+		crossing.add(pl);
+		crossing.getLayoutManager().setConstraint(pl,
+				new Rectangle(50, 10, 70, 20));
+		
+		statemachine.setTimerHandler(new TimerHandler());
+		statemachine.enter();
+		statemachine.start();
+
+		shell.open();
+		while (!shell.isDisposed()) {
+			// update traffic lights
+			tl.setRed(statemachine.getInterfaceTrafficLight().getVarRed());
+			tl.setYellow(statemachine.getInterfaceTrafficLight().getVarYellow());
+			tl.setGreen(statemachine.getInterfaceTrafficLight().getVarGreen());
+
+			pl.setWhite(statemachine.getInterfacePedestrian().getVarRequest());
+			pl.setRed(statemachine.getInterfacePedestrian().getVarRed());
+			pl.setGreen(statemachine.getInterfacePedestrian().getVarGreen());
+
+			crossing.repaint();
+
+			if (!display.readAndDispatch()) {
+				display.sleep();
+			}
+		}
+		
+		statemachine.stop();
+		statemachine.getTimerHandler().cancel();
+	}
+
+	private static LightweightSystem createLightweightsystem(Shell shell) {
+
+		FigureCanvas canvas = new FigureCanvas(shell);
+		GridData canvasGridData = new GridData();
+		canvasGridData.horizontalAlignment = GridData.FILL;
+		canvasGridData.verticalAlignment = GridData.FILL;
+		canvasGridData.grabExcessVerticalSpace = true;
+		canvasGridData.grabExcessHorizontalSpace = true;
+		canvas.setLayoutData(canvasGridData);
+		LightweightSystem lws = new LightweightSystem(canvas);
+		return lws;
+	}
+
+	private static void createButtonComposite(
+			final TrafficLightWaitingCycleBasedStatemachine statemachine,
+			Shell shell) {
+		// create a composite to hold the buttons
+		Composite buttonComposite = new Composite(shell, SWT.NO_SCROLL);
+		GridData buttonCompositeGridData = new GridData();
+		buttonCompositeGridData.horizontalAlignment = GridData.FILL;
+		buttonCompositeGridData.grabExcessHorizontalSpace = true;
+		buttonComposite.setLayoutData(buttonCompositeGridData);
+		FillLayout buttonCompositeLayout = new FillLayout();
+		buttonCompositeLayout.type = SWT.HORIZONTAL;
+		buttonComposite.setLayout(new FillLayout());
+
+		// create a button for each KEYPRESS event
+		Button[] button = new Button[2];
+		for (int i = 0; i < 2; i++) {
+			button[i] = new Button(buttonComposite, SWT.PUSH);
+			button[i].setText("key" + (i + 1));
+			final int j = i;
+			button[i].addListener(SWT.Selection, new Listener() {
+				public void handleEvent(
+						final org.eclipse.swt.widgets.Event event) {
+
+					// Shorter call for code commented out below
+					try {
+						Class<?> interfaceClass = statemachine
+								.getDefaultInterface().getClass();
+						interfaceClass.getDeclaredMethod(
+								"raiseKeypress" + (j + 1), new Class[0])
+								.invoke(statemachine.getDefaultInterface(),
+										new Object[0]);
+					} catch (IllegalAccessException e) {
+						e.printStackTrace();
+					} catch (IllegalArgumentException e) {
+						e.printStackTrace();
+					} catch (InvocationTargetException e) {
+						e.printStackTrace();
+					} catch (NoSuchMethodException e) {
+						e.printStackTrace();
+					} catch (SecurityException e) {
+						e.printStackTrace();
+					}
+				}
+			});
+		}
+	}
+}

+ 43 - 11
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/templates/CustomEventBasedStatemachine.xpt

@@ -22,27 +22,59 @@ Contributors:
 «getLicenseHeader(entry)»
 package «getImplementationPackageName(entry)»;
 
-import java.util.Collections;
 import java.util.LinkedList;
-import java.util.Queue;
 
 import «entry.getBasePackageName()».Event;
 
 public class «getEventBasedStatemachineName()» extends «getCycleBasedStatemachineName()» {
 
-	public «getEventBasedStatemachineName()»() {
-		super(new LinkedList<Event>());
+	private LinkedList<Event<? extends Enum<?>>> eventQueue;
+	
+	private Thread runtimeThread;
+	
+	private long cyclePeriod;
+	
+	public TrafficLightWaitingEventBasedStatemachine(long cyclePeriod) {
+		eventQueue = new LinkedList<Event<? extends Enum<?>>>();
+		this.cyclePeriod = cyclePeriod;
+	}
+	
+	@Override
+	protected LinkedList<Event<? extends Enum<?>>> getOccuredEvents() {
+		return eventQueue;
+	}
+	
+	@Override
+	protected boolean eventOccured() {
+		return !eventQueue.isEmpty();
 	}
 	
-	protected Queue<Event> getOccuredEvents() {
-		return (Queue<Event>) super.getOccuredEvents();
+	public void start() {
+		runtimeThread = new Thread() {
+			@Override
+			public void run() {
+				long startTime;
+				while (!isInterrupted()) {
+					startTime = System.currentTimeMillis();
+					if (eventOccured()) {
+						Event<? extends Enum<?>> event = getOccuredEvents().poll();
+						TrafficLightWaitingEventBasedStatemachine.super.getOccuredEvents().add(event);
+						runCycle();
+					}
+					try {
+						Thread.sleep(cyclePeriod-System.currentTimeMillis()+startTime);
+					} catch (InterruptedException e) {
+						interrupt();
+					}
+				}
+			}
+		};
+		runtimeThread.start();
 	}
 	
-	public void runCycle() {
-		if (eventOccured()) {
-			Event event = getOccuredEvents().poll();
-			runCycle(Collections.singletonList(event));
-		}
+	public boolean stop() {
+		runtimeThread.interrupt();
+		return runtimeThread.isAlive();
 	}
 }
 «ENDFILE-»

+ 0 - 2
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/templates/Main.xpt

@@ -53,9 +53,7 @@ Contributors:
 	
 	«EXPAND CustomCycleBasedStatemachine::file(entry) FOR this»
 	
-	«REM»Exclude event based statemachines from generation
 	«EXPAND CustomEventBasedStatemachine::file(entry) FOR this»
-	«ENDREM»
 
 «ENDDEFINE»