/[xulu]/trunk/src/appl/plugin/multimodelcontrol/MultiModelControlHandler.java
ViewVC logotype

Contents of /trunk/src/appl/plugin/multimodelcontrol/MultiModelControlHandler.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations)
Wed Feb 25 11:54:01 2009 UTC (15 years, 9 months ago) by mojays
File size: 20468 byte(s)
First Commit, corresponds to Revision 1008 of Wikisquare-SVN 
1 package appl.plugin.multimodelcontrol;
2
3 import java.awt.Color;
4 import java.awt.PopupMenu;
5 import java.awt.event.ActionEvent;
6 import java.awt.event.ActionListener;
7 import java.util.Vector;
8 import java.util.concurrent.locks.Condition;
9 import java.util.concurrent.locks.Lock;
10 import java.util.concurrent.locks.ReentrantLock;
11
12 import javax.swing.DefaultListModel;
13 import javax.swing.JList;
14 import javax.swing.JOptionPane;
15 import javax.swing.ListSelectionModel;
16 import javax.swing.event.ListSelectionEvent;
17 import javax.swing.event.ListSelectionListener;
18
19 import appl.parallel.gui.ParallelControlPanelEngine;
20
21 import schmitzm.data.event.ObjectEvent;
22 import schmitzm.data.event.ObjectListener;
23 import schmitzm.lang.WorkingThread;
24 import schmitzm.lang.WorkingThreadAdapter;
25 import schmitzm.lang.WorkingThreadListener;
26 import schmitzm.swing.TextAreaPrintStream;
27 import edu.bonn.xulu.XuluModellingPlatform;
28 import edu.bonn.xulu.appl.ModelControlManager;
29 import edu.bonn.xulu.gui.ModelControlFrame;
30 import edu.bonn.xulu.model.StepModel;
31 import edu.bonn.xulu.model.XuluModel;
32 import edu.bonn.xulu.model.event.ModelEvent;
33 import edu.bonn.xulu.model.event.ModelListener;
34 import edu.bonn.xulu.plugin.gui.ModelControlFrame_Basic;
35
36 /**
37 * The class allows to control several models at once. At the moment it provides
38 * a batch like execution functionality. It is still under development but
39 * should basically work. It was developed in very short time and is therefore
40 * not as well commented, as other classes.
41 *
42 * @author Dominik Appl
43 */
44 public class MultiModelControlHandler implements ListSelectionListener,
45 ObjectListener, ActionListener {
46
47 private MultiModelControlFrame frame;
48
49 private final XuluModellingPlatform xulu;
50
51 private DefaultListModel modelListModel;
52
53 private ParallelControlPanelEngine parallelControlPanelEngine;
54
55 private DefaultListModel commandListModel;
56
57 private InterpretingThread interpretingThread;
58
59 private TextAreaPrintStream consoleStream;
60
61 private String string;
62
63 public MultiModelControlHandler(XuluModellingPlatform xulu) {
64 this.xulu = xulu;
65 frame = new MultiModelControlFrame();
66 initGUI();
67 consoleStream = new TextAreaPrintStream(frame.console);
68 }
69
70 /**
71 *
72 */
73 private void initGUI() {
74 // register as listener for changes in the ModelControlManager
75 xulu.getModelControlManager().addObjectListener(this);
76 // init model list
77 initModelList();
78 initCommandList();
79 registerListeners();
80 }
81
82 /**
83 *
84 */
85 private void registerListeners() {
86 frame.addStepCommand.addActionListener(this);
87 frame.newOverAllStep.addActionListener(this);
88 frame.clearModelSteps.addActionListener(this);
89 frame.startButton.addActionListener(this);
90 frame.stopButton.addActionListener(this);
91 frame.stepButton.addActionListener(this);
92 frame.modelList.addMouseListener(new java.awt.event.MouseAdapter() {
93 public void mouseClicked(java.awt.event.MouseEvent e) {
94 if (e.getClickCount() == 2) {
95 handleModelListDoubleClick();
96 }
97 }
98 });
99 }
100
101 /**
102 *
103 */
104 private void initCommandList() {
105 commandListModel = new DefaultListModel();
106 frame.syncCommandList.setModel(commandListModel);
107 commandListModel.addElement(new StartCommand());
108 commandListModel.addElement(new StopCommand());
109 frame.syncCommandList
110 .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
111 frame.syncCommandList.setSelectedIndex(0);
112 }
113
114 /**
115 * inits the modelList
116 */
117 private void initModelList() {
118 modelListModel = new DefaultListModel();
119 frame.modelList.setModel(modelListModel);
120 frame.modelList.addListSelectionListener(this);
121 int modelCount = xulu.getModelControlManager().getCount();
122 for (int i = 0; i < modelCount; i++) {
123 ModelControlFrame frame = xulu.getModelControlManager().getAll()[i];
124 this.addModelControlFrame(frame);
125 }
126 // frame.modelList.add(frame.modelPopupMenu);
127 }
128
129 public MultiModelControlFrame getFrame() {
130 return frame;
131 }
132
133 /*
134 * (non-Javadoc)
135 *
136 * @see schmitzm.data.event.ObjectListener#performObjectEvent(schmitzm.data.event.ObjectEvent)
137 */
138 public void performObjectEvent(ObjectEvent e) {
139 // only listen for ChangeEvents
140 if (!(e instanceof ModelControlManager.ChangeEvent))
141 return;
142 ModelControlManager.ChangeEvent event = (ModelControlManager.ChangeEvent) e;
143 // if model was added:
144 if (event.getOldValue() == null && event.getNewValue() != null
145 && event.getNewValue() instanceof ModelControlFrame)
146 addModelControlFrame((ModelControlFrame) event.getNewValue());
147 // if model was removed
148 if (event.getOldValue() != null && event.getNewValue() == null
149 && event.getOldValue() instanceof ModelControlFrame)
150 removeModelControlFrame((ModelControlFrame) event.getOldValue());
151 }
152
153 /**
154 * @param model
155 */
156 private void addModelControlFrame(ModelControlFrame frame2) {
157 modelListModel.addElement(new ModelListObject(frame2,
158 frame2.getModel(), frame2.getModel().getName()));
159
160 }
161
162 /**
163 * Removes the model, which belongs to the specified ModelControlFrame from
164 * the list in the MCC
165 *
166 * @param frame2
167 * the ModelControlFrame from the removed model
168 */
169 private void removeModelControlFrame(ModelControlFrame frame2) {
170 // find the index of the model in the vector
171 for (int i = 0; i < modelListModel.size(); i++) {
172 ModelListObject m = (ModelListObject) modelListModel.get(i);
173 if (frame2.equals(m.getFrame()))
174 modelListModel.remove(i);
175 }
176 }
177
178 /**
179 * @returns the actually selected ModelListObject from the model list
180 */
181 private ModelListObject getSelectedModelListObject() {
182 return (ModelListObject) frame.modelList.getSelectedValue();
183
184 }
185
186 /*
187 * (non-Javadoc)
188 *
189 * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
190 */
191 public void valueChanged(ListSelectionEvent e) {
192 // TODO Auto-generated method stub
193 }
194
195 abstract class ModelCommand {
196 protected boolean finished = false;
197
198 public abstract String toString();
199
200 public void execute() {
201 finished = true;
202 }
203
204 public void reset() {
205 finished = false;
206 }
207
208 // /**
209 // * executed after all commands are executed
210 // */
211 // public void dispose()
212 // {
213 //
214 // }
215
216 /**
217 * @return true, if the execution is finished and no further execution
218 * is required
219 */
220 public boolean hasFinished() {
221 return finished;
222 }
223
224 /**
225 * tries to stop the execution of the command
226 */
227 public void stop() {
228 };
229
230 /**
231 * @return Message to be displayed in the console
232 */
233 public String startMessage() {
234 return null;
235 }
236
237 /**
238 * @return Message to be displayed
239 */
240 public String finshedMessage() {
241 return null;
242 }
243 }
244
245 class RepeatStartCommand extends ModelCommand {
246 private final int execTimes;
247
248 private int alreadyExec;
249
250 /**
251 * @param execTimes
252 */
253 public RepeatStartCommand(int execTimes) {
254 this.execTimes = execTimes;
255 alreadyExec = 0;
256 // TODO Auto-generated constructor stub
257 }
258
259 public String toString() {
260 return "Start Repeat (" + execTimes + " exec)";
261 }
262
263 /*
264 * (non-Javadoc)
265 *
266 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#finshedMessage()
267 */
268 @Override
269 public String finshedMessage() {
270 return "Starting Repeat (" + (alreadyExec) + "/" + execTimes + ")";
271 }
272
273 /*
274 * (non-Javadoc)
275 *
276 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#startMessage()
277 */
278 @Override
279 public String startMessage() {
280 return null;
281 }
282
283 /*
284 * (non-Javadoc)
285 *
286 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#execute()
287 */
288 @Override
289 public void execute() {
290 alreadyExec++;
291 finished = true;
292 }
293
294 public void reset() {
295 finished = false;
296 alreadyExec = 0;
297 }
298 }
299
300 /**
301 * The commands between start and stop are repeated
302 *
303 * @author Dominik Appl
304 */
305 class RepeatStopCommand extends ModelCommand {
306 private final int execTimes;
307
308 private int alreadyExec;
309
310 /**
311 * @param execTimes
312 */
313 public RepeatStopCommand(int execTimes) {
314 this.execTimes = execTimes;
315 alreadyExec = 0;
316 }
317
318 public String toString() {
319 return "End Repeat (" + execTimes + " exec)";
320 }
321
322 /*
323 * (non-Javadoc)
324 *
325 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#finshedMessage()
326 */
327 @Override
328 public String finshedMessage() {
329 return "Loop iteration finished.(" + alreadyExec + "/" + execTimes
330 + ")";
331 }
332
333 /*
334 * (non-Javadoc)
335 *
336 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#startMessage()
337 */
338 @Override
339 public String startMessage() {
340 return null;
341 }
342
343 /*
344 * (non-Javadoc)
345 *
346 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#execute()
347 */
348 @Override
349 public void execute() {
350 alreadyExec++;
351 if (alreadyExec == execTimes)
352 finished = true;
353 }
354
355 public void reset() {
356 finished = false;
357 alreadyExec = 0;
358 }
359 }
360
361 class StartCommand extends ModelCommand {
362 public String toString() {
363 return "------- START MODELLING -------";
364 }
365
366 /*
367 * (non-Javadoc)
368 *
369 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#finshedMessage()
370 */
371 @Override
372 public String finshedMessage() {
373 return "Starting execution...";
374 }
375
376 }
377
378 class StopCommand extends ModelCommand {
379 public String toString() {
380 return "------- MODELLING FINISHED -------";
381 }
382
383 /*
384 * (non-Javadoc)
385 *
386 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#finshedMessage()
387 */
388 @Override
389 public String finshedMessage() {
390 return "Finished execution";
391 }
392
393 /*
394 * (non-Javadoc)
395 *
396 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#startMessage()
397 */
398 @Override
399 public String startMessage() {
400 return null;
401 }
402 }
403
404 class ModelStepCommand extends ModelCommand {
405 private ModelControlFrame_Basic controlFrame;
406
407 private final Lock lock = new ReentrantLock();
408
409 private final Condition threadStillRunning = lock.newCondition();
410
411 private String name;
412
413 private XuluModel model;
414
415 private final int execTimes;
416
417 private int finishedExecutions = 0;
418
419 public void reset() {
420 finishedExecutions = 0;
421 }
422
423 /**
424 *
425 */
426 public ModelStepCommand(ModelListObject mlo, int execTimes) {
427 this.execTimes = execTimes;
428 if (!(mlo.getFrame() instanceof ModelControlFrame_Basic))
429 throw new UnsupportedOperationException(
430 "The modelframe must be an instance of ModelControlFrame_Basic");
431 controlFrame = (ModelControlFrame_Basic) mlo.getFrame();
432 name = mlo.getName();
433 model = mlo.getModel();
434 }
435
436 public void execute() {
437 // check first if the model must be initialised
438 if (!model.isInitialised() && !model.isRunning()) {
439 controlFrame.setModelResources();
440 controlFrame.getControlContainer().init();
441 }
442 lock.lock();
443 try {
444 WorkingThreadAdapter adapter = new WorkingThreadAdapter() {
445 /*
446 * (non-Javadoc)
447 *
448 * @see schmitzm.lang.WorkingThreadAdapter#threadPaused(schmitzm.lang.WorkingThread)
449 */
450 @Override
451 public void threadPaused(WorkingThread thread) {
452 try {
453 lock.lock();
454 // signal finished if the step is finished
455 threadStillRunning.signal();
456 } finally {
457 lock.unlock();
458 }
459 }
460
461 /*
462 * (non-Javadoc)
463 *
464 * @see schmitzm.lang.WorkingThreadAdapter#threadStopped(schmitzm.lang.WorkingThread)
465 */
466 @Override
467 public void threadStopped(WorkingThread thread) {
468 try {
469 lock.lock();
470 // signal finished if the step is finished
471 threadStillRunning.signal();
472 } finally {
473 lock.unlock();
474 }
475 }
476 };
477 controlFrame.getControlContainer().getModelThread()
478 .addThreadListener(adapter);
479 controlFrame.getControlContainer().step();
480 // wait for the model step to finish
481 threadStillRunning.await();
482 controlFrame.getControlContainer().getModelThread()
483 .removeThreadListener(adapter);
484 finishedExecutions++;
485 } catch (InterruptedException e) {
486 // TODO Auto-generated catch block
487 e.printStackTrace();
488 } finally {
489 lock.unlock();
490 }
491 }
492
493 public void stop() {
494 if (!model.isStopped())
495 controlFrame.getControlContainer().stop();
496 // try {
497 // controlFrame.getControlContainer().getModelThread().join();
498 // } catch (InterruptedException e) {
499 // // TODO Auto-generated catch block
500 // e.printStackTrace();
501 // }
502 }
503
504 @Override
505 public boolean hasFinished() {
506 return finishedExecutions >= execTimes;
507 }
508
509 /*
510 * (non-Javadoc)
511 *
512 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#toString()
513 */
514 @Override
515 public String toString() {
516 return name + " (" + execTimes + " exec)";
517 }
518
519 /*
520 * (non-Javadoc)
521 *
522 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#finshedMessage()
523 */
524 @Override
525 public String finshedMessage() {
526 return "...finished";
527 }
528
529 /*
530 * (non-Javadoc)
531 *
532 * @see appl.plugin.multimodelcontrol.MultiModelControlHandler.ModelCommand#startMessage()
533 */
534 @Override
535 public String startMessage() {
536 return "Executing step of " + name;
537 }
538
539 }
540
541 /*
542 * (non-Javadoc)
543 *
544 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
545 */
546 public void actionPerformed(ActionEvent e) {
547 if (e.getSource() == frame.addStepCommand) {
548 handleAddNewStep();
549 }
550 if (e.getSource() == frame.newOverAllStep) {
551 handleRepeatStep();
552 }
553 if (e.getSource() == frame.startButton) {
554 startInterpreting();
555 }
556 if (e.getSource() == frame.stopButton) {
557 if (interpretingThread != null) {
558 interpretingThread.stopThread();
559 }
560 // ToDO: dispose all models
561
562 }
563 if (e.getSource() == frame.clearModelSteps) {
564 int delIdx = frame.syncCommandList.getSelectedIndex();
565 // do not delete first or last entry
566 if (delIdx > 0 && delIdx < commandListModel.getSize() - 1)
567 commandListModel.remove(delIdx);
568 frame.syncCommandList.setSelectedIndex(delIdx);
569
570 }
571 }
572
573 /**
574 *
575 */
576 private void handleAddNewStep() {
577 if (checkInsertAllowed()) {
578 if (getSelectedModelListObject() == null) {
579 JOptionPane.showMessageDialog(null, "No model selected",
580 "No model selected", JOptionPane.ERROR_MESSAGE);
581 return;
582 }
583 int selIdx = frame.syncCommandList.getSelectedIndex();
584 int execTimes = 1;
585 // get execution times from user
586 try {
587 string = JOptionPane.showInputDialog(frame,
588 "How many steps do you want to execute for this enty?",
589 1);
590 execTimes = Integer.valueOf(string);
591 if (execTimes <= 0)
592 throw new UnsupportedOperationException(
593 "Only positive number allowed!");
594 } catch (Exception ex) {
595 JOptionPane.showMessageDialog(null,
596 "Only positive number allowed", "Error",
597 JOptionPane.ERROR_MESSAGE);
598 return;
599 }
600 commandListModel.add(selIdx + 1, new ModelStepCommand(
601 getSelectedModelListObject(), execTimes));
602 // select new entry
603 frame.syncCommandList.setSelectedIndex(selIdx + 1);
604 }
605 }
606
607 /**
608 *
609 */
610 protected void handleModelListDoubleClick() {
611 ModelListObject selectedModelListObject = getSelectedModelListObject();
612 if (selectedModelListObject != null) {
613 selectedModelListObject.getFrame().setVisible(true);
614 selectedModelListObject.getFrame().toFront();
615 }
616
617 }
618
619 /**
620 *
621 */
622 private void handleRepeatStep() {
623 if (checkInsertAllowed()) {
624 int selIdx = frame.syncCommandList.getSelectedIndex();
625 int execTimes = 1;
626 // get execution times from user
627 try {
628 string = JOptionPane.showInputDialog(frame,
629 "How many steps do you want to execute for this enty?",
630 1);
631 execTimes = Integer.valueOf(string);
632 if (execTimes <= 0)
633 throw new UnsupportedOperationException(
634 "Only positive numbers allowed!");
635 } catch (Exception ex) {
636 JOptionPane.showMessageDialog(null,
637 "Only positive numbers allowed", "Error",
638 JOptionPane.ERROR_MESSAGE);
639 return;
640 }
641 commandListModel.add(selIdx + 1, new RepeatStartCommand(execTimes));
642 commandListModel.add(selIdx + 2, new RepeatStopCommand(execTimes));
643
644 // select new entry
645 frame.syncCommandList.setSelectedIndex(selIdx + 1);
646 }
647 }
648
649 private void startInterpreting() {
650 // clear console and start Thread
651 frame.console.setText("");
652 interpretingThread = new InterpretingThread();
653 interpretingThread.start();
654
655 }
656
657 public void toggleGUI(boolean enabled) {
658 frame.modelList.setEnabled(enabled);
659 frame.addStepCommand.setEnabled(enabled);
660 frame.newOverAllStep.setEnabled(enabled);
661 frame.clearModelSteps.setEnabled(enabled);
662 if (enabled)
663 frame.syncCommandList.setSelectionBackground(Color.LIGHT_GRAY);
664 else
665 frame.syncCommandList.setSelectionBackground(Color.red);
666 }
667
668 /**
669 * insert is allowed if its not the last position
670 */
671 private boolean checkInsertAllowed() {
672 if (commandListModel.getSize() - 1 > frame.syncCommandList
673 .getSelectedIndex())
674 return true;
675 JOptionPane.showMessageDialog(null,
676 "You can add nothing after the end command!", "Error",
677 JOptionPane.ERROR_MESSAGE);
678 return false;
679 }
680
681 /**
682 * Interprets the commandlist
683 *
684 * @author Dominik Appl
685 */
686 class InterpretingThread extends Thread {
687
688 private boolean exit;
689
690 private ModelCommand currentCommand;
691
692 /**
693 * Creates a new Thread
694 */
695 public InterpretingThread() {
696 exit = false;
697 }
698
699 /**
700 * stops the Thread execution
701 */
702 public void stopThread() {
703 exit = true;
704 if (currentCommand != null)
705 currentCommand.stop();
706 }
707
708 public void run() {
709 toggleGUI(false);
710 // reset all commands
711 for (int i = 0; i < frame.syncCommandList.getModel().getSize(); i++)
712 ((ModelCommand) frame.syncCommandList.getModel()
713 .getElementAt(i)).reset();
714 // select first element
715 try {
716 frame.syncCommandList.setSelectedIndex(0);
717 int currentIdx = 0;
718 while (exit != true) {
719 currentCommand = (ModelCommand) commandListModel
720 .getElementAt(currentIdx);
721 // if the current command is an end of of a global loop
722 // than go back in the list until the start of the loop is
723 // found
724 if (currentCommand instanceof RepeatStopCommand) {
725 currentCommand.execute();
726 // if the all steps are done, just go on
727 if (currentCommand.hasFinished()) {
728 currentIdx++;
729 currentCommand = (ModelCommand) commandListModel
730 .getElementAt(currentIdx);
731 }
732 // else do the repetition by decreasing the index
733 // until the RepeatStartCommand is reached
734 else {
735 while (!(currentCommand instanceof RepeatStartCommand)) {
736 currentIdx--;
737 // if some structure error occured:
738 if (currentIdx <= 0) {
739 JOptionPane
740 .showMessageDialog(
741 frame,
742 "Something is wrong with the command structure. Do not use nested loops or other komplex structures!");
743 exit = true;
744 break;
745 }
746 currentCommand = (ModelCommand) commandListModel
747 .getElementAt(currentIdx);
748 }
749 }
750
751 }
752 if (currentCommand.startMessage() != null)
753 consoleStream.print(currentCommand.startMessage());
754 frame.syncCommandList.setSelectedIndex(currentIdx);
755 currentCommand.execute();
756 if (currentCommand.finshedMessage() != null)
757 consoleStream.println(currentCommand.finshedMessage());
758 // if the command has finished executing, get the next
759 // command
760 if (currentCommand.hasFinished())
761 currentIdx++;
762 if (currentIdx == commandListModel.getSize())
763 exit = true;
764 }
765 } catch (Exception e) {
766 e.printStackTrace();
767 } finally {
768 toggleGUI(true);
769 }
770 }
771 }
772
773 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26