summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2008-05-15 23:08:33 +0000
committerPaul Buetow <paul@buetow.org>2008-05-15 23:08:33 +0000
commitd4c1ddcc90c1e2e8660598fc36b3772d2bff6816 (patch)
tree28a0afc255e42f92adbca0d102e785301bc43a58 /sources
parent61599471a5978c1521b9c89c044ac2ce9a88c398 (diff)
1 Moved the stuff to trunk!
Diffstat (limited to 'sources')
-rw-r--r--sources/core/VSLamport.java19
-rw-r--r--sources/core/VSMessage.java56
-rw-r--r--sources/core/VSProcess.java442
-rw-r--r--sources/core/VSTask.java167
-rw-r--r--sources/core/VSTaskManager.java291
-rw-r--r--sources/editors/VSColorChooser.java36
-rw-r--r--sources/editors/VSEditor.java489
-rw-r--r--sources/editors/VSEditorFrame.java225
-rw-r--r--sources/editors/VSProcessEditor.java156
-rw-r--r--sources/editors/VSProtocolEditor.java335
-rw-r--r--sources/editors/VSSimulationEditor.java60
-rw-r--r--sources/events/ProcessCrashEvent.java10
-rw-r--r--sources/events/VSEvent.java4
-rw-r--r--sources/events/VSProcessEvent.java7
-rw-r--r--sources/prefs/VSDefaultPrefs.java178
-rw-r--r--sources/prefs/VSPrefs.java553
-rw-r--r--sources/protocols/BroadcastSturmProtocol.java47
-rw-r--r--sources/protocols/DummyProtocol.java45
-rw-r--r--sources/protocols/ExternalTimeSyncProtocol.java62
-rw-r--r--sources/protocols/InternalTimeSyncProtocol.java69
-rw-r--r--sources/protocols/PingPongProtocol.java57
-rw-r--r--sources/protocols/README10
-rw-r--r--sources/protocols/RegisteredProtocols.java78
-rw-r--r--sources/protocols/VSProtocol.java125
-rw-r--r--sources/simulator/VSAbout.java63
-rw-r--r--sources/simulator/VSLogging.java57
-rw-r--r--sources/simulator/VSMain.java34
-rw-r--r--sources/simulator/VSSimulation.java311
-rw-r--r--sources/simulator/VSSimulationPanel.java619
-rw-r--r--sources/utils/VSClassLoader.java20
-rw-r--r--sources/utils/VSFrame.java58
-rw-r--r--sources/utils/VSInfoArea.java26
-rw-r--r--sources/utils/VSRandom.java17
-rw-r--r--sources/utils/VSTools.java24
34 files changed, 4750 insertions, 0 deletions
diff --git a/sources/core/VSLamport.java b/sources/core/VSLamport.java
new file mode 100644
index 0000000..157aaae
--- /dev/null
+++ b/sources/core/VSLamport.java
@@ -0,0 +1,19 @@
+package core;
+
+public class VSLamport {
+ private long time;
+ private long lamportTime;
+
+ public VSLamport(long time, long lamportTime) {
+ this.time = time;
+ this.lamportTime = lamportTime;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public long getLamportTime() {
+ return lamportTime;
+ }
+}
diff --git a/sources/core/VSMessage.java b/sources/core/VSMessage.java
new file mode 100644
index 0000000..b3c1d31
--- /dev/null
+++ b/sources/core/VSMessage.java
@@ -0,0 +1,56 @@
+package core;
+
+import prefs.VSPrefs;
+import protocols.*;
+import events.VSEvent;
+
+public class VSMessage extends VSPrefs implements VSEvent {
+ private String protocolClassname;
+ private VSProcess sendingProcess;
+ private long messageID;
+ private static long messageCounter;
+ private long lamportTime;
+
+ public VSMessage(String protocolClassname) {
+ this.protocolClassname = protocolClassname;
+ this.messageID = ++messageCounter;
+ }
+
+ public String getProtocolName() {
+ return RegisteredProtocols.getProtocolName(getProtocolClassname());
+ }
+
+ public String getProtocolClassname() {
+ return protocolClassname;
+ }
+
+ public long getMessageID() {
+ return messageID;
+ }
+
+ public void setSendingProcess(VSProcess sendingProcess) {
+ this.sendingProcess = sendingProcess;
+ lamportTime = sendingProcess.getLamportTime();
+ }
+
+ public VSProcess getSendingProcess() {
+ return sendingProcess;
+ }
+
+ public long getLamportTime() {
+ return lamportTime;
+ }
+
+ public String toString() {
+ return "ID: " + messageID;
+ }
+
+ public String toStringFull() {
+ return toString() + "; " + super.toString();
+ }
+
+ public boolean equals(VSMessage message) {
+ return messageID == message.getMessageID();
+ }
+}
+
diff --git a/sources/core/VSProcess.java b/sources/core/VSProcess.java
new file mode 100644
index 0000000..bb65959
--- /dev/null
+++ b/sources/core/VSProcess.java
@@ -0,0 +1,442 @@
+package core;
+
+import java.awt.*;
+import java.util.*;
+
+import prefs.*;
+import protocols.*;
+import simulator.*;
+import utils.*;
+import events.*;
+
+public final class VSProcess extends VSPrefs {
+ private VSTask randomCrashTask;
+ private Color currentColor;
+ private Color tmpColor;
+ private Color crashedColor;;
+ private VSLogging logging;
+ private VSPrefs prefs;
+ private VSRandom random;
+ private VSSimulationPanel simulationPanel;
+ private boolean hasStarted;
+ private boolean isHighlighted;
+ private boolean isPaused;
+ private boolean timeModified;
+ private double clockOffset;
+ private float clockVariance;
+ private int num;
+ private int processID;
+ private long globalTime;
+ private long localTime;
+ private static int processCounter;
+ private boolean isCrashed;
+ private long lamportTime;
+ private ArrayList<VSLamport> lamportTimestamps;
+ private ArrayList<Integer> vectorTimestamps;
+
+ /* This array contains all Integer prefs of the process which should show
+ * up in the prefs menu! All keys which dont start with "sim." only show
+ * up in the extended prefs menu!
+ */
+ private static final String DEFAULT_INTEGER_VALUE_KEYS[] = {
+ "sim.process.prob.crash",
+ "sim.message.prob.outage",
+ };
+
+ /* This array contains all Long prefs of the process which should show
+ * up in the prefs menu! All keys which dont start with "sim." only show
+ * up in the extended prefs menu!
+ */
+ private static final String DEFAULT_LONG_VALUE_KEYS[] = {
+ "sim.message.sendingtime.min",
+ "sim.message.sendingtime.max",
+ };
+
+ /* This array contains all Float prefs of the process which should show
+ * up in the prefs menu! All keys which dont start with "sim." only show
+ * up in the extended prefs menu!
+ */
+ private static final String DEFAULT_FLOAT_VALUE_KEYS[] = {
+ "sim.process.clock.variance",
+ };
+
+ /* This array contains all Color prefs of the process which should show
+ * up in the prefs menu! All keys which dont start with "sim." only show
+ * up in the extended prefs menu!
+ */
+ private static final String DEFAULT_COLOR_VALUE_KEYS[] = {
+ "process.default",
+ "process.running",
+ "process.stopped",
+ "process.highlight",
+ "process.crashed",
+ };
+
+ /* This array contains all String prefs of the process which should show
+ * up in the prefs menu! All keys which dont start with "sim." only show
+ * up in the extended prefs menu!
+ */
+ private static final String DEFAULT_STRING_VALUE_KEYS[] = {
+ };
+
+ public VSProcess(VSPrefs prefs, VSSimulationPanel simulationPanel, VSLogging logging, int num) {
+ this.prefs = prefs;
+ this.simulationPanel = simulationPanel;
+ this.logging = logging;
+ this.num = num;
+ this.random = new VSRandom(processID+processCounter);
+ this.lamportTimestamps = new ArrayList<VSLamport>();
+ this.vectorTimestamps = new ArrayList<Integer>();
+ setLamportTime(0);
+
+ setObject("protocols", new ArrayList<VSProtocol>());
+
+ isPaused = true;
+ processID = ++processCounter;
+
+ /* Create the super.VSPrefs with it's default prefs */
+ fillWithDefaults();
+
+ /* Make local copys in order to have more performance */
+ clockVariance = getFloat("sim.process.clock.variance");
+ currentColor = getColor("process.default");
+
+ /* Make additional process settings editable through GUI */
+ initInteger("sim.process.id", processID,
+ prefs.getString("lang.process.id"), 1, processID + 10);
+ setLongIfUnset("sim.process.localtime", localTime, prefs.getString("lang.process.time.local"));
+
+ crashedColor = getColor("process.crashed");
+ createRandomCrashTask();
+ }
+
+ /**
+ * Called from the VSProcessEditor, after finishing editing!
+ */
+ public synchronized void updateFromVSPrefs() {
+ setClockVariance(getFloat("sim.process.clock.variance"));
+ setProcessID(getInteger("sim.process.id"));
+ setLocalTime(getLong("sim.process.localtime"));
+ crashedColor = getColor("process.crashed");
+ simulationPanel.repaint();
+ createRandomCrashTask();
+ }
+
+ /**
+ * Called from the VSProcessEditor, before starting editing!
+ */
+ public synchronized void updatePrefs() {
+ setFloat("sim.process.clock.variance", getClockVariance());
+ setInteger("sim.process.id", getProcessID());
+ setLong("sim.process.localtime", getTime());
+ }
+
+ public synchronized void syncTime(final long globalTime) {
+ final long currentGlobalTimestep = globalTime - this.globalTime;
+ this.globalTime = globalTime;
+
+ if (!isCrashed) {
+ localTime += currentGlobalTimestep;
+ clockOffset += currentGlobalTimestep * (double) clockVariance;
+ }
+
+ while (clockOffset >= 1) {
+ clockOffset -= 1;
+ ++localTime;
+ }
+
+ while (clockOffset <= -1) {
+ clockOffset += 1;
+ --localTime;
+ }
+
+ if (localTime < 0)
+ localTime = 0;
+ }
+
+ private void setCurrentColor(Color newColor) {
+ if (isHighlighted)
+ tmpColor = newColor;
+ else
+ currentColor = newColor;
+ }
+
+ public synchronized void highlightOn() {
+ tmpColor = currentColor;
+ currentColor = getColor("process.highlight");
+ isHighlighted = true;
+ }
+
+ public synchronized void highlightOff() {
+ currentColor = tmpColor;
+ isHighlighted = false;
+ }
+
+ public synchronized void reset() {
+ isPaused = true;
+ isCrashed = false;
+ localTime = 0;
+ globalTime = 0;
+ clockOffset = 0;
+ lamportTime = 0;
+ lamportTimestamps.clear();
+ vectorTimestamps.clear();
+
+ if (objectExists("protocols.registered")) {
+ Object protocolsObj = getObject("protocols.registered");
+ if (protocolsObj instanceof Vector) {
+ Vector<VSProtocol> protocols = (Vector<VSProtocol>) protocolsObj;
+ for (VSProtocol protocol : protocols)
+ protocol.reset();
+ }
+ }
+
+ setCurrentColor(getColor("process.default"));
+ createRandomCrashTask();
+ }
+
+ private void createRandomCrashTask() {
+ if (!isCrashed) {
+ VSTaskManager taskManager = simulationPanel.getTaskManager();
+ long crashTime = getARandomCrashTime();
+
+ if (randomCrashTask != null)
+ taskManager.removeTask(randomCrashTask);
+
+ if (crashTime >= 0 && crashTime >= getGlobalTime()) {
+ randomCrashTask = new VSTask(crashTime, this, new ProcessCrashEvent());
+ taskManager.addTask(randomCrashTask);
+ //System.out.println("DEBUG " + processID + " crashes at " + crashTime);
+
+ } else {
+ randomCrashTask = null;
+ }
+ }
+ }
+
+ public synchronized void addClockOffset(long add) {
+ this.clockOffset += add;
+ }
+
+ public synchronized void play() {
+ isPaused = false;
+ setCurrentColor(getColor("process.running"));
+ }
+
+ public synchronized void pause() {
+ isPaused = true;
+ setCurrentColor(getColor("process.stopped"));
+ }
+
+ public synchronized void finish() {
+ isPaused = true;
+ setCurrentColor(getColor("process.default"));
+ }
+
+ public synchronized int getProcessID() {
+ return processID;
+ }
+
+ public synchronized void setProcessID(int processID) {
+ this.processID = processID;
+ }
+
+ public synchronized Color getColor() {
+ return currentColor;
+ }
+
+ public synchronized void setLocalTime(final long localTime) {
+ if (localTime >= 0)
+ this.localTime = localTime;
+ else
+ this.localTime = 0;
+ }
+
+ public synchronized long getTime() {
+ return localTime;
+ }
+
+ public synchronized void setTime(final long time) {
+ if (time >= 0)
+ this.localTime = time;
+ else
+ this.localTime = 0;
+
+ this.timeModified = true;
+ }
+
+ public synchronized boolean isCrashed() {
+ return isCrashed;
+ }
+
+ public synchronized void isCrashed(boolean isCrashed) {
+ this.isCrashed = isCrashed;
+ }
+
+ public synchronized Color getCrashedColor() {
+ return crashedColor;
+ }
+
+ public int getNum() {
+ return num;
+ }
+
+ public synchronized boolean timeModified() {
+ return timeModified;
+ }
+
+ public synchronized void timeModified(boolean timeModified) {
+ this.timeModified = timeModified;
+ }
+
+ public synchronized long getGlobalTime() {
+ return globalTime;
+ }
+
+ public synchronized void setGlobalTime(final long globalTime) {
+ this.globalTime = globalTime >= 0 ? globalTime : 0;
+ }
+
+ public synchronized float getClockVariance() {
+ return clockVariance;
+ }
+
+ public synchronized void setClockVariance(float clockVariance) {
+ /* If negative, only allow < 1 prefs */
+ if (clockVariance < 0) {
+ int part = (int) -clockVariance;
+ if (part > 0) {
+ this.clockVariance = 0;
+ return;
+ }
+ }
+
+ this.clockVariance = clockVariance;
+ }
+
+ public synchronized long getDurationTime() {
+ final long maxDurationTime = getLong("sim.message.sendingtime.max");
+ final long minDurationTime = getLong("sim.message.sendingtime.min");
+
+ if (maxDurationTime <= minDurationTime)
+ return minDurationTime;
+
+ final int diff = (int) (maxDurationTime - minDurationTime);
+
+ /* Integer overflow */
+ if (diff <= 0)
+ return minDurationTime;
+
+ return minDurationTime + random.nextInt(diff+1);
+ }
+
+ public synchronized long getARandomMessageOutageTime(final long durationTime) {
+ /* Check if the message will have an outage or not */
+ if (random.nextInt(100) <= getInteger("sim.message.prob.outage")) {
+ /* Calculate the random outage time! */
+ final long outageTime = globalTime + random.nextLong(durationTime+1) % simulationPanel.getUntilTime();
+ return outageTime;
+ }
+
+ /* No outage */
+ return -1;
+ }
+
+ private long getARandomCrashTime() {
+ /* Check if the process will crash or not */
+ if (random.nextInt(100) <= getInteger("sim.process.prob.crash")) {
+ /* Calculate the random crash time! */
+ final long crashTime = random.nextLong(simulationPanel.getUntilTime()+1) % simulationPanel.getUntilTime();
+ return crashTime;
+ }
+
+ /* No crash */
+ return -1;
+ }
+
+ public synchronized VSTask getCrashTask() {
+ return randomCrashTask;
+ }
+
+ public synchronized boolean isPaused() {
+ return isPaused;
+ }
+
+ public synchronized long getLamportTime() {
+ return lamportTime;
+ }
+
+ public synchronized void setLamportTime(long lamportTime) {
+ this.lamportTime = lamportTime;
+ lamportTimestamps.add(new VSLamport(globalTime, lamportTime));
+ }
+
+ public synchronized VSLamport[] getLamportArray() {
+ final int size = lamportTimestamps.size();
+ final VSLamport[] arr = new VSLamport[size];
+
+ for (int i = 0; i < size; ++i)
+ arr[i] = lamportTimestamps.get(i);
+
+ return arr;
+ }
+
+ public synchronized int[] getVectorTime() {
+ final int size = vectorTimestamps.size();
+ final int[] arr = new int[size];
+
+ for (int i = 0; i < size; ++i)
+ arr[i] = vectorTimestamps.get(i);
+
+ return arr;
+ }
+
+
+ public void sendMessage(VSMessage message) {
+ logg(prefs.getString("lang.message.sent") + "; "
+ + prefs.getString("lang.protocol") + ": " + message.getProtocolName() + "; "
+ + prefs.getString("lang.message") + " " + message.toStringFull());
+ simulationPanel.sendMessage(message);
+ }
+
+ public void logg(String message) {
+ logging.logg(toString() + "; " + message, globalTime);
+ }
+
+ public void fillWithDefaults() {
+ prefs.copyIntegers(this, DEFAULT_INTEGER_VALUE_KEYS);
+ prefs.copyLongs(this, DEFAULT_LONG_VALUE_KEYS);
+ prefs.copyFloats(this, DEFAULT_FLOAT_VALUE_KEYS);
+ prefs.copyColors(this, DEFAULT_COLOR_VALUE_KEYS);
+ prefs.copyStrings(this, DEFAULT_STRING_VALUE_KEYS);
+ }
+
+ public String toString() {
+ return
+ prefs.getString("lang.process.id") + ": "
+ + getProcessID() + "; "
+ + prefs.getString("lang.process.time.local") + ": "
+ + VSTools.getTimeString(getTime())
+ + "; Lamport: " + lamportTime;
+ }
+
+ public String toStringFull() {
+ return toString() + "; paused: " + isPaused + "; crashed: " + isCrashed + "; crashTask: " + randomCrashTask;
+ }
+
+ public boolean equals(VSProcess process) {
+ return process.getNum() == getNum();
+ }
+
+ public VSSimulationPanel getSimulationPanel() {
+ return simulationPanel;
+ }
+
+ public VSPrefs getPrefs() {
+ return prefs;
+ }
+
+ public static void resetProcessCounter() {
+ processCounter = 0;
+ }
+}
diff --git a/sources/core/VSTask.java b/sources/core/VSTask.java
new file mode 100644
index 0000000..43b0265
--- /dev/null
+++ b/sources/core/VSTask.java
@@ -0,0 +1,167 @@
+package core;
+
+import prefs.VSPrefs;
+import events.*;
+import protocols.VSProtocol;
+import simulator.*;
+
+public class VSTask implements Comparable {
+ //public final static int RUN_ON_CLIENT_START = 1;
+ private long taskTime;
+ private VSEvent event;
+ private VSProcess process;
+ private VSPrefs prefs;
+ private boolean isProgrammed;
+
+ public VSTask(long taskTime, VSProcess process, VSEvent event) {
+ this.process = process;
+ this.taskTime = taskTime > 0 ? taskTime : 0;
+ this.event = event;
+ this.prefs = process.getPrefs();
+ }
+
+ public void isProgrammed(boolean isProgrammed) {
+ this.isProgrammed = isProgrammed;
+ }
+
+ public boolean isProgrammed() {
+ return isProgrammed;
+ }
+
+ public boolean isMessage() {
+ return event instanceof VSMessage;
+ }
+
+ public boolean isProtocol(VSProtocol protocol) {
+ if (event instanceof VSProtocol)
+ return ((VSProtocol) event).equals(protocol);
+
+ return false;
+ }
+
+ public boolean isGlobalTimed() {
+ if (event instanceof VSProtocol)
+ return false;
+
+ return true;
+ }
+
+ public VSProcess getProcess() {
+ return process;
+ }
+
+ public void run() {
+ if (process.isCrashed())
+ return;
+
+ if (event instanceof VSMessage) {
+ onMessageRecv();
+
+ } else if (event instanceof VSProtocol) {
+ /* Lamport time will get incremented by the VSProtocol class */
+ onProtocolStart();
+
+ } else if (event instanceof VSProcessEvent) {
+ onProcessEventStart();
+
+ } else {
+ onDummy();
+ }
+ }
+
+ private void onDummy() {
+ logg(prefs.getString("lang.process.task"));
+ }
+
+ /**
+ * If the process recv a message, check if the message's protocol is activated
+ * by the process. If yes, run the protocol on the message! If not, just logg
+ * that the process does not support this protocol! The process will ignore the
+ * message!
+ */
+ private void onMessageRecv() {
+ final VSMessage message = (VSMessage) event;
+ final String protocolName = message.getProtocolName();
+ final String protocolClassname = message.getProtocolClassname();
+
+ final long recvLamportTime = message.getLamportTime() + 1;
+ final long lamportTime = process.getLamportTime() + 1;
+
+ if (recvLamportTime > lamportTime)
+ process.setLamportTime(recvLamportTime);
+ else
+ process.setLamportTime(lamportTime);
+
+ Object protocolObj;
+
+ if (process.objectExists(protocolClassname))
+ protocolObj = process.getObject(protocolClassname);
+ else
+ protocolObj = null;
+
+ String loggVSMessage = prefs.getString("lang.message.recv")
+ + "; " + prefs.getString("lang.protocol") + ": " + protocolName
+ + "; " + prefs.getString("lang.message") + " " + message;
+
+ if (protocolObj == null) {
+ logg(loggVSMessage);
+
+ } else {
+ final VSProtocol protocol = (VSProtocol) protocolObj;
+ logg(loggVSMessage);
+ protocol.onMessageRecv(message);
+ }
+ }
+
+ private void onProtocolStart() {
+ ((VSProtocol) event).onStart();
+ }
+
+ private void onProcessEventStart() {
+ final VSProcessEvent processEvent = (VSProcessEvent) event;
+ processEvent.onStart(process);
+ /*
+ if (process.isCrashed())
+ process.setLamportTime(process.getLamportTime()-1);
+ */
+ }
+
+ public long getTaskTime() {
+ return taskTime;
+ }
+
+ public VSEvent getEvent() {
+ return event;
+ }
+
+ private void logg(String message) {
+ process.logg(message);
+ }
+
+ public int compareTo(Object object) {
+ if (object instanceof VSTask) {
+ final VSTask task = (VSTask) object;
+
+ if (taskTime < task.getTaskTime())
+ return -1;
+
+ else if (taskTime > task.getTaskTime())
+ return 1;
+ }
+
+ return 0;
+ }
+
+ public String toString() {
+ String descr = "VSTask: " + getTaskTime();
+
+ if (event instanceof VSMessage)
+ descr += (VSMessage) event;
+
+ else if (event instanceof VSProtocol)
+ descr += (VSProtocol) event;
+
+ return descr;
+ }
+}
+
diff --git a/sources/core/VSTaskManager.java b/sources/core/VSTaskManager.java
new file mode 100644
index 0000000..28f5a36
--- /dev/null
+++ b/sources/core/VSTaskManager.java
@@ -0,0 +1,291 @@
+package core;
+
+import java.util.*;
+
+import protocols.*;
+import prefs.*;
+
+public class VSTaskManager {
+ private PriorityQueue<VSTask> tasks;
+ private PriorityQueue<VSTask> globalTasks;
+ private LinkedList<VSTask> fullfilledProgrammedTasks;
+ public final static boolean PROGRAMMED_TASK = true;
+ public final static boolean NOT_PROGRAMMED_TASK = false;
+ private VSPrefs prefs;
+
+ public VSTaskManager(VSPrefs prefs) {
+ this.prefs = prefs;
+ Comparator<VSTask> comparator = createComparator();
+ this.tasks = new PriorityQueue<VSTask>(100, comparator);
+ this.globalTasks = new PriorityQueue<VSTask>(100, comparator);
+ this.fullfilledProgrammedTasks = new LinkedList<VSTask>();
+ }
+
+ private Comparator<VSTask> createComparator() {
+ return new Comparator<VSTask>() {
+ public int compare(VSTask a, VSTask b) {
+ if (a.getTaskTime() > b.getTaskTime())
+ return 1;
+
+ if (a.getTaskTime() < b.getTaskTime())
+ return -1;
+
+ return 0;
+ }
+ };
+ }
+
+ public synchronized void runVSTasks(final long step, final long offset, final long lastGlobalTime) {
+ VSTask task = null;
+ VSProcess process = null;
+ long localTime;
+ long offsetTime;
+ long taskTime;
+ long globalTime;
+ final long globalOffsetTime = lastGlobalTime + step;
+ boolean redo;
+
+ do {
+ redo = false;
+
+ /* Run tasks which have for its schedule the global time */
+ while (globalTasks.size() != 0) {
+ task = globalTasks.peek();
+ process = task.getProcess();
+ localTime = process.getTime();
+ offsetTime = localTime + step;
+ taskTime = task.getTaskTime();
+ globalTime = process.getGlobalTime();
+
+ if (globalOffsetTime < taskTime)
+ break;
+
+ globalTasks.poll();
+ redo = true;
+
+ if (process.isCrashed()) {
+ if (task.isProgrammed())
+ fullfilledProgrammedTasks.add(task);
+ continue;
+ }
+
+ if (globalOffsetTime == taskTime) {
+ process.setGlobalTime(globalOffsetTime);
+ process.setLocalTime(offsetTime);
+ process.timeModified(false);
+ task.run();
+ process.setGlobalTime(globalTime);
+ if (process.isCrashed())
+ process.addClockOffset(step);
+ if (process.timeModified())
+ process.addClockOffset(process.getTime()-offsetTime);
+ process.setLocalTime(localTime);
+
+ } else /* if (globalOffsetTime > taskTime) */ {
+ final long diff = globalOffsetTime - taskTime;
+ if (globalOffsetTime - diff < lastGlobalTime)
+ process.setGlobalTime(lastGlobalTime);
+ else
+ process.setGlobalTime(globalOffsetTime - diff);
+ process.setLocalTime(offsetTime - diff);
+ process.timeModified(false);
+ task.run();
+ process.setGlobalTime(globalTime);
+ if (process.isCrashed())
+ process.addClockOffset(step);
+ if (process.timeModified())
+ process.addClockOffset(process.getTime()-(offsetTime-diff));
+ process.setLocalTime(localTime);
+ }
+
+ if (task.isProgrammed())
+ fullfilledProgrammedTasks.add(task);
+ }
+
+ /* Run tasks which have for its schedule the local process times */
+ while (tasks.size() != 0) {
+ task = tasks.peek();
+ process = task.getProcess();
+ localTime = process.getTime();
+ offsetTime = localTime + step;
+ taskTime = task.getTaskTime();
+ globalTime = process.getGlobalTime();
+
+ if (offsetTime < taskTime)
+ break;
+
+ tasks.poll();
+ redo = true;
+
+ if (process.isCrashed()) {
+ if (task.isProgrammed())
+ fullfilledProgrammedTasks.add(task);
+ continue;
+ }
+
+ if (offsetTime == taskTime) {
+ process.setGlobalTime(globalOffsetTime);
+ process.setLocalTime(offsetTime);
+ process.timeModified(false);
+ task.run();
+ process.setGlobalTime(globalTime);
+ if (process.timeModified())
+ process.addClockOffset(process.getTime()-offsetTime);
+ process.setLocalTime(localTime);
+
+ } else /* if (offsetTime > taskTime) */ {
+ final long diff = offsetTime - taskTime;
+ if (globalOffsetTime - diff < lastGlobalTime)
+ process.setGlobalTime(lastGlobalTime);
+ else
+ process.setGlobalTime(globalOffsetTime - diff);
+ process.setLocalTime(offsetTime - diff);
+ process.timeModified(false);
+ task.run();
+ process.setGlobalTime(globalTime);
+ if (process.timeModified())
+ process.addClockOffset(process.getTime()-(offsetTime-diff));
+ process.setLocalTime(localTime);
+ }
+
+ if (task.isProgrammed())
+ fullfilledProgrammedTasks.add(task);
+ }
+
+ } while (redo);
+ }
+
+ public synchronized void reset() {
+ PriorityQueue<VSTask> tmp = tasks;
+ PriorityQueue<VSTask> tmp2 = globalTasks;
+ tasks = new PriorityQueue<VSTask>();
+ globalTasks = new PriorityQueue<VSTask>();
+
+ while (fullfilledProgrammedTasks.size() != 0) {
+ VSTask task = fullfilledProgrammedTasks.removeFirst();
+ if (task.isProgrammed())
+ insert(task);
+ }
+
+ while (tmp.size() != 0) {
+ VSTask task = tmp.poll();
+ if (task.isProgrammed())
+ insert(task);
+ }
+
+ while (tmp2.size() != 0) {
+ VSTask task = tmp2.poll();
+ if (task.isProgrammed())
+ insert(task);
+ }
+ }
+
+ private void insert(VSTask task) {
+ if (task.isGlobalTimed())
+ globalTasks.add(task);
+ else
+ tasks.add(task);
+ }
+
+ public void addTask(VSTask task) {
+ addTask(task, VSTaskManager.NOT_PROGRAMMED_TASK);
+ }
+
+ public synchronized void addTask(VSTask task, boolean isProgrammed) {
+ task.isProgrammed(isProgrammed);
+ insert(task);
+ }
+
+ public synchronized void removeTask(VSTask task) {
+ if (task.isGlobalTimed())
+ globalTasks.remove(task);
+ else
+ tasks.remove(task);
+ }
+
+ public synchronized LinkedList<VSTask> getProtocolTasks(VSProtocol protocol) {
+ LinkedList<VSTask> protocolVSTasks = new LinkedList<VSTask>();
+
+ for (VSTask task : fullfilledProgrammedTasks)
+ if (task.isProtocol(protocol))
+ protocolVSTasks.addLast(task);
+
+ for (VSTask task : globalTasks)
+ if (task.isProtocol(protocol))
+ protocolVSTasks.addLast(task);
+
+ for (VSTask task : tasks)
+ if (task.isProtocol(protocol))
+ protocolVSTasks.addLast(task);
+
+ return protocolVSTasks;
+ }
+
+ public synchronized LinkedList<VSTask> getNonProtocolTasks(VSProtocol protocol) {
+ LinkedList<VSTask> nonProtocolTasks = new LinkedList<VSTask>();
+
+ for (VSTask task : fullfilledProgrammedTasks)
+ if (!task.isProtocol(protocol))
+ nonProtocolTasks.addLast(task);
+
+ for (VSTask task : globalTasks)
+ if (!task.isProtocol(protocol))
+ nonProtocolTasks.addLast(task);
+
+ for (VSTask task : tasks)
+ if (!task.isProtocol(protocol))
+ nonProtocolTasks.addLast(task);
+
+ return nonProtocolTasks;
+ }
+
+ public synchronized void modifyProtocolTasks(VSProtocol protocol, LinkedList<VSTask> protocolVSTasks) {
+ VSProcess process = protocol.getProcess();
+ LinkedList<VSTask> nonProtocolTasks = getNonProtocolTasks(protocol);
+ //System.out.println("NON PROTO: " + nonProtocolTasks);
+ ListIterator<VSTask> iter1 = protocolVSTasks.listIterator(0);
+ ListIterator<VSTask> iter2 = nonProtocolTasks.listIterator(0);
+ long localTime = process.getTime();
+
+ fullfilledProgrammedTasks.clear();
+ globalTasks.clear();
+ tasks.clear();
+
+ for (VSTask task : nonProtocolTasks) {
+ if (task.getTaskTime() < localTime)
+ fullfilledProgrammedTasks.addLast(task);
+ else
+ insert(task);
+ }
+
+ for (VSTask task : protocolVSTasks) {
+ if (task.getTaskTime() < localTime)
+ fullfilledProgrammedTasks.addLast(task);
+ else
+ insert(task);
+ }
+ }
+
+ public String toString() {
+ final String taskManager = prefs.getString("lang.taskmanager");
+ String descr = "fullfilled: ";
+
+ for (VSTask task : fullfilledProgrammedTasks)
+ descr += task + "; ";
+
+ descr += "global: ";
+
+ for (VSTask task : globalTasks)
+ descr += task + "; ";
+
+ descr += "local: ";
+
+ for (VSTask task : tasks)
+ descr += task + "; ";
+
+ if (descr.endsWith("; "))
+ return taskManager + " (" + descr.substring(0, descr.length()-2) + ")";
+
+ return taskManager + " (" + descr + ")";
+ }
+}
diff --git a/sources/editors/VSColorChooser.java b/sources/editors/VSColorChooser.java
new file mode 100644
index 0000000..0e5ec82
--- /dev/null
+++ b/sources/editors/VSColorChooser.java
@@ -0,0 +1,36 @@
+package editors;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.colorchooser.*;
+
+import prefs.VSPrefs;
+
+public class VSColorChooser extends JPanel implements ChangeListener {
+ protected JColorChooser colorChooser;
+ private Color color;
+ private JTextField valField;
+ private VSPrefs prefs;
+
+ public VSColorChooser(VSPrefs prefs, JTextField valField) {
+ super(new BorderLayout());
+ this.prefs = prefs;
+ this.color = valField.getBackground();
+ this.valField = valField;
+
+ colorChooser = new JColorChooser(Color.yellow);
+ colorChooser.setColor(color);
+ colorChooser.getSelectionModel().addChangeListener(this);
+ colorChooser.setBorder(BorderFactory.createTitledBorder(
+ prefs.getString("lang.colorchooser2")));
+ add(colorChooser, BorderLayout.CENTER);
+ }
+
+ public void stateChanged(ChangeEvent e) {
+ Color newColor = colorChooser.getColor();
+ valField.setBackground(newColor);
+ valField.repaint();
+ }
+}
diff --git a/sources/editors/VSEditor.java b/sources/editors/VSEditor.java
new file mode 100644
index 0000000..074bfd4
--- /dev/null
+++ b/sources/editors/VSEditor.java
@@ -0,0 +1,489 @@
+package editors;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.filechooser.*;
+import java.util.*;
+import java.io.File;
+
+import simulator.*;
+import utils.*;
+import prefs.VSPrefs;
+
+abstract class VSEditor implements ActionListener {
+ protected int prefsCategory;
+ private HashMap<String,JComboBox> integerFields;
+ private HashMap<String,JTextField> colorFields;
+ private HashMap<String,JTextField> floatFields;
+ private HashMap<String,JTextField> longFields;
+ private HashMap<String,JCheckBox> booleanFields;
+ private HashMap<String,JTextField> stringFields;
+ private Vector<String> colorKeys;
+ private Vector<String> floatKeys;
+ private Vector<String> integerKeys;
+ private Vector<String> longKeys;
+ private Vector<String> booleanKeys;
+ private Vector<String> stringKeys;
+ protected JPanel buttonPanel;
+ protected JPanel editPanel;
+ protected VSPrefs prefs;
+ protected VSPrefs prefsToEdit;
+ public static final int ALL_PREFERENCES = 0;
+ public static final int SIMULATION_PREFERENCES = 1;
+ protected GridBagConstraints editPanelConstraints;
+ protected int editPanelRow;
+ protected Insets insetsTopSpaceing = new Insets(15, 0, 0, 0);
+ protected Insets insets = new Insets(0, 0, 0, 0);
+
+ public VSEditor(VSPrefs prefs, VSPrefs prefsToEdit) {
+ initialize(prefs, prefsToEdit, SIMULATION_PREFERENCES);
+ }
+
+ public VSEditor(VSPrefs prefs, VSPrefs prefsToEdit, int prefsCategory) {
+ initialize(prefs, prefsToEdit, prefsCategory);
+ }
+
+ private void initialize(VSPrefs prefs, VSPrefs prefsToEdit, int prefsCategory) {
+ this.prefs = prefs;
+ this.prefsToEdit = prefsToEdit;
+ this.prefsCategory = prefsCategory;
+
+ final String keyStartsWith = "sim.";
+ boolean reversed;
+
+ switch (prefsCategory) {
+ case SIMULATION_PREFERENCES:
+ reversed = false;
+ break;
+ default:
+ reversed = true;
+ }
+
+ colorKeys = setToSortedVector(prefsToEdit.getColorKeySet(), keyStartsWith, reversed);
+ floatKeys = setToSortedVector(prefsToEdit.getFloatKeySet(), keyStartsWith, reversed);
+ integerKeys = setToSortedVector(prefsToEdit.getIntegerKeySet(), keyStartsWith, reversed);
+ longKeys = setToSortedVector(prefsToEdit.getLongKeySet(), keyStartsWith, reversed);
+ booleanKeys = setToSortedVector(prefsToEdit.getBooleanKeySet(), keyStartsWith, reversed);
+ stringKeys = setToSortedVector(prefsToEdit.getStringKeySet(), keyStartsWith, reversed);
+
+ colorFields = new HashMap<String,JTextField>();
+ floatFields = new HashMap<String,JTextField>();
+ integerFields = new HashMap<String,JComboBox>();
+ longFields = new HashMap<String,JTextField>();
+ booleanFields = new HashMap<String,JCheckBox>();
+ stringFields = new HashMap<String,JTextField>();
+
+ //this.editPanel = createEditPanel();
+ //this.buttonPanel = createButtonPanel();
+ this.editPanel = createEditPanel();
+ this.buttonPanel = createButtonPanel();
+ }
+
+ private Vector<String> setToSortedVector(Set<String> set, String startsWith, boolean reversed) {
+ Vector<String> vector = new Vector<String>();
+
+ if (reversed) {
+ for (String elem : set)
+ if (!elem.startsWith(startsWith) && !elem.endsWith("!") && !elem.startsWith("keyevent"))
+ vector.add(elem);
+ } else {
+ for (String elem : set)
+ if (elem.startsWith(startsWith) && !elem.endsWith("!") && !elem.startsWith("keyevent"))
+ vector.add(elem);
+ }
+
+ Collections.sort(vector);
+
+ return vector;
+ }
+
+ private JPanel createButtonPanel() {
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setBackground(Color.WHITE);
+
+ JButton saveButton = new JButton(
+ prefs.getString("lang.ok"));
+ saveButton.setMnemonic(prefs.getInteger("keyevent.ok"));
+ saveButton.addActionListener(this);
+ buttonPanel.add(saveButton);
+
+ JButton resetButton = new JButton(
+ prefs.getString("lang.reset"));
+ resetButton.setMnemonic(prefs.getInteger("keyevent.reset"));
+ resetButton.addActionListener(this);
+ buttonPanel.add(resetButton);
+
+ return buttonPanel;
+ }
+
+ abstract protected void addToEditPanelFront(JPanel editPanel);
+
+ abstract protected void addToEditPanelLast(JPanel editPanel);
+
+ private JPanel createUnitPanel(Component comp, String key) {
+ JPanel unitPanel = new JPanel(new GridBagLayout());
+ unitPanel.setBackground(Color.WHITE);
+
+ String unitText = prefs.getUnit(key);
+ if (unitText == null)
+ unitText = "";
+
+ JLabel unitLabel = new JLabel(" " + unitText);
+
+ unitPanel.setLayout(new BoxLayout(unitPanel, BoxLayout.X_AXIS));
+ unitPanel.add(comp);
+ unitPanel.add(unitLabel);
+
+ return unitPanel;
+ }
+
+ private JPanel createEditPanel() {
+ JPanel editPanel = new JPanel(new GridBagLayout());
+ editPanel.setBackground(Color.WHITE);
+
+ editPanelConstraints = new GridBagConstraints();
+ editPanelConstraints.fill = GridBagConstraints.HORIZONTAL;
+ editPanelConstraints.ipady = 20;
+ editPanelConstraints.ipadx = 20;
+ editPanelRow = 0;
+
+ addToEditPanelFront(editPanel);
+
+ for (String key : integerKeys) {
+ String fullKey = VSPrefs.INTEGER_PREFIX + key;
+ String descr = prefsToEdit.getDescription(fullKey);
+
+ JLabel keyLabel = null;
+ if (descr == null)
+ keyLabel = new JLabel(fullKey);
+ else
+ keyLabel = new JLabel(descr);
+
+ editPanelConstraints.insets = insetsTopSpaceing;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(keyLabel, editPanelConstraints);
+ editPanelConstraints.insets = insets;
+
+ Integer integer = prefsToEdit.getInteger(key);
+ Integer initialSelection[] = { integer };
+ JComboBox valComboBox = new JComboBox(initialSelection);
+ VSPrefs.SettingRestriction settingRestriction = prefsToEdit.getRestriction(fullKey);
+
+ int minValue, maxValue;
+
+ if (settingRestriction != null) {
+ VSPrefs.IntegerSettingRestriction integerSettingRestriction =
+ (VSPrefs.IntegerSettingRestriction) settingRestriction;
+
+ minValue = integerSettingRestriction.getMinValue();
+ maxValue = integerSettingRestriction.getMaxValue();
+
+ } else {
+ minValue = 0;
+ maxValue = 100;
+ }
+
+ for (int i = minValue; i <= maxValue; ++i)
+ valComboBox.addItem(new Integer(i));
+
+ valComboBox.repaint();
+
+ JPanel pane = new JPanel(new BorderLayout());
+ pane.setBackground(Color.WHITE);
+ pane.add(createUnitPanel(valComboBox, fullKey), BorderLayout.WEST);
+
+ editPanelConstraints.insets = insets;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(pane, editPanelConstraints);
+ integerFields.put(key, valComboBox);
+ }
+
+ final String activated = prefs.getString("lang.activated");
+ for (String key : booleanKeys) {
+ String fullKey = VSPrefs.BOOLEAN_PREFIX + key;
+ String descr = prefsToEdit.getDescription(fullKey);
+
+ JLabel keyLabel = null;
+ if (descr == null)
+ keyLabel = new JLabel(fullKey);
+ else
+ keyLabel = new JLabel(descr);
+
+ editPanelConstraints.insets = insetsTopSpaceing;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(keyLabel, editPanelConstraints);
+
+ JCheckBox valField = new JCheckBox(activated, prefsToEdit.getBoolean(key));
+ valField.setBackground(Color.WHITE);
+
+ JPanel pane = new JPanel(new BorderLayout());
+ pane.setBackground(Color.WHITE);
+ pane.add(createUnitPanel(valField, fullKey), BorderLayout.WEST);
+
+ editPanelConstraints.insets = insets;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(pane, editPanelConstraints);
+ booleanFields.put(key, valField);
+ }
+
+
+ for (String key : longKeys) {
+ String fullKey = VSPrefs.LONG_PREFIX + key;
+ String descr = prefsToEdit.getDescription(fullKey);
+
+ JLabel keyLabel = null;
+ if (descr == null)
+ keyLabel = new JLabel(fullKey);
+ else
+ keyLabel = new JLabel(descr);
+
+ editPanelConstraints.insets = insetsTopSpaceing;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(keyLabel, editPanelConstraints);
+
+ JTextField valField = new JTextField(15);
+ valField.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyTyped(java.awt.event.KeyEvent e) {
+ JTextField valField = (JTextField)e.getSource();
+ if (valField.getText().length() >= valField.getColumns() + 10)
+ e.consume();
+ }
+ });
+ valField.setText(""+prefsToEdit.getLong(key));
+
+ JPanel pane = new JPanel(new BorderLayout());
+ pane.setBackground(Color.WHITE);
+ pane.add(createUnitPanel(valField, fullKey), BorderLayout.WEST);
+
+ editPanelConstraints.insets = insets;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(pane, editPanelConstraints);
+ longFields.put(key, valField);
+ }
+
+
+ for (String key : floatKeys) {
+ String fullKey = VSPrefs.FLOAT_PREFIX + key;
+ String descr = prefsToEdit.getDescription(fullKey);
+
+ JLabel keyLabel = null;
+ if (descr == null)
+ keyLabel = new JLabel(fullKey);
+ else
+ keyLabel = new JLabel(descr);
+
+ editPanelConstraints.insets = insetsTopSpaceing;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(keyLabel, editPanelConstraints);
+
+ JTextField valField = new JTextField(15);
+ valField.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyTyped(java.awt.event.KeyEvent e) {
+ JTextField valField = (JTextField)e.getSource();
+ if (valField.getText().length() >= valField.getColumns() + 10)
+ e.consume();
+ }
+ });
+ valField.setText(""+prefsToEdit.getFloat(key));
+
+ JPanel pane = new JPanel(new BorderLayout());
+ pane.setBackground(Color.WHITE);
+ pane.add(createUnitPanel(valField, fullKey), BorderLayout.WEST);
+
+ editPanelConstraints.insets = insets;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(pane, editPanelConstraints);
+ floatFields.put(key, valField);
+ }
+
+
+ for (String key : colorKeys) {
+ String fullKey = VSPrefs.COLOR_PREFIX + key;
+ String descr = prefsToEdit.getDescription(fullKey);
+
+ JLabel keyLabel = null;
+ if (descr == null)
+ keyLabel = new JLabel(fullKey);
+ else
+ keyLabel = new JLabel(descr);
+
+ editPanelConstraints.insets = insetsTopSpaceing;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(keyLabel, editPanelConstraints);
+
+ final JTextField valField = new JTextField(15);
+ Color color = prefsToEdit.getColor(key);
+ valField.setBackground(color);
+ valField.setEditable(false);
+ valField.addMouseListener(new MouseListener() {
+ public void mouseExited(MouseEvent e) { }
+ public void mouseReleased(MouseEvent e) { }
+ public void mouseEntered(MouseEvent e) { }
+ public void mousePressed(MouseEvent e) { }
+ public void mouseClicked(MouseEvent e) {
+ JFrame parentFrame = getFrame();
+ JFrame frame = new VSFrame(
+ prefs.getString("name") + " - " +
+ prefs.getString(
+ "lang.colorchooser"),parentFrame);
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+
+ JComponent colorChooserPane = new VSColorChooser(prefs, valField);
+ colorChooserPane.setOpaque(true);
+
+ frame.setContentPane(colorChooserPane);
+ frame.pack();
+ frame.setVisible(true);
+ }
+ });
+
+ editPanelConstraints.insets = insets;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(valField, editPanelConstraints);
+ colorFields.put(key, valField);
+ }
+
+ for (String key : stringKeys) {
+ String fullKey = VSPrefs.STRING_PREFIX + key;
+ String descr = prefsToEdit.getDescription(fullKey);
+
+ JLabel keyLabel = null;
+ if (descr == null)
+ keyLabel = new JLabel(fullKey);
+ else
+ keyLabel = new JLabel(descr);
+
+ editPanelConstraints.insets = insetsTopSpaceing;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(keyLabel, editPanelConstraints);
+
+ JTextField valField = new JTextField(15);
+ valField.addKeyListener(new java.awt.event.KeyAdapter() {
+ public void keyTyped(java.awt.event.KeyEvent e) {
+ JTextField valField = (JTextField)e.getSource();
+ if (valField.getText().length() >= valField.getColumns() + 10)
+ e.consume();
+ }
+ });
+ valField.setText(prefsToEdit.getString(key));
+
+ editPanelConstraints.insets = insets;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(createUnitPanel(valField, fullKey), editPanelConstraints);
+ stringFields.put(key, valField);
+ }
+
+ addToEditPanelLast(editPanel);
+
+ return editPanel;
+ }
+
+ protected void resetEditPanel() {
+ for (String key : integerKeys) {
+ JComboBox valComboBox = integerFields.get(key);
+ valComboBox.setSelectedIndex(0);
+ }
+
+ for (String key : booleanKeys) {
+ JCheckBox valField = booleanFields.get(key);
+ valField.setSelected(prefsToEdit.getBoolean(key));
+ }
+
+ for (String key : floatKeys) {
+ JTextField valField = floatFields.get(key);
+ valField.setText(""+prefsToEdit.getFloat(key));
+ }
+
+ for (String key : longKeys) {
+ JTextField valField = longFields.get(key);
+ valField.setText(""+prefsToEdit.getLong(key));
+ }
+
+ for (String key : colorKeys) {
+ JTextField valField = colorFields.get(key);
+ valField.setBackground(prefsToEdit.getColor(key));
+ }
+
+ for (String key : stringKeys) {
+ JTextField valField = stringFields.get(key);
+ valField.setText(prefsToEdit.getString(key));
+ }
+ }
+
+ protected void savePrefs() {
+ for (String key : integerKeys) {
+ JComboBox valComboBox = integerFields.get(key);
+ prefsToEdit.setInteger(key, (Integer) valComboBox.getSelectedItem());
+ }
+
+ for (String key : booleanKeys) {
+ JCheckBox valField = booleanFields.get(key);
+ prefsToEdit.setBoolean(key, valField.isSelected());
+ }
+
+ for (String key : floatKeys) {
+ JTextField valField = floatFields.get(key);
+
+ try {
+ Float val = Float.valueOf(valField.getText());
+ prefsToEdit.setFloat(key, val);
+
+ } catch (NumberFormatException e) {
+ valField.setText("0.0");
+ }
+ }
+
+ for (String key : longKeys) {
+ JTextField valField = longFields.get(key);
+
+ try {
+ Long val = Long.valueOf(valField.getText());
+ prefsToEdit.setLong(key, val);
+
+ } catch (NumberFormatException e) {
+ valField.setText("0");
+ }
+ }
+
+ for (String key : colorKeys) {
+ JTextField valField = colorFields.get(key);
+ prefsToEdit.setColor(key, valField.getBackground());
+ }
+
+ for (String key : stringKeys) {
+ JTextField valField = stringFields.get(key);
+ prefsToEdit.setString(key, valField.getText());
+ }
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String actionCommand = e.getActionCommand();
+
+ if (actionCommand.equals(prefs.getString("lang.ok"))) {
+ savePrefs();
+
+ } else if (actionCommand.equals(prefs.getString("lang.save"))) {
+ savePrefs();
+ prefs.saveFile();
+
+ } else if (actionCommand.equals(prefs.getString("lang.reset"))) {
+ resetEditPanel();
+
+ } else if (actionCommand.equals(prefs.getString("lang.default"))) {
+ prefs.fillWithDefaults();
+ resetEditPanel();
+ }
+ }
+
+ public JPanel getEditPanel() {
+ return editPanel;
+ }
+
+ public JPanel getButtonPanel() {
+ return buttonPanel;
+ }
+
+ abstract protected JFrame getFrame();
+}
diff --git a/sources/editors/VSEditorFrame.java b/sources/editors/VSEditorFrame.java
new file mode 100644
index 0000000..b9c14c6
--- /dev/null
+++ b/sources/editors/VSEditorFrame.java
@@ -0,0 +1,225 @@
+package editors;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.filechooser.*;
+import java.util.*;
+import java.io.File;
+
+import prefs.*;
+import simulator.*;
+import utils.*;
+
+public abstract class VSEditorFrame extends VSEditor {
+ protected VSInfoArea infoArea;
+ protected VSFrame frame;
+
+ public VSEditorFrame(VSPrefs prefs, Component relativeTo, VSPrefs prefsToEdit, String title) {
+ super(prefs, prefsToEdit);
+ frame = new VSFrame(title, relativeTo);
+ initialize();
+ }
+
+ public VSEditorFrame(VSPrefs prefs, Component relativeTo, VSPrefs prefsToEdit, String title, int prefsCategory) {
+ super(prefs, prefsToEdit, prefsCategory);
+ frame = new VSFrame(title, relativeTo);
+ initialize();
+ }
+
+ private void initialize() {
+ frame.setJMenuBar(createJMenuBar());
+ frame.setContentPane(createContentPane());
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ frame.setSize(prefs.getInteger("window.prefs.xsize"),
+ prefs.getInteger("window.prefs.ysize"));
+ frame.setResizable(false);
+ frame.setVisible(true);
+
+ /*
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent we) {
+ Window window = we.getWindow();
+ }
+ });
+ */
+ }
+
+ private Container createContentPane() {
+ Container contentPane = frame.getContentPane();
+
+ infoArea = new VSInfoArea();
+ JPanel editPanel = super.editPanel;
+ JPanel buttonPanel = createButtonPanel();
+
+ JScrollPane scrollPane = new JScrollPane(editPanel);
+ contentPane.add(infoArea, BorderLayout.NORTH);
+ contentPane.add(scrollPane, BorderLayout.CENTER);
+ contentPane.add(buttonPanel, BorderLayout.SOUTH);
+
+ return contentPane;
+ }
+
+ protected void addToEditPanelFront(JPanel editPanel) { }
+
+ protected void addToEditPanelLast(JPanel editPanel) { }
+
+ private JPanel createButtonPanel() {
+ JPanel buttonPanel = super.buttonPanel;
+
+ JButton cancelButton = new JButton(
+ prefs.getString("lang.cancel"));
+ cancelButton.setMnemonic(prefs.getInteger("keyevent.cancel"));
+ cancelButton.addActionListener(this);
+ buttonPanel.add(cancelButton);
+
+ return buttonPanel;
+ }
+
+ private JMenuBar createJMenuBar() {
+ /* File menu */
+ JMenu menuFile = new JMenu(
+ prefs.getString("lang.file"));
+ menuFile.setMnemonic(prefs.getInteger("keyevent.file"));
+ JMenuItem menuItem;
+
+ menuItem = new JMenuItem(
+ prefs.getString("lang.save"));
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.save"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ menuFile.add(menuItem);
+
+ if (!(this instanceof VSSimulationEditor))
+ menuItem.setEnabled(false);
+
+ menuItem = new JMenuItem(
+ prefs.getString("lang.saveas"));
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.saveas"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ menuFile.add(menuItem);
+
+ if (!(this instanceof VSSimulationEditor))
+ menuItem.setEnabled(false);
+
+ menuItem = new JMenuItem(
+ prefs.getString("lang.open"));
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.open"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ menuFile.add(menuItem);
+
+ if (!(this instanceof VSSimulationEditor))
+ menuItem.setEnabled(false);
+
+ menuFile.addSeparator();
+
+ menuItem = new JMenuItem(
+ prefs.getString("lang.close"));
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.close"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ menuFile.add(menuItem);
+
+ /* Edit menu */
+ JMenu menuEdit = new JMenu(
+ prefs.getString("lang.edit"));
+ menuEdit.setMnemonic(prefs.getInteger("keyevent.edit"));
+
+ menuItem = new JMenuItem(
+ prefs.getString("lang.default"));
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.default"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ menuEdit.add(menuItem);
+
+ if (!(this instanceof VSSimulationEditor))
+ menuItem.setEnabled(false);
+
+ menuEdit.addSeparator();
+
+ menuItem = new JMenuItem(prefs.getString("lang.prefs"));
+ /*
+ if (super.prefsCategory == ALL_PREFERENCES) {
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.prefs"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ }
+ */
+ menuItem.setEnabled(false);
+ menuEdit.add(menuItem);
+
+ menuItem = new JMenuItem(prefs.getString("lang.prefs.ext"));
+ if (super.prefsCategory == SIMULATION_PREFERENCES) {
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.prefs.ext"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ } else {
+ menuItem.setEnabled(false);
+ }
+ menuEdit.add(menuItem);
+
+ JMenuBar mainMenuBar = new JMenuBar();
+ mainMenuBar.add(menuFile);
+ mainMenuBar.add(menuEdit);
+
+ return mainMenuBar;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String actionCommand = e.getActionCommand();
+
+ if (actionCommand.equals(prefs.getString("lang.close"))) {
+ frame.dispose();
+
+ } else if (actionCommand.equals(prefs.getString("lang.saveas"))) {
+ JFileChooser fileChooser = new JFileChooser();
+ int ret = fileChooser.showSaveDialog(frame);
+
+ if (ret == JFileChooser.APPROVE_OPTION) {
+ File file = fileChooser.getSelectedFile();
+ savePrefs();
+ prefs.saveFile(file.getName());
+ }
+
+ } else if (actionCommand.equals(prefs.getString("lang.open"))) {
+ JFileChooser fileChooser = new JFileChooser();
+ fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
+ int ret = fileChooser.showOpenDialog(frame);
+
+ if (ret == JFileChooser.APPROVE_OPTION) {
+ File file = fileChooser.getSelectedFile();
+ prefsToEdit = prefs = VSDefaultPrefs.initialize(file.getName());
+ resetEditPanel();
+ }
+
+ } else if (actionCommand.equals(prefs.getString("lang.cancel"))) {
+ frame.dispose();
+
+ } else if (actionCommand.equals(prefs.getString("lang.prefs"))) {
+ newVSEditorInstance(prefs, prefs, VSEditor.SIMULATION_PREFERENCES);
+
+ } else if (actionCommand.equals(prefs.getString("lang.prefs.ext"))) {
+ newVSEditorInstance(prefs, prefs, VSEditor.ALL_PREFERENCES);
+
+ } else {
+ /* More action in the super class!!! */
+ super.actionPerformed(e);
+ }
+ }
+
+ public void newVSEditorInstance(VSPrefs prefs, VSPrefs prefsToEdit, int prefsCategory) { };
+
+ protected VSFrame getFrame() {
+ return frame;
+ }
+}
diff --git a/sources/editors/VSProcessEditor.java b/sources/editors/VSProcessEditor.java
new file mode 100644
index 0000000..ecd495d
--- /dev/null
+++ b/sources/editors/VSProcessEditor.java
@@ -0,0 +1,156 @@
+package editors;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import javax.swing.border.*;
+import javax.swing.filechooser.*;
+import java.util.*;
+import java.io.File;
+
+import simulator.*;
+import utils.*;
+import core.*;
+import protocols.*;
+import prefs.VSPrefs;
+
+public class VSProcessEditor extends VSEditorFrame {
+ private VSProcess process;
+
+ public VSProcessEditor(VSPrefs prefs, Component relativeTo, VSProcess process) {
+ super(prefs, relativeTo, process, prefs.getString("name") + " - "
+ + prefs.getString("lang.prefs.process"));
+
+ this.process = process;
+
+ initialize();
+ }
+
+ public VSProcessEditor(VSPrefs prefs, Component relativeTo, VSProcess process, int prefsCategory) {
+ super(prefs, relativeTo, process, prefs.getString("name") + " - "
+ + prefs.getString("lang.prefs.process"
+ + (prefsCategory == ALL_PREFERENCES ? ".ext" : "")),
+ prefsCategory);
+
+ this.process = process;
+
+ initialize();
+ }
+
+ private void initialize() {
+ super.infoArea.setText(prefs.getString("lang.prefs.process.info!"));
+ getFrame().disposeWithParent();
+ createButtonPanel();
+ }
+
+ protected void addToEditPanelFront(JPanel editPanel) {
+ super.addToEditPanelFront(editPanel);
+
+ if (prefsCategory != SIMULATION_PREFERENCES)
+ return;
+
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(new JLabel(prefs.getString("lang.protocol.editor")), editPanelConstraints);
+
+ editPanelConstraints.insets = insets;
+ editPanelConstraints.gridy = editPanelRow++;
+ JPanel protocolSelectorPanel = createProtocolSelector();
+ editPanel.add(protocolSelectorPanel, editPanelConstraints);
+
+ editPanelConstraints.insets = insetsTopSpaceing;
+ editPanelConstraints.gridy = editPanelRow++;
+ }
+
+ private JPanel createProtocolSelector() {
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.setBorder(BorderFactory.createLineBorder(Color.black));
+ Vector<String> registeredProtocols = RegisteredProtocols.getProtocolNames();
+
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+ constraints.gridx = 0;
+ constraints.gridy = 0;
+ constraints.insets = new Insets(5, 0, 5, 0);
+ constraints.ipadx = 10;
+ constraints.ipady = 10;
+ final JComboBox comboBox = new JComboBox(registeredProtocols);
+ comboBox.setBackground(Color.WHITE);
+ panel.add(comboBox, constraints);
+ constraints.gridy = 1;
+ JButton button = new JButton(prefs.getString("lang.edit"));
+ button.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ if (ae.getActionCommand().equals(prefs.getString("lang.edit"))) {
+ String protocolName = (String) comboBox.getSelectedItem();
+ String protocolClassname = RegisteredProtocols.getProtocolClassname(protocolName);
+ VSProtocol protocol = null;
+ if (process.objectExists(protocolClassname)) {
+ Object object = process.getObject(protocolClassname);
+ if (object instanceof VSProtocol)
+ protocol = (VSProtocol) process.getObject(protocolClassname);
+ else
+ return;
+ } else {
+ protocol = RegisteredProtocols.getProtocolInstanceByName(protocolName);
+ process.setObject(protocolClassname, protocol);
+ protocol.setProcess(process);
+ protocol.setVSPrefs(prefs);
+ }
+ new VSProtocolEditor(prefs, frame, protocol);
+ }
+ }
+ });
+
+ panel.add(button, constraints);
+
+ return panel;
+ }
+
+ protected void resetEditPanel() {
+ super.resetEditPanel();
+ }
+
+ protected void savePrefs() {
+ super.savePrefs();
+ }
+
+ private JPanel createButtonPanel() {
+ JPanel buttonPanel = super.buttonPanel;
+
+ JButton cancelButton = new JButton(
+ prefs.getString("lang.takeover"));
+ cancelButton.setMnemonic(prefs.getInteger("keyevent.takeover"));
+ cancelButton.addActionListener(this);
+ buttonPanel.add(cancelButton);
+
+ return buttonPanel;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String actionCommand = e.getActionCommand();
+
+ if (actionCommand.equals(prefs.getString("lang.ok"))) {
+ savePrefs();
+ process.updateFromVSPrefs();
+ frame.dispose();
+
+ } else if (actionCommand.equals(prefs.getString("lang.takeover"))) {
+ savePrefs();
+ process.updateFromVSPrefs();
+
+ } else {
+ super.actionPerformed(e);
+ }
+ }
+
+ public void newVSEditorInstance(VSPrefs prefs, VSPrefs prefsToEdit, int prefsCategory) {
+ if (prefsToEdit instanceof VSProcess) {
+ VSProcess process = (VSProcess) prefsToEdit;
+ new VSProcessEditor(prefs, frame, process, prefsCategory);
+
+ } else {
+ new VSProcessEditor(prefs, frame, process, prefsCategory);
+ }
+ }
+}
diff --git a/sources/editors/VSProtocolEditor.java b/sources/editors/VSProtocolEditor.java
new file mode 100644
index 0000000..b347498
--- /dev/null
+++ b/sources/editors/VSProtocolEditor.java
@@ -0,0 +1,335 @@
+package editors;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import javax.swing.filechooser.*;
+
+import protocols.*;
+import utils.*;
+import core.*;
+import prefs.VSPrefs;
+
+public class VSProtocolEditor extends VSEditorFrame {
+ private JCheckBox clientCheckBox;
+ private JCheckBox serverCheckBox;
+ private JComboBox clientComboBox;
+ private VSProtocol protocol;
+ private VSTaskManager taskManager;
+ private JPanel clientTaskManagerEditorPanel;
+ private JButton takeOverButton;
+ private JButton deleteButton;
+ private JTextField textField;
+
+ public VSProtocolEditor(VSPrefs prefs, Component relativeTo, VSProtocol protocol) {
+ super(prefs, relativeTo, protocol, prefs.getString("name") + " - "
+ + protocol.getProtocolName() + " " + prefs.getString("lang.editor"), ALL_PREFERENCES);
+
+ this.protocol = protocol;
+ this.taskManager = protocol.getProcess().getSimulationPanel().getTaskManager();
+
+ initialize();
+ }
+
+ private void initialize() {
+ super.getFrame().disposeWithParent();
+ super.infoArea.setText(prefs.getString("lang.prefs.protocol.info!"));
+ initializeTaskManagerEditor(clientTaskManagerEditorPanel);
+ initlializeClientServerCheckboxes();
+ createButtonPanel();
+ }
+
+ private JPanel createButtonPanel() {
+ JPanel buttonPanel = super.buttonPanel;
+
+ JButton cancelButton = new JButton(
+ prefs.getString("lang.takeover"));
+ cancelButton.setMnemonic(prefs.getInteger("keyevent.takeover"));
+ cancelButton.addActionListener(this);
+ buttonPanel.add(cancelButton);
+
+ return buttonPanel;
+ }
+
+ protected void addToEditPanelFront(JPanel editPanel) {
+ super.addToEditPanelFront(editPanel);;
+
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(new JLabel(prefs.getString("lang.protocol.tasks.activation")), editPanelConstraints);
+
+ editPanelConstraints.insets = insets;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(createClientServerCheckboxes(), editPanelConstraints);
+
+ editPanelConstraints.insets = insetsTopSpaceing;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(new JLabel(prefs.getString("lang.protocol.tasks.client")), editPanelConstraints);
+ clientComboBox = new JComboBox();
+ clientTaskManagerEditorPanel = new JPanel(new GridBagLayout());
+ editPanelConstraints.insets = insets;
+ editPanelConstraints.gridy = editPanelRow++;
+ editPanel.add(clientTaskManagerEditorPanel, editPanelConstraints);
+
+ editPanelConstraints.insets = insetsTopSpaceing;
+ editPanelConstraints.gridy = editPanelRow++;
+ }
+
+ private JPanel createClientServerCheckboxes() {
+ final String activated = prefs.getString("lang.activate");
+ final String client = prefs.getString("lang.protocol.client") + " " + activated;
+ final String server = prefs.getString("lang.protocol.server") + " " + activated;
+
+ final JPanel panel = new JPanel(new GridBagLayout());
+ panel.setBorder(BorderFactory.createLineBorder(Color.black));
+
+ int row = 0;
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+ constraints.ipady = 10;
+ constraints.ipadx = 10;
+ constraints.insets = new Insets(5, 0, 5, 0);
+ constraints.gridy = row++;
+ constraints.gridx = 0;
+ panel.add(new JLabel(client), constraints);
+
+ constraints.gridx = 1;
+ clientCheckBox = new JCheckBox();
+ clientCheckBox.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent ce) {
+ if (takeOverButton != null && textField != null) {
+ AbstractButton abstractButton = (AbstractButton) ce.getSource();
+ ButtonModel buttonModel = abstractButton.getModel();
+ takeOverButton.setEnabled(buttonModel.isSelected());
+ textField.setEnabled(buttonModel.isSelected());
+ if (!buttonModel.isSelected()) {
+ clientComboBox.setEnabled(false);
+ deleteButton.setEnabled(false);
+ } else if (clientComboBox.getItemCount() > 0) {
+ clientComboBox.setEnabled(true);
+ deleteButton.setEnabled(true);
+ }
+ }
+ }
+ });
+
+ panel.add(clientCheckBox, constraints);
+
+ constraints.gridy = row++;
+ constraints.gridx = 0;
+ panel.add(new JLabel(server), constraints);
+
+ constraints.gridx = 1;
+ serverCheckBox = new JCheckBox();
+ panel.add(serverCheckBox, constraints);
+
+ return panel;
+ }
+
+ private void initlializeClientServerCheckboxes() {
+ final String protocolName = protocol.getProtocolName();
+ final VSProcess process = protocol.getProcess();
+
+ String protocolKey = "sim."+protocolName.toLowerCase()+".client.enabled!";
+ clientCheckBox.setSelected(process.getBoolean(protocolKey));
+ protocolKey = "sim."+protocolName.toLowerCase()+".server.enabled!";
+ serverCheckBox.setSelected(process.getBoolean(protocolKey));
+
+ }
+
+ private void initializeTaskManagerEditor(JPanel panel) {
+ clientComboBox = new JComboBox();
+ deleteButton = new JButton(prefs.getString("lang.remove"));
+ takeOverButton = new JButton(prefs.getString("lang.takeover"));
+ textField = new JTextField();
+
+ panel.setBorder(BorderFactory.createLineBorder(Color.black));
+
+ int row = 0;
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+ constraints.ipady = 10;
+ constraints.ipadx = 10;
+ constraints.insets = new Insets(5, 5, 5, 5);
+
+ textField.setText("0000");
+ textField.setColumns(10);
+ constraints.gridy = row++;
+ constraints.gridx = 0;
+ panel.add(textField, constraints);
+
+ Insets insetsBackup = constraints.insets;
+ constraints.insets = new Insets(0, 0, 0, 0);
+ constraints.gridx = 1;
+ panel.add(new JLabel("ms"), constraints);
+
+ constraints.insets = insetsBackup;
+ constraints.gridx = 2;
+ panel.add(takeOverButton, constraints);
+
+ constraints.gridy = row++;
+ constraints.gridx = 0;
+ resetTaskManager();
+ clientComboBox.setBackground(Color.WHITE);
+ panel.add(clientComboBox, constraints);
+
+ constraints.gridx = 2;
+ panel.add(deleteButton, constraints);
+
+ ActionListener actionListener = new ActionListener() {
+ private boolean isRed;
+ public void actionPerformed(ActionEvent ae) {
+ if (ae.getActionCommand().equals(prefs.getString("lang.takeover"))) {
+ String textValue = textField.getText();
+ try {
+ Long longValue = Long.valueOf(textValue);
+
+ if (longValue.longValue() < 0) {
+ textField.setBackground(Color.RED);
+ isRed = true;
+ return;
+ }
+
+ clientComboBox.addItem(VSTools.getTimeString(longValue.longValue()));
+ clientComboBox.setSelectedIndex(clientComboBox.getItemCount()-1);
+ clientComboBox.setEnabled(true);
+ sortComboBox(clientComboBox);
+ deleteButton.setEnabled(true);
+
+ if (isRed) {
+ textField.setBackground(Color.WHITE);
+ isRed = false;
+ }
+ } catch (NumberFormatException e) {
+ textField.setBackground(Color.RED);
+ isRed = true;
+ }
+
+ } else if (ae.getActionCommand().equals(prefs.getString("lang.remove"))) {
+ Object[] objects = clientComboBox.getSelectedObjects();
+ for (Object object : objects)
+ clientComboBox.removeItem(object);
+ if (clientComboBox.getItemCount() == 0) {
+ clientComboBox.setEnabled(false);
+ deleteButton.setEnabled(false);
+ }
+ }
+ }
+ };
+
+ takeOverButton.addActionListener(actionListener);
+ deleteButton.addActionListener(actionListener);
+
+ clientComboBox.setEnabled(false);
+ deleteButton.setEnabled(false);
+ takeOverButton.setEnabled(false);
+ textField.setEnabled(false);
+ }
+
+ protected void resetEditPanel() {
+ super.resetEditPanel();
+
+ resetTaskManager();
+
+ final VSProcess process = protocol.getProcess();
+ final String protocolName = protocol.getProtocolName();
+ String protocolKey = "sim."+protocolName.toLowerCase()+".client.enabled!";
+ clientCheckBox.setSelected(process.getBoolean(protocolKey));
+ protocolKey = "sim."+protocolName.toLowerCase()+".server.enabled!";
+ serverCheckBox.setSelected(process.getBoolean(protocolKey));
+
+ takeOverButton.setEnabled(clientCheckBox.isSelected());
+ textField.setEnabled(clientCheckBox.isSelected());
+ if (!clientCheckBox.isSelected()) {
+ clientComboBox.setEnabled(false);
+ deleteButton.setEnabled(false);
+ }
+ }
+
+ protected void savePrefs() {
+ super.savePrefs();
+ saveTasks();
+ }
+
+ private void resetTaskManager() {
+ clientComboBox.removeAllItems();
+ LinkedList<VSTask> protocolVSTasks = taskManager.getProtocolTasks(protocol);
+
+ for (VSTask task : protocolVSTasks)
+ clientComboBox.addItem(VSTools.getTimeString(task.getTaskTime()));
+ }
+
+ private void saveTasks() {
+ LinkedList<VSTask> tasks = new LinkedList<VSTask>();
+ int numItems;
+
+ numItems = clientComboBox.getItemCount();
+ for (int i = 0; i < numItems; ++i) {
+ long taskTime = VSTools.getStringTime((String) clientComboBox.getItemAt(i));
+ VSTask task = new VSTask(taskTime, protocol.getProcess(), protocol);
+ task.isProgrammed(true);
+ tasks.addLast(task);
+ }
+
+ taskManager.modifyProtocolTasks(protocol, tasks);
+
+ final VSProcess process = protocol.getProcess();
+ final String protocolName = protocol.getProtocolName();
+ String protocolKey = "sim."+protocolName.toLowerCase()+".client.enabled!";
+ process.setBoolean(protocolKey, clientCheckBox.isSelected());
+ protocol.isClient(clientCheckBox.isSelected());
+
+ protocolKey = "sim."+protocolName.toLowerCase()+".server.enabled!";
+ process.setBoolean(protocolKey, serverCheckBox.isSelected());
+ protocol.isServer(serverCheckBox.isSelected());
+
+ Object protocolsObj = null;
+ if (process.objectExists("protocols.registered")) {
+ protocolsObj = process.getObject("protocols.registered");
+ } else {
+ protocolsObj = new Vector<VSProtocol>();
+ process.setObject("protocols.registered", protocolsObj);
+ }
+
+ if (protocolsObj instanceof Vector) {
+ Vector<VSProtocol> protocols = (Vector<VSProtocol>) protocolsObj;
+ if (!protocols.contains(protocol))
+ protocols.add(protocol);
+ }
+ }
+
+ private void sortComboBox(JComboBox comboBox) {
+ Object selected = comboBox.getSelectedItem();
+ int numItems = comboBox.getItemCount();
+ Vector<String> vector = new Vector<String>();
+
+ for (int i = 0; i < numItems; ++i) {
+ String value = (String) comboBox.getItemAt(i);
+ vector.add(value);
+ }
+
+ Collections.sort(vector);
+ comboBox.removeAllItems();
+ for (String value : vector)
+ comboBox.addItem(value);
+ comboBox.setSelectedItem(selected);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String actionCommand = e.getActionCommand();
+
+ if (actionCommand.equals(prefs.getString("lang.ok"))) {
+ savePrefs();
+ frame.dispose();
+
+ } else if (actionCommand.equals(prefs.getString("lang.takeover"))) {
+ savePrefs();
+
+ } else {
+ super.actionPerformed(e);
+ }
+ }
+}
diff --git a/sources/editors/VSSimulationEditor.java b/sources/editors/VSSimulationEditor.java
new file mode 100644
index 0000000..c455d64
--- /dev/null
+++ b/sources/editors/VSSimulationEditor.java
@@ -0,0 +1,60 @@
+package editors;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.filechooser.*;
+import java.util.*;
+import java.io.File;
+
+import simulator.*;
+import utils.*;
+import prefs.VSPrefs;
+
+public class VSSimulationEditor extends VSEditorFrame {
+ private boolean startNewVSSimulation;
+
+ public VSSimulationEditor(VSPrefs prefs, Component relativeTo) {
+ super(prefs, relativeTo, prefs, prefs.getString("name")
+ + " - " + prefs.getString("lang.prefs"));
+
+ startNewVSSimulation = true;
+ initialize();
+ }
+
+ public VSSimulationEditor(VSPrefs prefs, Component relativeTo, int prefsCategory) {
+ super(prefs, relativeTo, prefs, prefs.getString("name")
+ + " - " + prefs.getString("lang.prefs"
+ + (prefsCategory == ALL_PREFERENCES ? ".ext" : "")),
+ prefsCategory);
+
+ startNewVSSimulation = false;
+ initialize();
+ }
+
+ private void initialize() {
+ super.infoArea.setText(prefs.getString("lang.prefs.info!"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String actionCommand = e.getActionCommand();
+
+ if (actionCommand.equals(prefs.getString("lang.ok"))) {
+ super.actionPerformed(e);
+ prefsToEdit.saveFile();
+
+ frame.dispose();
+
+ if (startNewVSSimulation)
+ new VSSimulation(prefs, getFrame());
+
+ } else {
+ super.actionPerformed(e);
+ }
+ }
+
+ public void newVSEditorInstance(VSPrefs prefs, VSPrefs prefsToEdit, int prefsCategory) {
+ new VSSimulationEditor(prefs, getFrame(), prefsCategory);
+ }
+}
diff --git a/sources/events/ProcessCrashEvent.java b/sources/events/ProcessCrashEvent.java
new file mode 100644
index 0000000..0726e53
--- /dev/null
+++ b/sources/events/ProcessCrashEvent.java
@@ -0,0 +1,10 @@
+package events;
+
+import core.VSProcess;
+
+public class ProcessCrashEvent extends VSProcessEvent {
+ public void onStart(VSProcess process) {
+ process.logg("Crashed");
+ process.isCrashed(true);
+ }
+}
diff --git a/sources/events/VSEvent.java b/sources/events/VSEvent.java
new file mode 100644
index 0000000..cf5ab5b
--- /dev/null
+++ b/sources/events/VSEvent.java
@@ -0,0 +1,4 @@
+package events;
+
+public interface VSEvent {
+}
diff --git a/sources/events/VSProcessEvent.java b/sources/events/VSProcessEvent.java
new file mode 100644
index 0000000..cb651ad
--- /dev/null
+++ b/sources/events/VSProcessEvent.java
@@ -0,0 +1,7 @@
+package events;
+
+import core.VSProcess;
+
+abstract public class VSProcessEvent implements VSEvent {
+ abstract public void onStart(VSProcess process);
+}
diff --git a/sources/prefs/VSDefaultPrefs.java b/sources/prefs/VSDefaultPrefs.java
new file mode 100644
index 0000000..f46c82c
--- /dev/null
+++ b/sources/prefs/VSDefaultPrefs.java
@@ -0,0 +1,178 @@
+package prefs;
+
+import java.awt.Color;
+import java.awt.event.KeyEvent;
+import java.io.*;
+
+public class VSDefaultPrefs extends VSPrefs {
+ public static VSPrefs initialize() {
+ return initialize(VSPrefs.PREFERENCES_FILENAME);
+ }
+
+ public static VSPrefs initialize(String fileName) {
+ File file = new File(fileName);
+ VSPrefs prefs = null;
+
+ if (file.exists()) {
+ prefs = openFile(fileName);
+
+ } else {
+ prefs = new VSDefaultPrefs();
+ prefs.fillWithDefaults();
+ }
+
+ return prefs;
+ }
+
+ public void saveFile() {
+ super.saveFile(VSPrefs.PREFERENCES_FILENAME);
+ }
+
+ public void fillWithDefaults() {
+ super.clear();
+ fillDefaultColors();
+ fillDefaultFloats();
+ fillDefaultIntegers();
+ fillDefaultLongs();
+ fillDefaultStrings();
+ fillDefaultBooleans();
+ }
+
+ public void fillDefaultStrings() {
+ /* Internal prefs */
+ initString("lang.time.lamport", "Lamport");
+ initString("lang.message.sent", "Nachricht versendet");
+ initString("lang.logging.active", "Logging");
+ initString("lang.message", "Nachricht");
+ initString("lang.message.recv", "Nachricht erhalten");
+ initString("lang.about", "About");
+ initString("lang.about.info!", "Dieses Programm wurde von Paul Bütow im Rahmen der Diplomarbeit bei Prof. Dr.-Ing. Oßmann erstellt. Dieses Programm stellt noch keinesfalls eine fertige Version dar, da es sich noch in Entwicklung befindet und die Diplomarbeit erst mitte August abgeschlossen sein wird! Bei Fehlern bitte eine kurze Mail mitsamt Fehlerbeschreibung an paul@buetow.org schicken! Dieser Simulator wird später außerdem unter einer open source Linzenz (wahrscheinlich der GNU General Public License) freigegeben!");
+ initString("lang.cancel", "Abbrechen");
+ initString("lang.close", "Schliessen");
+ initString("lang.requesttime", "Requestzeit");
+ initString("lang.colorchooser", "Farbauswahl");
+ initString("lang.colorchooser2", "Bitte Farbe auswählen");
+ initString("lang.default", "Defaults");
+ initString("lang.remove", "Entfernen");
+ initString("lang.edit", "Editieren");
+ initString("lang.editor", "Editor");
+ initString("lang.activate", "aktivieren");
+ initString("lang.activated", "Aktiviert");
+ initString("lang.server", "Server");
+ initString("lang.client", "Client");
+ initString("lang.type", "Typ");
+ initString("lang.taskmanager", "Taskmanager");
+ initString("lang.protocol", "Protokoll");
+ initString("lang.protocol.editor", "Protokolleditor");
+ initString("lang.protocol.tasks.activation", "Client-/Serverprotokoll Aktivierung");
+ initString("lang.protocol.tasks.client", "Client Task-Manager (Clientanfragen)");
+ //initString("lang.protocol.tasks.server", "Server Task-Manager (onServerStart Schedule)");
+ initString("lang.protocol.client", "Clientseite");
+ initString("lang.protocol.server", "Serverseite");
+ initString("lang.file", "Datei");
+ initString("lang.new", "Neu");
+ initString("lang.ok", "OK");
+ initString("lang.actualize", "Aktualisieren");
+ initString("lang.takeover", "Übernehmen");
+ initString("lang.open", "Öffnen");
+ initString("lang.pause", "Pausieren");
+ initString("lang.prefs", "Einstellungen");
+ initString("lang.prefs.more", "Mehr Einstellungen");
+ initString("lang.prefs.ext", "Erweiterte Einstellungen");
+ initString("lang.prefs.info!", "Prozesseinstellungen können später für jeden Prozess einzelnd eingestellt werden.Die folgenden Werte sind lediglich die globalen Defaultwerte, die für neue Prozesse verwendet werden!");
+ initString("lang.prefs.protocol", "Protokolleinstellungen");
+ initString("lang.prefs.process", "Prozesseinstellungen");
+ initString("lang.prefs.process.ext", "Erweiterte Prozesseinstellungen");
+ initString("lang.prefs.process.info!", "Änderungen werden erst nach Betätigen des \"Übernehmen\" oder \"OK\" Knopfes übernommen!");
+ initString("lang.prefs.protocol.info!", "Änderungen werden erst nach Betätigen des \"Übernehmen\" oder \"OK\" Knopfes übernommen!");
+ initString("lang.process.clock.variance", "Uhrabweichung");
+ initString("lang.process.id", "PID");
+ initString("lang.process.new", "Neuer Prozess");
+ //initString("lang.process.prob.delay", "Verzögerungswahrscheinlichkeit");
+ //initString("lang.process.prob.outage", "Ausfallwahrscheinlichkeit");
+ initString("lang.process.time.local", "Lokale Zeit");
+ initString("lang.quit", "Beenden");
+ initString("lang.replay", "Wiederholen");
+ initString("lang.reset", "Reset");
+ initString("lang.save", "Speichern");
+ initString("lang.saveas", "Speichern unter");
+ initString("lang.process.task", "Prozess-Task");
+ initString("lang.simulation", "Simulation");
+ initString("lang.simulation.finished", "Simulation beendet");
+ initString("lang.simulation.new", "Neue Simulation");
+ initString("lang.simulation.paused", "Simulation pausiert");
+ initString("lang.simulation.resetted", "Simulation zurückgesetzt");
+ initString("lang.simulation.started", "Simulation gestartet");
+ initString("lang.start", "Starten");
+ initString("lang.stop", "Stoppen");
+ initString("name", "Verteilte Systeme v0.1");
+ }
+
+ public void fillDefaultIntegers() {
+ /* Simulation prefs */
+ initInteger("sim.process.num", 3, "Anzahl der Prozesse", 1, 6);
+ initIntegerUnit("sim.message.prob.outage", 5, "W'keit, dass eine Nachricht verloren geht", 0, 100, "%");
+ initIntegerUnit("sim.process.prob.crash", 5, "W'keit, dass der Prozess ausfällt", 0, 100, "%");
+ initIntegerUnit("sim.seconds", 30, "Simulationsdauer", 5, 120, "s");
+
+ /* Internal prefs */
+ initInteger("keyevent.about", KeyEvent.VK_A, null, 0, 100);
+ initInteger("keyevent.cancel", KeyEvent.VK_N, null, 0, 100);
+ initInteger("keyevent.close", KeyEvent.VK_C, null, 0, 100);
+ initInteger("keyevent.default", KeyEvent.VK_F, null, 0, 100);
+ initInteger("keyevent.edit", KeyEvent.VK_E, null, 0, 100);
+ initInteger("keyevent.file", KeyEvent.VK_D, null, 0, 100);
+ initInteger("keyevent.new", KeyEvent.VK_N, null, 0, 100);
+ initInteger("keyevent.actualize", KeyEvent.VK_A, null, 0, 100);
+ initInteger("keyevent.takeover", KeyEvent.VK_B, null, 0, 100);
+ initInteger("keyevent.ok", KeyEvent.VK_O, null, 0, 100);
+ initInteger("keyevent.open", KeyEvent.VK_O, null, 0, 100);
+ initInteger("keyevent.pause", KeyEvent.VK_P, null, 0, 100);
+ initInteger("keyevent.prefs", KeyEvent.VK_P, null, 0, 100);
+ initInteger("keyevent.prefs.ext", KeyEvent.VK_E, null, 0, 100);
+ initInteger("keyevent.quit", KeyEvent.VK_B, null, 0, 100);
+ initInteger("keyevent.replay", KeyEvent.VK_R, null, 0, 100);
+ initInteger("keyevent.reset", KeyEvent.VK_R, null, 0, 100);
+ initInteger("keyevent.save", KeyEvent.VK_S, null, 0, 100);
+ initInteger("keyevent.saveas", KeyEvent.VK_V, null, 0, 100);
+ initInteger("keyevent.simulation", KeyEvent.VK_S, null, 0, 100);
+ initInteger("keyevent.start", KeyEvent.VK_S, null, 0, 100);
+ initInteger("keyevent.stop", KeyEvent.VK_P, null, 0, 100);
+
+ initIntegerUnit("window.prefs.xsize", 400, "X-Grösse des Einstellungsfensters", 550, 3200, "px");
+ initIntegerUnit("window.prefs.ysize", 650, "Y-Grösse des Einstellungsfensters", 640, 2400, "px");
+ initIntegerUnit("window.loggsize", 350, "Y-Grösse des Loggingfensters", 100, 1000, "px");
+ initIntegerUnit("window.splitsize", 180, null, 100, 1000, "px");
+ initIntegerUnit("window.xsize", 1024, "X-Grösse des Hauptfensters", 800, 3200, "px");
+ initIntegerUnit("window.ysize", 768, "Y-Grösse des Hauptfensters", 600, 2400, "px");
+ }
+
+ public void fillDefaultFloats() {
+ /* Simulation prefs */
+ initFloat("sim.process.clock.variance", 0, "Uhrabweichung");
+ }
+
+ public void fillDefaultLongs() {
+ /* Simulation prefs */
+ initLongUnit("sim.message.sendingtime.min", 1000, "Minimale Nachrichtenübertragungszeit", "ms");
+ initLongUnit("sim.message.sendingtime.max", 5000, "Maximale Nachrichtenübertragungszeit", "ms");
+ }
+
+ public void fillDefaultColors() {
+ /* Internal prefs */
+ initColor("process.default", new Color(0x00, 0x00, 0x00));
+ initColor("process.running", new Color(0x0D, 0xD8, 0x09));
+ initColor("process.crashed", new Color(0xff, 0x00, 0x00));
+ initColor("process.highlight", new Color(0xff, 0xA5, 0x00));
+ initColor("process.line", new Color(0x00, 0x00, 0x00));
+ initColor("process.secondline", new Color(0xAA, 0xAA, 0xAA));
+ initColor("process.sepline", new Color(0xff, 0x00, 0x00));
+ initColor("process.stopped", new Color(0x00, 0x00, 0x00));
+ initColor("message.arrived", new Color(0x00, 0x85, 0xD2));
+ initColor("message.sending", new Color(0x0D, 0xD8, 0x09));
+ initColor("message.lost", new Color(0xFF, 0x00, 0x00));
+ }
+
+ public void fillDefaultBooleans() {
+ }
+}
diff --git a/sources/prefs/VSPrefs.java b/sources/prefs/VSPrefs.java
new file mode 100644
index 0000000..9da4808
--- /dev/null
+++ b/sources/prefs/VSPrefs.java
@@ -0,0 +1,553 @@
+package prefs;
+
+import java.awt.Color;
+import java.awt.event.KeyEvent;
+import java.io.*;
+import java.util.*;
+
+public abstract class VSPrefs implements Serializable {
+ public static final String BOOLEAN_PREFIX = "Boolean: ";
+ public static final String COLOR_PREFIX = "Color: ";
+ public static final String FLOAT_PREFIX = "Float: ";
+ public static final String INTEGER_PREFIX = "Integer: ";
+ public static final String LONG_PREFIX = "Long: ";
+ public static final String STRING_PREFIX = "String: ";
+ private HashMap<String,Color> colorVSPrefs;
+ private HashMap<String,Float> floatVSPrefs;
+ private HashMap<String,Integer> integerVSPrefs;
+ private HashMap<String,Long> longVSPrefs;
+ private HashMap<String,SettingRestriction> settingRestrictionPrefs;
+ private HashMap<String,String> descriptionPrefs;
+ private HashMap<String,String> stringVSPrefs;
+ private HashMap<String,Boolean> booleanVSPrefs;
+ private HashMap<String,Object> objectVSPrefs;
+ private HashMap<String,String> units;
+ private static final long serialVersionUID = 4L;
+ protected final static String PREFERENCES_FILENAME = "vs.dat";
+ private static long idCounter;
+ protected long id;
+
+ public class SettingRestriction implements Serializable {
+ }
+
+ public class IntegerSettingRestriction extends SettingRestriction {
+ private int minValue;
+ private int maxValue;
+
+ public IntegerSettingRestriction(int minValue, int maxValue) {
+ this.minValue = minValue;
+ this.maxValue = maxValue;
+ }
+
+ public int getMinValue() {
+ return minValue;
+ }
+
+ public int getMaxValue() {
+ return maxValue;
+ }
+ }
+
+ public class StringSettingRestriction extends SettingRestriction {
+ Vector<String> possibleSelections;
+
+ public StringSettingRestriction(String [] possibleSelections) {
+ this.possibleSelections = new Vector<String>();
+
+ for (String elem : possibleSelections)
+ this.possibleSelections.add(elem);
+ }
+
+ public Vector<String> getPossibleSelections() {
+ return possibleSelections;
+ }
+ }
+
+ public VSPrefs() {
+ colorVSPrefs = new HashMap<String,Color>();
+ descriptionPrefs = new HashMap<String,String>();
+ floatVSPrefs = new HashMap<String,Float>();
+ integerVSPrefs = new HashMap<String,Integer>();
+ longVSPrefs = new HashMap<String,Long>();
+ settingRestrictionPrefs = new HashMap<String,SettingRestriction>();
+ stringVSPrefs = new HashMap<String,String>();
+ booleanVSPrefs = new HashMap<String,Boolean>();
+ objectVSPrefs = new HashMap<String,Object>();
+ units = new HashMap<String,String>();
+ id = ++idCounter;
+ }
+
+ protected synchronized void clear() {
+ colorVSPrefs.clear();
+ floatVSPrefs.clear();
+ integerVSPrefs.clear();
+ longVSPrefs.clear();
+ stringVSPrefs.clear();
+ booleanVSPrefs.clear();
+ objectVSPrefs.clear();
+ descriptionPrefs.clear();
+ settingRestrictionPrefs.clear();
+ }
+
+ public synchronized Object getObject(String key) {
+ Object val = objectVSPrefs.get(key);
+
+ if (val == null) {
+ System.err.println("Fatal: No such object config value \""
+ + key + "\"");
+ System.exit(1);
+ }
+
+ return val;
+ }
+
+ public synchronized boolean objectExists(String key) {
+ return null != objectVSPrefs.get(key);
+ }
+
+ public synchronized String getString(String key) {
+ String val = stringVSPrefs.get(key);
+
+ if (val == null) {
+ System.err.println("Fatal: No such string config value \""
+ + key + "\"");
+ System.exit(1);
+ }
+
+ return val;
+ }
+
+ public synchronized Integer getIntegerObj(String key) {
+ Integer val = integerVSPrefs.get(key);
+
+ if (val == null) {
+ System.err.println("Fatal: No such integer config value \""
+ + key + "\"");
+ System.exit(1);
+ }
+
+ return val;
+ }
+
+ public int getInteger(String key) {
+ return getIntegerObj(key).intValue();
+ }
+
+ public synchronized Float getFloatObj(String key) {
+ Float val = floatVSPrefs.get(key);
+
+ if (val == null) {
+ System.err.println("Fatal: No such float config value \""
+ + key + "\"");
+ System.exit(1);
+ }
+
+ return val;
+ }
+
+ public float getFloat(String key) {
+ return getFloatObj(key).floatValue();
+ }
+
+ public synchronized Long getLongObj(String key) {
+ Long val = longVSPrefs.get(key);
+
+ if (val == null) {
+ System.err.println("Fatal: No such long config value \""
+ + key + "\"");
+ System.exit(1);
+ }
+
+ return val;
+ }
+
+ public long getLong(String key) {
+ return getLongObj(key).longValue();
+ }
+
+ public synchronized Boolean getBooleanObj(String key) {
+ Boolean val = booleanVSPrefs.get(key);
+
+ if (val == null)
+ return new Boolean(false);
+
+ return val;
+ }
+
+ public boolean getBoolean(String key) {
+ return getBooleanObj(key).booleanValue();
+ }
+
+ public synchronized Color getColor(String key) {
+ Color color = colorVSPrefs.get(key);
+
+ if (color == null) {
+ System.err.println("Fatal: No such color config value \""
+ + key + "\"");
+ System.exit(1);
+ }
+
+ return color;
+ }
+
+ public synchronized String getDescription(String key) {
+ return descriptionPrefs.get(key);
+ }
+
+ public synchronized String getUnit(String key) {
+ return units.get(key);
+ }
+
+ public synchronized SettingRestriction getRestriction(String key) {
+ return settingRestrictionPrefs.get(key);
+ }
+
+ public synchronized Set<String> getStringKeySet() {
+ return stringVSPrefs.keySet();
+ }
+
+ public synchronized Set<String> getIntegerKeySet() {
+ return integerVSPrefs.keySet();
+ }
+
+ public synchronized Set<String> getFloatKeySet() {
+ return floatVSPrefs.keySet();
+ }
+
+ public synchronized Set<String> getLongKeySet() {
+ return longVSPrefs.keySet();
+ }
+
+ public synchronized Set<String> getBooleanKeySet() {
+ return booleanVSPrefs.keySet();
+ }
+
+ public synchronized Set<String> getColorKeySet() {
+ return colorVSPrefs.keySet();
+ }
+
+ public synchronized void setObject(String key, Object val) {
+ objectVSPrefs.put(key, val);
+ }
+
+ public synchronized void setString(String key, String val) {
+ stringVSPrefs.put(key, val);
+ }
+
+ public synchronized void setInteger(String key, Integer val) {
+ integerVSPrefs.put(key, val);
+ }
+
+ public synchronized void setColor(String key, Color color) {
+ colorVSPrefs.put(key, color);
+ }
+
+ public synchronized void setInt(String key, int val) {
+ integerVSPrefs.put(key, new Integer(val));
+ }
+
+ public synchronized void setFloat(String key, float val) {
+ floatVSPrefs.put(key, new Float(val));
+ }
+
+ public synchronized void setFloat(String key, Float val) {
+ floatVSPrefs.put(key, val);
+ }
+
+ public synchronized void setLong(String key, long val) {
+ longVSPrefs.put(key, new Long(val));
+ }
+
+ public synchronized void setLong(String key, Long val) {
+ longVSPrefs.put(key, val);
+ }
+
+ public synchronized void setBoolean(String key, boolean val) {
+ booleanVSPrefs.put(key, new Boolean(val));
+ }
+
+ public synchronized void setBoolean(String key, Boolean val) {
+ booleanVSPrefs.put(key, val);
+ }
+
+ public synchronized void initString(String key, String val) {
+ if (!stringVSPrefs.containsKey(key))
+ stringVSPrefs.put(key, val);
+ }
+
+ public synchronized void initInteger(String key, Integer val) {
+ if (!integerVSPrefs.containsKey(key))
+ integerVSPrefs.put(key, val);
+ }
+
+ public void initInteger(String key, int val) {
+ initInteger(key, new Integer(val));
+ }
+
+ public synchronized void initLong(String key, Long val) {
+ if (!longVSPrefs.containsKey(key))
+ longVSPrefs.put(key, val);
+ }
+
+ public void initLong(String key, int val) {
+ initLong(key, new Long(val));
+ }
+
+ public synchronized void initFloat(String key, Float val) {
+ if (!floatVSPrefs.containsKey(key))
+ floatVSPrefs.put(key, val);
+ }
+
+ public void initFloat(String key, float val) {
+ initFloat(key, new Float(val));
+ }
+
+ public synchronized void setLongIfUnset(String key, Long val) {
+ if (!longVSPrefs.containsKey(key))
+ longVSPrefs.put(key, val);
+ }
+
+ public void setLongIfUnset(String key, long val) {
+ setLongIfUnset(key, new Long(val));
+ }
+
+ public synchronized void initBoolean(String key, Boolean val) {
+ if (!booleanVSPrefs.containsKey(key))
+ booleanVSPrefs.put(key, val);
+ }
+
+ public void initBoolean(String key, boolean val) {
+ initBoolean(key, new Boolean(val));
+ }
+
+ public synchronized void initColor(String key, Color color) {
+ if (!colorVSPrefs.containsKey(key))
+ colorVSPrefs.put(key, color);
+ }
+
+ public synchronized void setDescriptionIfUnset(String key, String descr) {
+ if (descr == null || descriptionPrefs.containsKey(key))
+ return;
+ descriptionPrefs.put(key, descr);
+ }
+
+ public synchronized void setRestriction(String key, SettingRestriction settingRestriction) {
+ settingRestrictionPrefs.put(key, settingRestriction);
+ }
+
+ public synchronized void setUnit(String key, String unit) {
+ units.put(key, unit);
+ }
+
+ public void initString(String key, String val, String descr) {
+ initString(key, val);
+ setDescriptionIfUnset(STRING_PREFIX + key, descr);
+ }
+
+ public void setLongIfUnset(String key, long val, String descr) {
+ setLongIfUnset(key, val);
+ setDescriptionIfUnset(LONG_PREFIX + key, descr);
+ }
+
+ public void initBoolean(String key, boolean val, String descr) {
+ initBoolean(key, val);
+ setDescriptionIfUnset(BOOLEAN_PREFIX + key, descr);
+ }
+
+ public void initBooleanUnit(String key, boolean val, String descr, String unit) {
+ initBoolean(key, val, descr);
+ setUnit(BOOLEAN_PREFIX + key, unit);
+ }
+
+ public void initInteger(String key, Integer val, String descr, IntegerSettingRestriction r) {
+ initInteger(key, val);
+ setDescriptionIfUnset(INTEGER_PREFIX + key, descr);
+ setRestriction(INTEGER_PREFIX + key, r);
+ }
+
+ public void initInteger(String key, Integer val, String descr, int minValue, int maxValue) {
+ initInteger(key, val, descr, new IntegerSettingRestriction(minValue, maxValue));
+ }
+
+ public void initInteger(String key, int val, String descr, IntegerSettingRestriction r) {
+ initInteger(key, new Integer(val), descr, r);
+ }
+
+ public void initInteger(String key, int val, String descr, int minValue, int maxValue) {
+ initInteger(key, new Integer(val), descr, minValue, maxValue);
+ }
+
+ public void initIntegerUnit(String key, int val, String descr, int minValue, int maxValue, String unit) {
+ initInteger(key, new Integer(val), descr, minValue, maxValue);
+ setUnit(INTEGER_PREFIX + key, unit);
+ }
+
+ public void initLong(String key, Long val, String descr) {
+ initLong(key, val);
+ setDescriptionIfUnset(LONG_PREFIX + key, descr);
+ }
+
+ public void initLong(String key, int val, String descr) {
+ initLong(key, new Long(val), descr);
+ }
+
+ public void initLongUnit(String key, int val, String descr, String unit) {
+ initLong(key, new Long(val), descr);
+ setUnit(LONG_PREFIX + key, unit);
+ }
+
+ public void initFloat(String key, Float val, String descr) {
+ initFloat(key, val);
+ setDescriptionIfUnset(FLOAT_PREFIX + key, descr);
+ }
+
+ public void initFloat(String key, float val, String descr) {
+ initFloat(key, new Float(val), descr);
+ }
+
+ public void initFloatUnit(String key, float val, String descr, String unit) {
+ initFloat(key, new Float(val), descr);
+ setUnit(FLOAT_PREFIX + key, unit);
+ }
+
+
+ public void initColor(String key, Color val, String descr) {
+ initColor(key, val);
+ setDescriptionIfUnset(COLOR_PREFIX + key, descr);
+ }
+
+ public void fillDefaultStrings() {}
+ public void fillDefaultIntegers() {}
+ public void fillDefaultFloats() {}
+ public void fillDefaultColors() {}
+ public void fillDefaultBooleans() {}
+ public void fillWithDefaults() {}
+
+ public synchronized void writeObject(ObjectOutputStream objectOutputStream)
+ throws IOException {
+ objectOutputStream.writeObject(booleanVSPrefs);
+ objectOutputStream.writeObject(colorVSPrefs);
+ objectOutputStream.writeObject(floatVSPrefs);
+ objectOutputStream.writeObject(integerVSPrefs);
+ objectOutputStream.writeObject(longVSPrefs);
+ objectOutputStream.writeObject(stringVSPrefs);
+ objectOutputStream.writeObject(units);
+ }
+
+ public synchronized void readObject(ObjectInputStream objectInputStream)
+ throws IOException, ClassNotFoundException {
+ booleanVSPrefs = (HashMap<String,Boolean>) objectInputStream.readObject();
+ colorVSPrefs = (HashMap<String,Color>) objectInputStream.readObject();
+ descriptionPrefs = new HashMap<String,String>();
+ floatVSPrefs = (HashMap<String,Float>) objectInputStream.readObject();
+ integerVSPrefs = (HashMap<String,Integer>) objectInputStream.readObject();
+ longVSPrefs = (HashMap<String,Long>) objectInputStream.readObject();
+ settingRestrictionPrefs = new HashMap<String,SettingRestriction>();
+ stringVSPrefs = (HashMap<String,String>) objectInputStream.readObject();
+ units = (HashMap<String,String>) objectInputStream.readObject();
+ }
+
+ public void saveFile(String filename) {
+ //System.out.println("SAVE FILE " + filename);
+ try {
+ FileOutputStream fileOutputStream = new FileOutputStream(filename);
+ ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
+ objectOutputStream.writeObject(this);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void saveFile() { };
+
+ public static VSPrefs openFile(String filename) {
+ VSPrefs prefs = null;
+ //System.out.println("OPEN FILE " + filename);
+
+ try {
+ FileInputStream fileInputStream = new FileInputStream(filename);
+ ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
+ prefs = (VSPrefs) objectInputStream.readObject();
+
+ prefs.fillDefaultStrings();
+ prefs.fillDefaultIntegers();
+ prefs.fillDefaultFloats();
+ prefs.fillDefaultColors();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return prefs;
+ }
+
+ public void copyIntegers(VSPrefs copyInto, String[] keys) {
+ for (String key : keys)
+ copyInto.initInteger(key, getInteger(key), getDescription(INTEGER_PREFIX + key),
+ (IntegerSettingRestriction) getRestriction(INTEGER_PREFIX + key));
+ }
+
+ public void copyLongs(VSPrefs copyInto, String[] keys) {
+ for (String key : keys)
+ copyInto.initLong(key, getLong(key), getDescription(LONG_PREFIX + key));
+ }
+
+ public void copyFloats(VSPrefs copyInto, String[] keys) {
+ for (String key : keys)
+ copyInto.initFloat(key, getFloat(key), getDescription(FLOAT_PREFIX + key));
+ }
+
+ public void copyStrings(VSPrefs copyInto, String[] keys) {
+ for (String key : keys)
+ copyInto.initString(key, getString(key), getDescription(STRING_PREFIX + key));
+ }
+
+ public void copyColors(VSPrefs copyInto, String[] keys) {
+ for (String key : keys)
+ copyInto.initColor(key, getColor(key), getDescription(COLOR_PREFIX + key));
+ }
+
+ public String toString() {
+ String descr = "";
+
+ Set<String> set = null;
+
+ set = getIntegerKeySet();
+ if (set.size() > 0) {
+ descr += INTEGER_PREFIX;
+ for (String key : set)
+ descr += key + "=" + getInteger(key) + "; ";
+ }
+
+ set = getFloatKeySet();
+ if (set.size() > 0) {
+ descr += FLOAT_PREFIX;
+ for (String key : set)
+ descr += key + "=" + getFloat(key) + "; ";
+ }
+
+ set = getBooleanKeySet();
+ if (set.size() > 0) {
+ descr += BOOLEAN_PREFIX;
+ for (String key : set)
+ descr += key + "=" + getBoolean(key) + "; ";
+ }
+
+ set = getStringKeySet();
+ if (set.size() > 0) {
+ descr += STRING_PREFIX;
+ for (String key : set)
+ descr += key + "=" + getString(key) + "; ";
+ }
+
+ if (descr.endsWith("; "))
+ return descr.substring(0, descr.length() - 2);
+
+ return descr;
+ }
+
+ public long getID() {
+ return id;
+ }
+}
diff --git a/sources/protocols/BroadcastSturmProtocol.java b/sources/protocols/BroadcastSturmProtocol.java
new file mode 100644
index 0000000..3940e5f
--- /dev/null
+++ b/sources/protocols/BroadcastSturmProtocol.java
@@ -0,0 +1,47 @@
+package protocols;
+
+import java.util.ArrayList;
+
+import prefs.VSPrefs;
+import core.VSMessage;
+
+public class BroadcastSturmProtocol extends VSProtocol {
+ private ArrayList<VSMessage> sentMessages;
+ private static int broadcastCount;
+
+ public BroadcastSturmProtocol() {
+ setProtocolClassname(getClass().toString());
+ sentMessages = new ArrayList<VSMessage>();
+ }
+
+ protected void onClientReset() {
+ }
+
+ protected void onClientStart() {
+ VSMessage message = new VSMessage(getProtocolClassname());
+ message.setInteger("Broadcast", broadcastCount++);
+ sentMessages.add(message);
+ sendMessage(message);
+ }
+
+ protected void onClientRecv(VSMessage recvMessage) {
+ }
+
+ protected void onServerReset() {
+ sentMessages.clear();
+ }
+
+ protected void onServerRecv(VSMessage recvMessage) {
+ if (!sentMessages.contains(recvMessage)) {
+ VSMessage message = new VSMessage(getProtocolClassname());
+ message.setInteger("Broadcast", recvMessage.getInteger("Broadcast"));
+
+ sentMessages.add(message);
+ sendMessage(message);
+ }
+ }
+
+ public String toString() {
+ return super.toString();
+ }
+}
diff --git a/sources/protocols/DummyProtocol.java b/sources/protocols/DummyProtocol.java
new file mode 100644
index 0000000..8c9009c
--- /dev/null
+++ b/sources/protocols/DummyProtocol.java
@@ -0,0 +1,45 @@
+package protocols;
+
+import core.VSMessage;
+
+public class DummyProtocol extends VSProtocol {
+ public DummyProtocol() {
+ setProtocolClassname(getClass().toString());
+ }
+
+ protected void onClientReset() {
+ logg("onClientReset()");
+ }
+
+ protected void onClientStart() {
+ logg("onClientStart()");
+
+ VSMessage message = new VSMessage(getProtocolClassname());
+ message.setString("Greeting", "Hello World!");
+ message.setInteger("A number", 1);
+ message.setBoolean("A boolean", true);
+ message.setFloat("A float", 1.2f);
+ sendMessage(message);
+ }
+
+ protected void onClientRecv(VSMessage recvMessage) {
+ logg("onClientRecv("+recvMessage+")");
+
+ String s = recvMessage.getString("Greeting");
+ int n = recvMessage.getInteger("A number");
+ boolean b = recvMessage.getBoolean("A boolean");
+ float f = recvMessage.getFloat("A float");
+ }
+
+ protected void onServerReset() {
+ logg("onClientReset()");
+ }
+
+ protected void onServerRecv(VSMessage recvMessage) {
+ logg("onServerRecv("+recvMessage+")");
+ }
+
+ public String toString() {
+ return super.toString() + "; Dummy Test";
+ }
+}
diff --git a/sources/protocols/ExternalTimeSyncProtocol.java b/sources/protocols/ExternalTimeSyncProtocol.java
new file mode 100644
index 0000000..33a60ad
--- /dev/null
+++ b/sources/protocols/ExternalTimeSyncProtocol.java
@@ -0,0 +1,62 @@
+package protocols;
+
+import prefs.VSPrefs;
+import core.VSMessage;
+
+public class ExternalTimeSyncProtocol extends VSProtocol {
+ private long requestTime;
+ private boolean waitingForResponse;
+
+ public ExternalTimeSyncProtocol() {
+ setProtocolClassname(getClass().toString());
+ }
+
+ protected void onClientReset() {
+ }
+
+ protected void onClientStart() {
+ requestTime = process.getTime();
+ waitingForResponse = true;
+
+ /* Multicast message to all processes */
+ VSMessage message = new VSMessage(getProtocolClassname());
+ message.setBoolean("isClientRequest", true);
+ sendMessage(message);
+ }
+
+ protected void onClientRecv(VSMessage recvMessage) {
+ if (!recvMessage.getBoolean("isServerResponse"))
+ return;
+
+ if (waitingForResponse)
+ waitingForResponse = false;
+ else
+ return;
+
+ long recvTime = process.getTime();
+ long roundTripTime = recvTime - requestTime;
+ long serverTime = recvMessage.getLong("time");
+ long newTime = serverTime + (long) (roundTripTime / 2);
+
+ logg("Server Zeit: " + serverTime + "; RTT: " + roundTripTime + "; Alte Zeit: " + recvTime + "; Neue Zeit: " + newTime + "; Offset: " + (newTime - recvTime));
+ process.setTime(newTime);
+ }
+
+ protected void onServerReset() {
+ }
+
+ protected void onServerRecv(VSMessage recvMessage) {
+ if (!recvMessage.getBoolean("isClientRequest"))
+ return;
+
+ /* Multicast message to all processes */
+ VSMessage message = new VSMessage(getProtocolClassname());
+ message.setLong("time", process.getTime());
+ message.setBoolean("isServerResponse", true);
+ sendMessage(message);
+ }
+
+ public String toString() {
+ return super.toString(); //+ "; " + prefs.getString("lang.requesttime") + ": " + requestTime;
+ }
+}
diff --git a/sources/protocols/InternalTimeSyncProtocol.java b/sources/protocols/InternalTimeSyncProtocol.java
new file mode 100644
index 0000000..48b57e0
--- /dev/null
+++ b/sources/protocols/InternalTimeSyncProtocol.java
@@ -0,0 +1,69 @@
+package protocols;
+
+import prefs.VSPrefs;
+import core.VSMessage;
+
+public class InternalTimeSyncProtocol extends VSProtocol {
+ private boolean waitingForResponse;
+
+ public InternalTimeSyncProtocol() {
+ setProtocolClassname(getClass().toString());
+
+ /* Those prefs are editable through the VSProtocol VSEditor GUI. t_min and t_max in milliseconds */
+ setLong("t_min", 1000);
+ setLong("t_max", 5000);
+ }
+
+ protected void onClientReset() {
+ }
+
+ protected void onClientStart() {
+ waitingForResponse = true;
+
+ /* Multicast message to all processes */
+ VSMessage message = new VSMessage(getProtocolClassname());
+ message.setBoolean("isClientRequest", true);
+ sendMessage(message);
+ }
+
+ protected void onClientRecv(VSMessage recvMessage) {
+ /* Ignore all protocol messages which are not a response message, e.g. itself */
+ if (!recvMessage.getBoolean("isServerResponse"))
+ return;
+
+ if (waitingForResponse)
+ waitingForResponse = false;
+ else
+ return;
+
+ long tMax = getLong("t_max");
+ long tMin = getLong("t_min");
+ long serverTime = recvMessage.getLong("time");
+ long newTime = serverTime + (long) ((tMax + tMin) / 2 );
+
+ logg("Server Zeit: " + serverTime + "; (t_min,t_max): (" + tMin + "," + tMax
+ + "); Alte Zeit: " + process.getTime() + "; Neue Zeit: " + newTime
+ + "; Offset: " + (process.getTime() - newTime));
+
+ process.setTime(newTime);
+ }
+
+ protected void onServerReset() {
+ }
+
+ protected void onServerRecv(VSMessage recvMessage) {
+ /* Ignore all protocol messages which are not a request message, e.g. itself */
+ if (!recvMessage.getBoolean("isClientRequest"))
+ return;
+
+ /* Multicast message to all processes */
+ VSMessage message = new VSMessage(getProtocolClassname());
+ message.setLong("time", process.getTime());
+ message.setBoolean("isServerResponse", true);
+ sendMessage(message);
+ }
+
+ public String toString() {
+ return super.toString();
+ }
+}
diff --git a/sources/protocols/PingPongProtocol.java b/sources/protocols/PingPongProtocol.java
new file mode 100644
index 0000000..6244b9a
--- /dev/null
+++ b/sources/protocols/PingPongProtocol.java
@@ -0,0 +1,57 @@
+package protocols;
+
+import prefs.VSPrefs;
+import core.VSMessage;
+
+public class PingPongProtocol extends VSProtocol {
+ private int clientCounter;
+ private int serverCounter;
+
+ public PingPongProtocol() {
+ setProtocolClassname(getClass().toString());
+ }
+
+ protected void onClientReset() {
+ clientCounter = 0;
+ }
+
+ protected void onClientStart() {
+
+ VSMessage message = new VSMessage(getProtocolClassname());
+ message.setBoolean("fromClient", true);
+ message.setInteger("counter", ++clientCounter);
+ sendMessage(message);
+ }
+
+ protected void onClientRecv(VSMessage recvMessage) {
+ if (!recvMessage.getBoolean("fromServer"))
+ return;
+
+ logg("message: " + recvMessage.getInteger("counter"));
+
+ VSMessage message = new VSMessage(getProtocolClassname());
+ message.setBoolean("fromClient", true);
+ message.setInteger("counter", ++clientCounter);
+ sendMessage(message);
+ }
+
+ protected void onServerReset() {
+ serverCounter = 0;
+ }
+
+ protected void onServerRecv(VSMessage recvMessage) {
+ if (!recvMessage.getBoolean("fromClient"))
+ return;
+
+ logg("message: " + recvMessage.getInteger("counter"));
+
+ VSMessage message = new VSMessage(getProtocolClassname());
+ message.setBoolean("fromServer", true);
+ message.setInteger("counter", ++serverCounter);
+ sendMessage(message);
+ }
+
+ public String toString() {
+ return super.toString();
+ }
+}
diff --git a/sources/protocols/README b/sources/protocols/README
new file mode 100644
index 0000000..3bf4f6d
--- /dev/null
+++ b/sources/protocols/README
@@ -0,0 +1,10 @@
+How to add a new protocol:
+
+1. Copy the file DummyProtocol.java into YourOwnNiceProtocol.java
+
+2. Edit YourOwnNiceProtocol.java and replace the classname!
+
+3. Edit the initialize method of RegisteredProtocols.java and add the classname
+of your protocol. E.g.: "org.buetow.vs.protocols.YourOwnNiceProtocol"
+
+
diff --git a/sources/protocols/RegisteredProtocols.java b/sources/protocols/RegisteredProtocols.java
new file mode 100644
index 0000000..542d686
--- /dev/null
+++ b/sources/protocols/RegisteredProtocols.java
@@ -0,0 +1,78 @@
+package protocols;
+
+import java.util.*;
+
+import prefs.*;
+import core.*;
+import utils.*;
+
+public final class RegisteredProtocols {
+ private static HashMap<String,String> protocolClassnames;
+ private static HashMap<String,String> protocolNames;
+ private static VSPrefs prefs;
+
+ public static void initialize(VSPrefs prefs_) {
+ prefs = prefs_;
+ protocolNames = new HashMap<String, String>();
+ protocolClassnames = new HashMap<String, String>();
+
+ registerProtocol("protocols.DummyProtocol");
+ registerProtocol("protocols.PingPongProtocol");
+ registerProtocol("protocols.ExternalTimeSyncProtocol");
+ registerProtocol("protocols.InternalTimeSyncProtocol");
+ registerProtocol("protocols.BroadcastSturmProtocol");
+ }
+
+ public static Vector<String> getProtocolNames() {
+ Set<String> set = protocolClassnames.keySet();
+ Vector<String> vector = new Vector<String>();
+
+ for (String protocolName : set)
+ vector.add(protocolName);
+
+ Collections.sort(vector);
+
+ return vector;
+ }
+
+ public static String getProtocolClassname(String protocolName) {
+ return protocolClassnames.get(protocolName);
+ }
+
+ public static String getProtocolName(String protocolClassname) {
+ return protocolNames.get(protocolClassname);
+ }
+
+ public static VSProtocol getProtocolInstanceByName(String protocolName) {
+ final String protocolClassname = protocolClassnames.get(protocolName);
+ final Object protocolObj = new VSClassLoader().newInstance(protocolClassname);
+
+ if (protocolObj instanceof VSProtocol)
+ return (VSProtocol) protocolObj;
+
+ return null;
+ }
+
+ public static void registerProtocol(String protocolClassname) {
+ int index = protocolClassname.lastIndexOf('.');
+
+ if (index < 0) {
+ protocolNames.put(protocolClassname, protocolClassname);
+ protocolClassnames.put(protocolClassname, protocolClassname);
+ return;
+ }
+
+ String protocolName = protocolClassname.substring(index + 1);
+ index = protocolName.lastIndexOf("Protocol");
+
+ if (index < 0 || index != protocolName.length() - 8) {
+ protocolNames.put(protocolClassname, protocolName);
+ protocolClassnames.put(protocolName, protocolClassname);
+ return;
+ }
+
+ protocolName = protocolName.substring(0, index);
+ protocolNames.put(protocolClassname, protocolName);
+ protocolClassnames.put(protocolName, protocolClassname);
+ }
+}
diff --git a/sources/protocols/VSProtocol.java b/sources/protocols/VSProtocol.java
new file mode 100644
index 0000000..b66f034
--- /dev/null
+++ b/sources/protocols/VSProtocol.java
@@ -0,0 +1,125 @@
+package protocols;
+
+import prefs.VSPrefs;
+import events.VSEvent;
+import core.*;
+
+abstract public class VSProtocol extends VSPrefs implements VSEvent {
+ protected VSPrefs prefs;
+ private String protocolClassname;
+ private boolean isServer;
+ private boolean isClient;
+ protected VSProcess process;
+ private boolean currentContextIsServer;
+ private boolean lamportIncreased;
+
+ public VSProtocol() {
+ }
+
+ protected final void setProtocolClassname(String protocolClassname) {
+ if (protocolClassname.startsWith("class "))
+ protocolClassname = protocolClassname.substring(6);
+
+ this.protocolClassname = protocolClassname;
+ }
+
+ public final String getProtocolClassname() {
+ return protocolClassname;
+ }
+
+ public final String getProtocolName() {
+ return RegisteredProtocols.getProtocolName(protocolClassname);
+ }
+
+ public final VSProcess getProcess() {
+ return process;
+ }
+
+ protected void sendMessage(VSMessage message) {
+ process.setLamportTime(process.getLamportTime()+1);
+ message.setSendingProcess(process);
+ process.sendMessage(message);
+ }
+
+ private final boolean isIncorrectProtocol(VSMessage message) {
+ return !message.getProtocolClassname().equals(getProtocolClassname());
+ }
+
+ public final void onStart() {
+ if (isClient) {
+ onClientStart();
+ currentContextIsServer = false;
+ }
+ }
+
+ public final void onMessageRecv(VSMessage message) {
+ if (isIncorrectProtocol(message))
+ return;
+
+ if (isServer) {
+ currentContextIsServer = true;
+ onServerRecv(message);
+ }
+
+ if (isClient) {
+ currentContextIsServer = false;
+ onClientRecv(message);
+ }
+ }
+
+ public final void isServer(boolean isServer) {
+ this.isServer = isServer;
+ }
+
+ public final void isClient(boolean isClient) {
+ this.isClient = isClient;
+ }
+
+ public final void setVSPrefs(VSPrefs prefs) {
+ this.prefs = prefs;
+ }
+
+ public final void setProcess(VSProcess process) {
+ this.process = process;
+ }
+
+ public void reset() {
+ if (isServer) {
+ currentContextIsServer = true;
+ onServerReset();
+ }
+
+ if (isClient) {
+ currentContextIsServer = false;
+ onClientReset();
+ }
+ }
+
+ abstract protected void onClientStart();
+ abstract protected void onClientReset();
+ abstract protected void onClientRecv(VSMessage message);
+
+ abstract protected void onServerReset();
+ abstract protected void onServerRecv(VSMessage message);
+
+ protected void logg(String message) {
+ process.logg(toString() + "; " + message);
+ }
+
+ public boolean equals(VSProtocol protocol) {
+ return protocol.getID() == getID();
+ }
+
+ public String toString() {
+ String type = new String();
+
+ if (currentContextIsServer)
+ type += prefs.getString("lang.server");
+
+ else
+ type += prefs.getString("lang.client");
+
+ return prefs.getString("lang.protocol") + ": "
+ + RegisteredProtocols.getProtocolName(getProtocolClassname()) + " " + type;// + "; ID: " + getID();
+ }
+}
diff --git a/sources/simulator/VSAbout.java b/sources/simulator/VSAbout.java
new file mode 100644
index 0000000..4b68598
--- /dev/null
+++ b/sources/simulator/VSAbout.java
@@ -0,0 +1,63 @@
+package simulator;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.filechooser.*;
+import java.util.*;
+import java.io.File;
+
+import prefs.*;
+import utils.*;
+
+public class VSAbout extends VSFrame implements ActionListener {
+ private VSPrefs prefs;
+
+ public VSAbout(VSPrefs prefs, Component relativeTo) {
+ super(prefs.getString("name") + " - "
+ + prefs.getString("lang.about"), relativeTo);
+
+ this.prefs = prefs;
+ disposeWithParent();
+ setContentPane(createContentPane());
+ setSize(350, 250);
+ setResizable(false);
+ setVisible(true);
+ }
+
+
+ public Container createContentPane() {
+ Container contentPane = getContentPane();
+
+ VSInfoArea infoArea = new VSInfoArea(prefs.getString("lang.about.info!"));
+ JPanel buttonPane = createButtonPane();
+ JScrollPane scrollPane = new JScrollPane(infoArea);
+
+ contentPane.add(scrollPane, BorderLayout.CENTER);
+ contentPane.add(buttonPane, BorderLayout.SOUTH);
+
+ return contentPane;
+ }
+
+ public JPanel createButtonPane() {
+ JPanel buttonPane = new JPanel();
+ buttonPane.setBackground(Color.WHITE);
+
+ JButton closeButton = new JButton(
+ prefs.getString("lang.close"));
+ closeButton.setMnemonic(prefs.getInteger("keyevent.close"));
+ closeButton.addActionListener(this);
+ buttonPane.add(closeButton);
+
+ return buttonPane;
+ }
+
+
+ public void actionPerformed(ActionEvent e) {
+ String actionCommand = e.getActionCommand();
+
+ if (actionCommand.equals(prefs.getString("lang.close")))
+ dispose();
+ }
+}
diff --git a/sources/simulator/VSLogging.java b/sources/simulator/VSLogging.java
new file mode 100644
index 0000000..c65198b
--- /dev/null
+++ b/sources/simulator/VSLogging.java
@@ -0,0 +1,57 @@
+package simulator;
+
+import javax.swing.*;
+import java.util.*;
+
+import utils.*;
+
+public class VSLogging {
+ private JTextArea loggingArea;
+ private VSSimulationPanel simulationPanel;
+ private volatile boolean isPaused;
+ private StringBuffer pauseBuffer;
+
+ public VSLogging() {
+ loggingArea = new JTextArea(0, 0);
+ loggingArea.setEditable(false);
+ pauseBuffer = new StringBuffer();
+ }
+
+ public void setSimulationPanel(VSSimulationPanel simulationPanel) {
+ this.simulationPanel = simulationPanel;
+ }
+
+ public JTextArea getLoggingArea() {
+ return loggingArea;
+ }
+
+ public void logg(String message) {
+ if (simulationPanel == null)
+ logg(message, 0);
+ else
+ logg(message, simulationPanel.getTime());
+ }
+
+ public void logg(String message, long time) {
+ if (isPaused) {
+ pauseBuffer.append(VSTools.getTimeString(time));
+ pauseBuffer.append(": ");
+ pauseBuffer.append(message);
+ pauseBuffer.append("\n");
+
+ } else {
+ loggingArea.append(VSTools.getTimeString(time) + ": " + message + "\n");
+ loggingArea.setCaretPosition(loggingArea.getDocument().getLength());
+ }
+ }
+
+ public void isPaused(boolean isPaused) {
+ this.isPaused = isPaused;
+
+ if (!isPaused) {
+ loggingArea.append(pauseBuffer.toString());
+ loggingArea.setCaretPosition(loggingArea.getDocument().getLength());
+ pauseBuffer.delete(0, pauseBuffer.length());
+ }
+ }
+}
diff --git a/sources/simulator/VSMain.java b/sources/simulator/VSMain.java
new file mode 100644
index 0000000..9280eeb
--- /dev/null
+++ b/sources/simulator/VSMain.java
@@ -0,0 +1,34 @@
+package simulator;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+import editors.*;
+import prefs.*;
+import protocols.*;
+
+public class VSMain {
+ public VSMain(VSPrefs prefs) {
+ initialize(prefs, null);
+ }
+
+ public VSMain(VSPrefs prefs, Component relativeTo) {
+ initialize(prefs, relativeTo);
+ }
+
+ private void initialize(VSPrefs prefs, Component relativeTo) {
+ new VSSimulationEditor(prefs, relativeTo);
+ }
+
+ public static void main(String[] args) {
+ try {
+ UIManager.setLookAndFeel(
+ UIManager.getCrossPlatformLookAndFeelClassName());
+ } catch (Exception e) { }
+
+ VSPrefs prefs = VSDefaultPrefs.initialize();
+ RegisteredProtocols.initialize(prefs);
+ new VSMain(prefs);
+ }
+}
diff --git a/sources/simulator/VSSimulation.java b/sources/simulator/VSSimulation.java
new file mode 100644
index 0000000..2bc90d8
--- /dev/null
+++ b/sources/simulator/VSSimulation.java
@@ -0,0 +1,311 @@
+package simulator;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+import prefs.*;
+import core.*;
+import utils.*;
+
+public class VSSimulation extends VSFrame implements ActionListener {
+ private JMenuItem pauseItem;
+ private JMenuItem replayItem;
+ private JMenuItem resetItem;
+ private JMenuItem startItem;
+ private JSplitPane splitPaneH;
+ private JSplitPane splitPaneV;
+ private JPanel processEditPanel;
+ private VSSimulationPanel simulationPanel;
+ private Thread thread;
+ private VSPrefs prefs;
+ private boolean hasStarted = false;
+ private VSLogging logging;
+
+ public VSSimulation (VSPrefs prefs, Component relativeTo) {
+ super(prefs.getString("name"), relativeTo);
+ this.prefs = prefs;
+ this.logging = new VSLogging();
+
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+
+ setSize(prefs.getInteger("window.xsize")+100,
+ prefs.getInteger("window.ysize"));
+ setJMenuBar(createJMenuBar());
+ setContentPane(createContentPane());
+ setVisible(true);
+
+ thread = new Thread(simulationPanel);
+ //logging.start();
+ logging.logg(prefs.getString("lang.simulation.new"));
+ }
+
+ private JMenuBar createJMenuBar() {
+ /* File menu */
+ JMenu menuFile = new JMenu(prefs.getString("lang.file"));
+ menuFile.setMnemonic(prefs.getInteger("keyevent.file"));
+ JMenuItem menuItem;
+
+ menuItem = new JMenuItem(prefs.getString("lang.new"));
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.new"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ menuFile.add(menuItem);
+
+ menuItem = new JMenuItem(
+ prefs.getString("lang.close"));
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.close"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ menuFile.add(menuItem);
+
+ menuFile.addSeparator();
+
+ menuItem = new JMenuItem(prefs.getString("lang.about"));
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.about"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ menuFile.add(menuItem);
+
+ menuItem = new JMenuItem(prefs.getString("lang.quit"));
+ menuItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.quit"),
+ ActionEvent.ALT_MASK));
+ menuItem.addActionListener(this);
+ menuFile.add(menuItem);
+
+ /* VSSimulation menu */
+ JMenu menuVSSimulation = new JMenu(
+ prefs.getString("lang.simulation"));
+ menuVSSimulation.setMnemonic(prefs.getInteger("keyevent.simulation"));
+
+ startItem = new JMenuItem(
+ prefs.getString("lang.start"));
+ startItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.start"),
+ ActionEvent.ALT_MASK));
+ startItem.addActionListener(this);
+ menuVSSimulation.add(startItem);
+
+ pauseItem = new JMenuItem(
+ prefs.getString("lang.pause"));
+ pauseItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.pause"),
+ ActionEvent.ALT_MASK));
+ pauseItem.addActionListener(this);
+ menuVSSimulation.add(pauseItem);
+ pauseItem.setEnabled(false);
+
+ resetItem = new JMenuItem(
+ prefs.getString("lang.reset"));
+ resetItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.reset"),
+ ActionEvent.ALT_MASK));
+ resetItem.addActionListener(this);
+ resetItem.setEnabled(false);
+ menuVSSimulation.add(resetItem);
+
+ replayItem = new JMenuItem(
+ prefs.getString("lang.replay"));
+ replayItem.setAccelerator(KeyStroke.getKeyStroke(
+ prefs.getInteger("keyevent.replay"),
+ ActionEvent.ALT_MASK));
+ replayItem.addActionListener(this);
+ replayItem.setEnabled(false);
+ menuVSSimulation.add(replayItem);
+
+ JMenuBar mainMenuBar = new JMenuBar();
+ mainMenuBar.add(menuFile);
+ mainMenuBar.add(menuVSSimulation);
+
+ return mainMenuBar;
+ }
+
+ private Container createContentPane() {
+ JTextArea loggingArea = logging.getLoggingArea();
+
+ /*
+ splitPaneH = new JSplitPane();
+ splitPaneH.setDividerLocation(
+ prefs.getInteger("window.splitsize"));
+
+ */
+ splitPaneV = new JSplitPane();
+ splitPaneV.setDividerLocation(
+ prefs.getInteger("window.ysize")
+ - prefs.getInteger("window.loggsize"));
+
+ simulationPanel = new VSSimulationPanel(prefs, this, logging);
+ logging.setSimulationPanel(simulationPanel);
+ simulationPanel.setBackground(new Color(0xFD, 0xFC, 0xF7));
+ //processEditPanel = createProcessEditPanel();
+
+ JScrollPane paintScrollPane = new JScrollPane(simulationPanel);
+ JScrollPane textScrollPane = new JScrollPane(loggingArea);
+ JPanel toolsPanel = createToolsPanel();
+
+ JPanel loggingPane = new JPanel(new BorderLayout());
+ loggingPane.add(textScrollPane, BorderLayout.CENTER);
+ loggingPane.add(toolsPanel, BorderLayout.SOUTH);
+ loggingPane.setPreferredSize(new Dimension(200, 1));
+
+ //JScrollPane processEditScrollPane = new JScrollPane(processEditPanel);
+
+ /*
+ splitPaneH.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
+ splitPaneH.setLeftComponent(processEditScrollPane);
+ splitPaneH.setRightComponent(paintScrollPane);
+ splitPaneH.setContinuousLayout(true);
+ splitPaneH.setOneTouchExpandable(true);
+ */
+
+ splitPaneV.setOrientation(JSplitPane.VERTICAL_SPLIT);
+ //splitPaneV.setTopComponent(splitPaneH);
+ splitPaneV.setTopComponent(paintScrollPane);
+ splitPaneV.setBottomComponent(loggingPane);
+ splitPaneV.setOneTouchExpandable(true);
+ splitPaneV.setContinuousLayout(true);
+
+ Container contentPane = getContentPane();
+ contentPane.add(splitPaneV, BorderLayout.CENTER);
+
+
+ return contentPane;
+ }
+
+ private JPanel createToolsPanel() {
+ JPanel toolsPanel = new JPanel();
+
+ toolsPanel.setLayout(new BoxLayout(toolsPanel, BoxLayout.X_AXIS));
+ JCheckBox loggingActiveCheckBox = new JCheckBox(prefs.getString("lang.logging.active"));
+ loggingActiveCheckBox.setSelected(true);
+ loggingActiveCheckBox.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent ce) {
+ AbstractButton abstractButton = (AbstractButton) ce.getSource();
+ ButtonModel buttonModel = abstractButton.getModel();
+ logging.isPaused(!buttonModel.isSelected());
+ }
+ });
+ toolsPanel.add(loggingActiveCheckBox);
+
+ JCheckBox lamportActiveCheckBox = new JCheckBox(prefs.getString("lang.time.lamport"));
+ lamportActiveCheckBox.setSelected(false);
+ lamportActiveCheckBox.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent ce) {
+ AbstractButton abstractButton = (AbstractButton) ce.getSource();
+ ButtonModel buttonModel = abstractButton.getModel();
+ simulationPanel.showLamport(buttonModel.isSelected());
+ }
+ });
+ toolsPanel.add(lamportActiveCheckBox);
+
+ return toolsPanel;
+ }
+
+ /*
+ private JPanel createProcessEditPanel() {
+ JPanel editPanel = new JPanel(new GridBagLayout());
+ editPanel.setBackground(Color.WHITE);
+
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+
+ Insets insets = new Insets(5, 5, 5, 5);
+ constraints.insets = insets;
+ constraints.ipady = 5;
+ constraints.ipadx = 5;
+ int row = 0;
+
+ Vector<VSProcess> processes = simulationPanel.getProcesses();
+
+ for (VSProcess p : processes) {
+ constraints.gridy = row++;
+ //editPanel.add(new VSProcessEditor(prefs, p), constraints);
+ }
+
+ return editPanel;
+ }
+ */
+
+ public int getSplitSize() {
+ return 0;//splitPaneH.getDividerLocation();
+ }
+
+ public int getPaintSize() {
+ return splitPaneV.getDividerLocation();
+ }
+
+ public void dispose() {
+ simulationPanel.finalize();
+ super.dispose();
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ JMenuItem source = (JMenuItem) e.getSource();
+
+ if (source.getText().equals(prefs.getString("lang.close"))) {
+ dispose();
+
+ } else if (source.getText().equals(prefs.getString("lang.new"))) {
+ new VSMain(VSDefaultPrefs.initialize(), VSSimulation.this);
+
+ } else if (source.getText().equals(prefs.getString("lang.about"))) {
+ new VSAbout(prefs, VSSimulation.this);
+
+ } else if (source.getText().equals(prefs.getString("lang.quit"))) {
+ System.exit(0);
+
+ } else if (source.getText().equals(prefs.getString("lang.start"))) {
+ startItem.setEnabled(false);
+ pauseItem.setEnabled(true);
+ resetItem.setEnabled(false);
+ replayItem.setEnabled(true);
+ runThread();
+
+ } else if (source.getText().equals(prefs.getString("lang.pause"))) {
+ startItem.setEnabled(true);
+ pauseItem.setEnabled(false);
+ resetItem.setEnabled(true);
+ replayItem.setEnabled(true);
+ simulationPanel.pause();
+
+ } else if (source.getText().equals(prefs.getString("lang.reset"))) {
+ startItem.setEnabled(true);
+ pauseItem.setEnabled(false);
+ resetItem.setEnabled(false);
+ replayItem.setEnabled(false);
+ simulationPanel.reset();
+
+ } else if (source.getText().equals(prefs.getString("lang.replay"))) {
+ startItem.setEnabled(false);
+ pauseItem.setEnabled(true);
+ resetItem.setEnabled(false);
+ replayItem.setEnabled(true);
+ simulationPanel.reset();
+ runThread();
+ }
+ }
+
+ private void runThread() {
+ if (hasStarted) {
+ simulationPanel.play();
+
+ } else {
+ hasStarted = true;
+ thread = new Thread(simulationPanel);
+ thread.start();
+ }
+ }
+
+ public void finish() {
+ startItem.setEnabled(false);
+ pauseItem.setEnabled(false);
+ resetItem.setEnabled(true);
+ replayItem.setEnabled(true);
+ }
+}
diff --git a/sources/simulator/VSSimulationPanel.java b/sources/simulator/VSSimulationPanel.java
new file mode 100644
index 0000000..f0d3d75
--- /dev/null
+++ b/sources/simulator/VSSimulationPanel.java
@@ -0,0 +1,619 @@
+package simulator;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.*;
+import java.util.*;
+import javax.swing.*;
+
+import core.*;
+import editors.*;
+import prefs.*;
+import utils.*;
+import events.*;
+
+public class VSSimulationPanel extends JPanel implements Runnable, MouseMotionListener, MouseListener, HierarchyBoundsListener {
+ private VSProcess highlightedProcess;
+ private VSSimulation simulation;
+ private VSPrefs prefs;
+ private VSLogging logging;
+ private int numProcesses;
+ private int secondsSpaceing;
+ private int threadSleep;
+ private long untilTime;
+ private volatile boolean isPaused = false;
+ private volatile boolean isFinalized = false;
+ private volatile boolean isFinished = false;
+ private volatile boolean isResetted = false;
+ private volatile boolean showLamport = false;
+ private volatile long pauseTime;
+ private volatile long startTime;
+ private volatile long time;
+ private volatile long lastTime;
+ private VSTaskManager taskManager;
+ private LinkedList<VSMessageLine> messageLines;
+ private LinkedList<VSProcess> processes;
+
+ /* Static constats */
+ private static final int LINE_WIDTH = 5;
+ private static final int SEPLINE_WIDTH = 2;
+ private static final int XOFFSET = 50;
+ private static final int YOFFSET = 30;
+ private static final int YOUTER_SPACEING = 10;
+ private static final int YSEPLINE_SPACEING = 20;
+ private static final int TEXT_SPACEING = 10;
+
+ /* Constats, which have to get calculated once after start */
+ private Color processlineColor;
+ private Color processSecondlineColor;
+ private Color processSeplineColor;
+ private Color messageArrivedColor;
+ private Color messageSendingColor;
+ private Color messageLostColor;
+
+ private class VSMessageLine {
+ private VSProcess receiverProcess;
+ private Color color;
+ private long sendTime;
+ private long recvTime;
+ private int senderNum;
+ private int receiverNum;
+ private int offset1;
+ private int offset2;
+ private boolean isArrived;
+ private boolean isLost;
+ private double x1;
+ private double y1;
+ private double x2;
+ private double y2;
+ private double x;
+ private double y;
+ private long outageTime;
+ private long z;
+
+ public VSMessageLine(VSProcess receiverProcess, long sendTime, long recvTime, long outageTime, int senderNum , int receiverNum) {
+ this.receiverProcess = receiverProcess;
+ this.sendTime = sendTime;
+ this.recvTime = recvTime;
+ this.outageTime = outageTime;
+ this.senderNum = senderNum;
+ this.receiverNum = receiverNum;
+ this.isArrived = false;
+ this.isLost = false;
+
+ if (senderNum > receiverNum) {
+ //offset1 = 1;
+ offset2 = LINE_WIDTH;
+ } else {
+ offset1 = LINE_WIDTH - 1;
+ //offset2 = 1;
+ }
+
+ /* Needed if the message gets lost after 0ms */
+ this.x = getTimeXPosition(sendTime);
+ this.y = getProcessYPosition(senderNum) + offset1;
+
+ recalcOnWindowChanged();
+ }
+
+ public void recalcOnWindowChanged() {
+ x1 = getTimeXPosition(sendTime);
+ y1 = getProcessYPosition(senderNum) + offset1;
+ x2 = getTimeXPosition(recvTime);
+ y2 = getProcessYPosition(receiverNum) + offset2;
+
+ if (isLost) {
+ x = getTimeXPosition(z);
+ y = y1 + ( ( (y2-y1) / (x2-x1)) * (x-x1));
+ }
+ }
+
+ public void draw(final Graphics2D g, final long globalTime) {
+ if (isArrived) {
+ g.setColor(color);
+ g.drawLine((int) x1, (int) y1, (int) x2, (int) y2);
+
+ } else if (isLost) {
+ g.setColor(messageLostColor);
+ g.drawLine((int) x1, (int) y1, (int) x, (int) y);
+
+ } else if (globalTime >= recvTime) {
+ isArrived = true;
+ if (receiverProcess.isCrashed())
+ color = messageLostColor;
+ else
+ color = messageArrivedColor;
+ draw(g, globalTime);
+
+ } else if (outageTime >= 0 && outageTime <= globalTime){
+ isLost = true;
+ draw(g, globalTime);;
+
+ } else {
+ z = globalTime;
+ x = globalTimeXPosition;
+ y = y1 + ( ( (y2-y1) / (x2-x1)) * (x-x1));
+ g.setColor(messageSendingColor);
+ g.drawLine((int) x1, (int) y1, (int) x, (int) y);
+ }
+ }
+ }
+
+ public VSSimulationPanel(VSPrefs prefs, VSSimulation simulation, VSLogging logging) {
+ this.prefs = prefs;
+ this.simulation = simulation;
+ this.logging = logging;
+ this.taskManager = new VSTaskManager(prefs);
+ this.messageLines = new LinkedList<VSMessageLine>();
+ this.processes = new LinkedList<VSProcess>();
+
+ numProcesses = prefs.getInteger("sim.process.num");
+ untilTime = prefs.getInteger("sim.seconds") * 1000;
+ recalcOnWindowChanged();
+
+ secondsSpaceing = (int) untilTime / 15000;
+ if (secondsSpaceing == 0)
+ secondsSpaceing = 1;
+
+ threadSleep = (int) untilTime / 7500;
+ if (threadSleep == 0)
+ threadSleep = 1;
+
+ VSProcess.resetProcessCounter();
+ for (int i = 0; i < numProcesses; ++i)
+ createProcess(i);
+
+ addMouseListener(this);
+ addMouseMotionListener(this);
+ addHierarchyBoundsListener(this);
+ }
+
+ double xPaintSize;
+ double paintSize;
+ double yDistance;
+ double globalTimeXPosition;
+
+ int xoffset_plus_xpaintsize;
+ double xpaintsize_dividedby_untiltime;
+ int paintProcessesOffset;
+
+ int paintSecondlinesSeconds;
+ int paintSecondlinesLine[] = new int[4];
+ int paintSecondlinesYStringPos1;
+ int paintSecondlinesYStringPos2;
+ int paintGlobalTimeYPosition;
+
+ /* This method contains very ugly code. But this has to be in order to gain performance! */
+ private void recalcOnWindowChanged() {
+ processlineColor = prefs.getColor("process.line");
+ processSecondlineColor = prefs.getColor("process.secondline");
+ processSeplineColor = prefs.getColor("process.sepline");
+ messageArrivedColor = prefs.getColor("message.arrived");
+ messageSendingColor = prefs.getColor("message.sending");
+ messageLostColor = prefs.getColor("message.lost");
+
+ paintSize = simulation.getPaintSize();
+ xPaintSize = simulation.getWidth() - (3 * XOFFSET + simulation.getSplitSize());
+ yDistance = (simulation.getPaintSize() - 2 * (YOFFSET + YOUTER_SPACEING))/ numProcesses;
+ xpaintsize_dividedby_untiltime = xPaintSize / (double) untilTime;
+
+ for (VSMessageLine messageLine : messageLines)
+ messageLine.recalcOnWindowChanged();
+
+ /* paintProcesses optimization, precalc things */
+ {
+ xoffset_plus_xpaintsize = XOFFSET + (int) xPaintSize;
+ if (numProcesses > 1)
+ paintProcessesOffset = (int) ((paintSize-2*(YOFFSET+YOUTER_SPACEING+YSEPLINE_SPACEING))/(numProcesses-1));
+ else
+ paintProcessesOffset = (int) ((paintSize-2*(YOFFSET+YOUTER_SPACEING+YSEPLINE_SPACEING)));
+ }
+
+ /* paintSecondlines optimization, precalc things */
+ {
+ int yMax = YOFFSET + YOUTER_SPACEING + (int) (numProcesses * yDistance);
+ paintSecondlinesSeconds = (int) untilTime / 1000;
+ paintSecondlinesLine[1] = YOFFSET;
+ paintSecondlinesLine[3] = yMax;
+ paintSecondlinesYStringPos1 = paintSecondlinesLine[1] - 5;
+ paintSecondlinesYStringPos2 = paintSecondlinesLine[3] + 15;
+ }
+
+ /* paitnGlobalTime optimization, precalc things */
+ {
+ paintGlobalTimeYPosition = YOFFSET + YOUTER_SPACEING + (int) (numProcesses * yDistance);
+ }
+ }
+
+ public VSProcess createProcess(int i) {
+ VSProcess process = new VSProcess(prefs, this, logging, i+1);
+ processes.add(process);
+ logging.logg(prefs.getString("lang.process.new") + "; " + process);
+
+ return process;
+ }
+
+ private void updateSimulation(final long globalTime, final long lastGlobalTime) {
+ final long offset = globalTime - lastGlobalTime;
+ for (long l = 0; l < offset; ++l)
+ taskManager.runVSTasks(l, offset, lastGlobalTime);
+
+ for (VSProcess process : processes)
+ process.syncTime(globalTime);
+ }
+
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+
+ final long globalTime = time;
+ final Graphics2D g2d = (Graphics2D) g;
+
+ globalTimeXPosition = getTimeXPosition(globalTime);
+
+ paintSecondlines(g2d);
+ paintProcesses(g2d, globalTime);
+ paintGlobalTime(g2d, globalTime);
+
+ synchronized (messageLines) {
+ for (VSMessageLine line : messageLines)
+ line.draw(g2d, globalTime);
+ }
+
+ }
+
+ private void paintProcesses(Graphics2D g, long globalTime) {
+ /* First paint the horizontal process timelines
+ * Second paint the processes
+ */
+ final int yOffset = YOFFSET + YOUTER_SPACEING + YSEPLINE_SPACEING;
+ final int xPoints[] = { XOFFSET, xoffset_plus_xpaintsize, xoffset_plus_xpaintsize, XOFFSET, XOFFSET };
+ final int yPoints[] = { yOffset, yOffset, yOffset + LINE_WIDTH, yOffset + LINE_WIDTH, yOffset };
+
+ for (VSProcess process : processes) {
+ final long localTime = process.getTime();
+
+ g.setColor(process.getColor());
+ g.fillPolygon(xPoints, yPoints, 5);
+ if (process.isCrashed()) {
+ final VSTask crashTask = process.getCrashTask();
+ final int crashPos = (int) getTimeXPosition(crashTask.getTaskTime());
+ final int xPointsCrashed[] = { crashPos, xoffset_plus_xpaintsize, xoffset_plus_xpaintsize, crashPos, crashPos };
+ g.setColor(process.getCrashedColor());
+ g.fillPolygon(xPointsCrashed, yPoints, 5);
+ }
+
+ g.drawString("P" + process.getProcessID() + ":", XOFFSET - 30, yPoints[0] + LINE_WIDTH);
+
+ final long tmp = localTime > untilTime ? untilTime : localTime;
+ final int xPos = 1 + (int) getTimeXPosition(tmp);
+ final int yStart = yPoints[0] - 14;
+ final int yEnd = yPoints[0];
+
+ g.setColor(processlineColor);
+ g.drawLine(xPos, yStart, xPos, yEnd);
+ g.drawString(localTime+"ms", xPos + 2, yStart + TEXT_SPACEING);
+
+ if (showLamport) {
+ int last = -1;
+ final int distance = 20;
+ final VSLamport[] lamportStamps = process.getLamportArray();
+ for (VSLamport lamport : lamportStamps) {
+ int xPos_ = (int) getTimeXPosition(lamport.getTime());
+ if (last >= 0) {
+ int diff = xPos_ - last;
+ if (diff < distance)
+ xPos_ += distance - diff;
+ }
+ g.drawString(""+lamport.getLamportTime(), xPos_ + 2, yStart + 3 * TEXT_SPACEING);
+ last = xPos_;
+ }
+ }
+
+ for (int i = 0; i < 5; ++i)
+ yPoints[i] += paintProcessesOffset;
+ }
+ }
+
+ private void paintSecondlines(Graphics2D g) {
+ g.setColor(processSecondlineColor);
+
+ int i;
+ for (i = 0; i <= paintSecondlinesSeconds; i += secondsSpaceing) {
+ paintSecondlinesLine[0] = paintSecondlinesLine[2] = (int) getTimeXPosition(i*1000);
+ g.drawLine(paintSecondlinesLine[0], paintSecondlinesLine[1], paintSecondlinesLine[2], paintSecondlinesLine[3]);
+
+ final int xStringPos = paintSecondlinesLine[0] - 5;
+ g.drawString(i+"s", xStringPos, paintSecondlinesYStringPos1);
+ g.drawString(i+"s", xStringPos, paintSecondlinesYStringPos2);
+ }
+
+ if (i > paintSecondlinesSeconds) {
+ paintSecondlinesLine[0] = paintSecondlinesLine[2] = (int) getTimeXPosition(untilTime);
+ g.drawLine(paintSecondlinesLine[0], paintSecondlinesLine[1], paintSecondlinesLine[2], paintSecondlinesLine[3]);
+ }
+ }
+
+ private void paintGlobalTime(Graphics2D g, long globalTime) {
+ g.setColor(processSeplineColor);
+ final int xOffset = (int) globalTimeXPosition;
+
+ final int xPoints[] = { xOffset, xOffset + SEPLINE_WIDTH, xOffset + SEPLINE_WIDTH, xOffset, xOffset };
+ final int yOffset = YOFFSET - 8;
+ final int yPoints[] = { yOffset, yOffset, paintGlobalTimeYPosition, paintGlobalTimeYPosition, yOffset };
+
+ g.fillPolygon(xPoints, yPoints, 5);
+ g.drawString(globalTime+"ms", xPoints[1]+1, yPoints[0]+TEXT_SPACEING);
+ }
+
+ private VSProcess getProcessAtYPos(int yPos) {
+ final int reachDistance = (int) (yDistance/3);
+ int y = YOFFSET + YOUTER_SPACEING + YSEPLINE_SPACEING;
+
+ int yOffset = numProcesses > 1
+ ? (int) ((paintSize-2*(YOFFSET+YOUTER_SPACEING+YSEPLINE_SPACEING))/(numProcesses-1))
+ : (int) ((paintSize-2*(YOFFSET+YOUTER_SPACEING+YSEPLINE_SPACEING)));
+
+ for (int i = 0; i < numProcesses; ++i) {
+ if (yPos < y + reachDistance && yPos > y - reachDistance - LINE_WIDTH)
+ return processes.get(i);
+ y += yOffset;
+ }
+
+ return null;
+ }
+
+ private double getTimeXPosition(long time) {
+ return XOFFSET + xpaintsize_dividedby_untiltime * time;
+ }
+
+ private int getProcessYPosition(int i) {
+ int y;
+
+ if (numProcesses > 1)
+ y = (int) ((paintSize -
+ 2 * (YOFFSET + YOUTER_SPACEING + YSEPLINE_SPACEING))/ (numProcesses-1));
+ else
+ y = (int) ((paintSize -
+ 2 * (YOFFSET + YOUTER_SPACEING + YSEPLINE_SPACEING)));
+
+ return y * (i - 1) + YOFFSET + YOUTER_SPACEING + YSEPLINE_SPACEING;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public long getUntilTime() {
+ return untilTime;
+ }
+
+ public long getStartTime() {
+ return startTime;
+ }
+
+ public VSTaskManager getTaskManager() {
+ return taskManager;
+ }
+
+ public int getNumProcesses() {
+ return numProcesses;
+ }
+
+ public void run() {
+ play();
+
+ while (true) {
+ while (!isPaused && !isFinalized) {
+ try {
+ Thread.sleep(threadSleep);
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+
+ updateSimulation(time, lastTime);
+ repaint();
+
+ lastTime = time;
+ time = System.currentTimeMillis() - startTime;
+
+ if (time > untilTime)
+ time = untilTime;
+
+ if (time == untilTime) {
+ finish();
+ break;
+ }
+ }
+
+ if (isPaused) {
+ for (VSProcess p : processes)
+ p.pause();
+
+ pauseTime = System.currentTimeMillis();
+
+ logging.logg(prefs.getString("lang.simulation.paused"));
+ repaint();
+ }
+
+ updateSimulation(time, lastTime);
+ repaint();
+
+ while (!isFinalized && (isPaused || isFinished || isResetted)) {
+ try {
+ Thread.sleep(100);
+ repaint();
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+ }
+
+ if (isFinalized)
+ break; /* Exit the thread */
+ }
+ }
+
+ public void play() {
+ logging.logg(prefs.getString("lang.simulation.started"));
+ final long currentTime = System.currentTimeMillis();
+
+ for (VSProcess p : processes)
+ p.play();
+
+ if (isResetted)
+ isResetted = false;
+
+ else if (isFinished)
+ isFinished = false;
+
+ if (isPaused) {
+ isPaused = false;
+ startTime += currentTime - pauseTime;
+ time = currentTime - startTime;
+
+ } else {
+ startTime = currentTime;
+ time = 0;
+ }
+
+ repaint();
+ }
+
+ public void finish() {
+ for (VSProcess p : processes)
+ p.finish();
+
+ simulation.finish();
+ isFinished = true;
+
+ logging.logg(prefs.getString("lang.simulation.finished"));
+ repaint();
+ }
+
+ public void pause() {
+ isPaused = true;
+ }
+
+ public void reset() {
+ if (!isResetted) {
+ logging.logg(prefs.getString("lang.simulation.resetted"));
+
+ isResetted = true;
+ isPaused = false;
+ isFinished = false;
+ startTime = System.currentTimeMillis();
+ time = 0;
+ lastTime = 0;
+
+ taskManager.reset();
+
+ for (VSProcess p : processes)
+ p.reset();
+
+ synchronized (messageLines) {
+ messageLines.clear();
+ }
+ repaint();
+ }
+ }
+
+ public void finalize() {
+ isFinalized = true;
+ }
+
+ public boolean isFinalized() {
+ return isFinalized;
+ }
+
+ public void showLamport(boolean showLamport) {
+ this.showLamport = showLamport;
+ repaint();
+ }
+
+ public void sendMessage(VSMessage message) {
+ VSTask task = null;
+ VSProcess sendingProcess = message.getSendingProcess();
+ long deliverTime, outageTime, durationTime;
+
+ for (VSProcess receiverProcess : processes) {
+ if (receiverProcess.equals(sendingProcess)) {
+ deliverTime = sendingProcess.getGlobalTime();
+ task = new VSTask(deliverTime, receiverProcess, message);
+ taskManager.addTask(task);
+
+ } else {
+ durationTime = sendingProcess.getDurationTime();
+ deliverTime = sendingProcess.getGlobalTime() + durationTime;
+ outageTime = sendingProcess.getARandomMessageOutageTime(durationTime);
+
+ /* Only add a 'receiving message' task if the message will not get lost! */
+ if (outageTime == -1) {
+ task = new VSTask(deliverTime, receiverProcess, message);
+ taskManager.addTask(task);
+ }
+
+ synchronized (messageLines) {
+ messageLines.add(new VSMessageLine(receiverProcess,
+ sendingProcess.getGlobalTime(), deliverTime, outageTime,
+ sendingProcess.getNum(), receiverProcess.getNum()));
+ }
+ }
+ }
+ }
+
+ public void mouseClicked(MouseEvent e) {
+ VSProcess process = getProcessAtYPos(e.getY());
+ if (process != null) {
+ process.updatePrefs();
+ new VSProcessEditor(prefs, simulation, process);
+ }
+ }
+
+ public void mouseEntered(MouseEvent e) { }
+
+ public void mouseExited(MouseEvent e) {
+ if (highlightedProcess != null) {
+ highlightedProcess.highlightOff();
+ highlightedProcess = null;
+ repaint();
+ }
+ }
+
+ public void mousePressed(MouseEvent e) { }
+
+ public void mouseReleased(MouseEvent e) { }
+
+ public void mouseDragged(MouseEvent e) { }
+
+ public void mouseMoved(MouseEvent e) {
+ VSProcess p = getProcessAtYPos(e.getY());
+
+ if (p == null) {
+ if (highlightedProcess != null) {
+ highlightedProcess.highlightOff();
+ highlightedProcess = null;
+ repaint();
+ }
+
+ return;
+ }
+
+ if (highlightedProcess != null) {
+ if (highlightedProcess.getProcessID() != p.getProcessID()) {
+ highlightedProcess.highlightOff();
+ highlightedProcess = p;
+ p.highlightOn();
+ repaint();
+ }
+ } else {
+ highlightedProcess = p;
+ p.highlightOn();
+ repaint();
+ }
+ }
+
+ public void ancestorMoved(HierarchyEvent e) { }
+
+ public void ancestorResized(HierarchyEvent e) {
+ recalcOnWindowChanged();
+ }
+}
diff --git a/sources/utils/VSClassLoader.java b/sources/utils/VSClassLoader.java
new file mode 100644
index 0000000..7d9fdf3
--- /dev/null
+++ b/sources/utils/VSClassLoader.java
@@ -0,0 +1,20 @@
+package utils;
+
+import java.util.*;
+
+import prefs.*;
+
+public class VSClassLoader extends ClassLoader {
+ public Object newInstance(String classname) {
+ Object object = null;
+
+ try {
+ object = loadClass(classname, true).newInstance();
+
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+
+ return object;
+ }
+}
diff --git a/sources/utils/VSFrame.java b/sources/utils/VSFrame.java
new file mode 100644
index 0000000..2725729
--- /dev/null
+++ b/sources/utils/VSFrame.java
@@ -0,0 +1,58 @@
+package utils;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.JFrame;
+
+public class VSFrame extends JFrame {
+ private final static int X_LOCATION_OFFSET = 40;
+ private final static int Y_LOCATION_OFFSET = 80;
+ private Component parent;
+ private boolean dispose;
+
+ public VSFrame(String title, Component parent) {
+ super(title);
+ initialize(parent);
+ }
+
+ public VSFrame(String title) {
+ super(title);
+ initialize(null);
+ }
+
+ private void initialize(Component parent) {
+ this.parent = parent;
+ this.dispose = false;
+
+ setLocation();
+ }
+
+ public void disposeWithParent() {
+ if (!dispose && parent != null && parent instanceof Window) {
+ Window window = (Window) parent;
+ window.addWindowListener(new WindowAdapter() {
+ public void windowClosed(WindowEvent we) {
+ VSFrame.this.dispose();
+ }
+ });
+ }
+ dispose = true;
+ }
+
+ private void setLocation() {
+ int x = 0, y = 0;
+
+ if (parent == null) {
+ final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ x = (int) (screenSize.width - getWidth()) / 2;
+ y = (int) (screenSize.height - getHeight()) / 2;
+
+ } else {
+ final Point location = parent.getLocation();
+ x = (int) location.getX() + X_LOCATION_OFFSET;
+ y = (int) location.getY() + Y_LOCATION_OFFSET;
+ }
+
+ setLocation(x, y);
+ }
+}
diff --git a/sources/utils/VSInfoArea.java b/sources/utils/VSInfoArea.java
new file mode 100644
index 0000000..9d3600e
--- /dev/null
+++ b/sources/utils/VSInfoArea.java
@@ -0,0 +1,26 @@
+package utils;
+
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.border.*;
+
+public class VSInfoArea extends JTextPane {
+ public VSInfoArea() {
+ initialize();
+ }
+
+ public VSInfoArea(String text) {
+ setText(text);
+ initialize();
+ }
+
+ private void initialize() {
+ setOpaque(false);
+ setBorder(null);
+ setFocusable(false);
+ setBorder(new CompoundBorder(
+ new LineBorder(Color.BLACK),
+ new EmptyBorder(15, 15, 15, 15)));
+ setBackground(Color.WHITE);
+ }
+}
diff --git a/sources/utils/VSRandom.java b/sources/utils/VSRandom.java
new file mode 100644
index 0000000..4f23e7e
--- /dev/null
+++ b/sources/utils/VSRandom.java
@@ -0,0 +1,17 @@
+package utils;
+
+import java.util.Random;
+
+public final class VSRandom extends Random {
+ public VSRandom(long seedAdd) {
+ super(seedAdd*System.currentTimeMillis()+seedAdd);
+ }
+
+ public int nextInt() {
+ return Math.abs(super.nextInt());
+ }
+
+ public long nextLong(long mod) {
+ return Math.abs((super.nextLong() + System.currentTimeMillis()) % mod);
+ }
+}
diff --git a/sources/utils/VSTools.java b/sources/utils/VSTools.java
new file mode 100644
index 0000000..11d93a7
--- /dev/null
+++ b/sources/utils/VSTools.java
@@ -0,0 +1,24 @@
+package utils;
+
+import java.util.*;
+
+public final class VSTools {
+ public static String getTimeString(long time) {
+ String ret = ""+time;
+
+ while (ret.length() < 6)
+ ret = "0" + ret;
+
+ return ret + "ms";
+ }
+ public static long getStringTime(String string) {
+ try {
+ /* Ignore the "ms" postfix */
+ Long longValue = Long.valueOf(string.substring(0, string.length()-2));
+ return longValue.longValue();
+ } catch (NumberFormatException e) {
+ }
+
+ return 0;
+ }
+}