EMMA Coverage Report (generated Sun Feb 05 10:43:15 CET 2012)
[all classes][desmoj.core.simulator]

COVERAGE SUMMARY FOR SOURCE FILE [Scheduler.java]

nameclass, %method, %block, %line, %
Scheduler.java0%   (0/1)0%   (0/35)0%   (0/3492)0%   (0/1091)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Scheduler0%   (0/1)0%   (0/35)0%   (0/3492)0%   (0/1091)
Scheduler (Experiment, String, EventList): void 0%   (0/1)0%   (0/47)0%   (0/11)
advanceTime (TimeInstant, TimeInstant): void 0%   (0/1)0%   (0/5)0%   (0/2)
getAllCurrentEntities (): List 0%   (0/1)0%   (0/30)0%   (0/5)
getCurrentEntity (): Entity 0%   (0/1)0%   (0/3)0%   (0/1)
getCurrentEvent (): EventAbstract 0%   (0/1)0%   (0/3)0%   (0/1)
getCurrentModel (): Model 0%   (0/1)0%   (0/3)0%   (0/1)
getCurrentSchedulable (): Schedulable 0%   (0/1)0%   (0/3)0%   (0/1)
getCurrentSimProcess (): SimProcess 0%   (0/1)0%   (0/3)0%   (0/1)
getExecutionSpeedRate (): double 0%   (0/1)0%   (0/3)0%   (0/1)
getSimClock (): SimClock 0%   (0/1)0%   (0/3)0%   (0/1)
isRandomizingConcurrentEvents (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
preemptSimProcess (EventNote): void 0%   (0/1)0%   (0/45)0%   (0/14)
presentTime (): TimeInstant 0%   (0/1)0%   (0/4)0%   (0/1)
processNextEventNote (): boolean 0%   (0/1)0%   (0/608)0%   (0/172)
reSchedule (Schedulable, TimeInstant): void 0%   (0/1)0%   (0/114)0%   (0/51)
reSchedule (Schedulable, TimeSpan): void 0%   (0/1)0%   (0/102)0%   (0/40)
realTimeSchedule (RealTimeEventWrapper): void 0%   (0/1)0%   (0/72)0%   (0/28)
schedule (Entity, Entity, Entity, EventOf3Entities, TimeInstant): void 0%   (0/1)0%   (0/214)0%   (0/76)
schedule (Entity, Entity, Entity, EventOf3Entities, TimeSpan): void 0%   (0/1)0%   (0/196)0%   (0/67)
schedule (Entity, Entity, EventOf2Entities, TimeInstant): void 0%   (0/1)0%   (0/166)0%   (0/60)
schedule (Entity, Entity, EventOf2Entities, TimeSpan): void 0%   (0/1)0%   (0/148)0%   (0/51)
schedule (Entity, EventAbstract, TimeInstant): void 0%   (0/1)0%   (0/170)0%   (0/62)
schedule (Entity, EventAbstract, TimeSpan): void 0%   (0/1)0%   (0/150)0%   (0/52)
scheduleAfter (Schedulable, Entity, Entity, Entity, EventOf3Entities): void 0%   (0/1)0%   (0/213)0%   (0/62)
scheduleAfter (Schedulable, Entity, Entity, EventOf2Entities): void 0%   (0/1)0%   (0/168)0%   (0/48)
scheduleAfter (Schedulable, Entity, EventAbstract): void 0%   (0/1)0%   (0/181)0%   (0/55)
scheduleBefore (Schedulable, Entity, Entity, Entity, EventOf3Entities): void 0%   (0/1)0%   (0/188)0%   (0/60)
scheduleBefore (Schedulable, Entity, Entity, EventOf2Entities): void 0%   (0/1)0%   (0/144)0%   (0/46)
scheduleBefore (Schedulable, Entity, EventAbstract): void 0%   (0/1)0%   (0/146)0%   (0/47)
sendDebugNote (String): void 0%   (0/1)0%   (0/16)0%   (0/4)
setExecutionSpeedRate (double): void 0%   (0/1)0%   (0/16)0%   (0/6)
setRandomizingConcurrentEvents (boolean): void 0%   (0/1)0%   (0/54)0%   (0/16)
signalStop (): void 0%   (0/1)0%   (0/13)0%   (0/5)
simFinished (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/255)0%   (0/41)

1package desmoj.core.simulator;
2 
3import java.util.LinkedList;
4import java.util.List;
5import java.util.concurrent.LinkedBlockingQueue;
6import java.util.concurrent.TimeUnit;
7import java.util.concurrent.locks.ReentrantLock;
8import desmoj.core.report.DebugNote;
9 
10/**
11 * The scheduler is the main element controlling the run of a simulation. It
12 * controls the event-list in which all scheduled events are stored, picks the
13 * next event to be processed and advances the simulation clock accordingly.
14 * 
15 * @version DESMO-J, Ver. 2.3.3 copyright (c) 2011
16 * @author Tim Lechler, modified by Ruth Meyer, Justin Neumann
17 * 
18 *         Licensed under the Apache License, Version 2.0 (the "License"); you
19 *         may not use this file except in compliance with the License. You may
20 *         obtain a copy of the License at
21 *         http://www.apache.org/licenses/LICENSE-2.0
22 * 
23 *         Unless required by applicable law or agreed to in writing, software
24 *         distributed under the License is distributed on an "AS IS" BASIS,
25 *         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
26 *         implied. See the License for the specific language governing
27 *         permissions and limitations under the License.
28 * 
29 */
30public class Scheduler extends NamedObject {
31 
32        /**
33         * The experiment this scheduler serves.
34         */
35        protected Experiment myExperiment;
36 
37        /**
38         * The actual simulation clock for this scheduler.
39         */
40        protected SimClock clock;
41 
42        /**
43         * The event-list used by the scheduler.
44         */
45        protected EventList evList;
46 
47        /**
48         * Flag to indicate whether the current simulation is running or stopped. If
49         * true, the simulation is stopped, if false, the simulation is still
50         * running. This flag is especially polled by processes exiting any
51         * synchronized method used for passivating the process thus giving control
52         * back to the scheduler.
53         */
54        protected boolean simulationFinished;
55 
56        /**
57         * Contains the event-note used by the current Schedulables.
58         */
59        private EventNote _currentNote;
60 
61        /**
62         * Contains the current active Entity.
63         */
64        private Entity _currentEntity1;
65        
66        /**
67         * Contains the current active Entity.
68         */
69        private Entity _currentEntity2;
70        
71        /**
72         * Contains the current active Entity.
73         */
74        private Entity _currentEntity3;
75 
76        /**
77         * Contains the current active SimProcess.
78         */
79        private SimProcess _currentProcess;
80 
81        /**
82         * Contains the current active Event.
83         */
84        private EventAbstract _currentEvent;
85 
86        /**
87         * Contains the current active model.
88         */
89        private Model _currentModel;
90 
91        /**
92         * Contains the current active Schedulable. This is either the entity or
93         * simProcess if available, or the external event, if none of the first two
94         * are available.
95         */
96        private Schedulable _currentSchedulable;
97 
98        /**
99         * Flag indicating if the event-list will process concurrent Events in
100         * random order or not. Default is not (<code>false</code>). (Modification
101         * by Ruth Meyer, 11/2001)
102         */
103        private boolean _randomizingConcurrentEvents = false;
104 
105        /**
106         * The execution speed rate. Default is zero (as-fast-as-possible).
107         * (Modification by Felix Klueckmann, 05/2009)
108         */
109        private double _executionSpeedRate = 0.0;
110 
111        /**
112         * The point in physical time (real time) of the last change of the
113         * execution speed rate (in nanoseconds). (Modification by Felix Klueckmann,
114         * 05/2009)
115         */
116        private long _realTimeAtResetInNanos;
117        
118        /**
119         * The point in simulation time of the last change of the execution speed
120         * rate or the last time the simulation was stopped . (Modification by Felix
121         * Klueckmann, 05/2009)
122         */
123        private TimeInstant _simulationTimeAtReset;
124 
125        /**
126         * Flag indicating if the the execution speed rate was changed or the
127         * experiment was stopped since the last call of processNextEventNote().
128         * (Modification by Felix Klueckmann, 05/2009)
129         */
130        private boolean _timeReset;
131 
132        /**
133         * Lock for process synchronisation during a realtime execution.
134         * (Modification by Felix Klueckmann, 06/2009)
135         */
136        private ReentrantLock _lock;
137 
138        /**
139         * The condition used for process synchronisation during a realtime
140         * execution.
141         */
142        private java.util.concurrent.locks.Condition _waitSynchCondition;
143 
144        /**
145         * A threadsafte consumer/producer queue to store
146         * RealTimeEventWrapper-Objects send by external systems
147         */
148        private java.util.concurrent.BlockingQueue<RealTimeEventWrapper> _realTimeEventQueue;
149 
150        /**
151         * Constructs a scheduler with given name and the event-list (i.e. inheritor
152         * of <code>desmoj.core.simulator.EventList</code>) to use.
153         * 
154         * @param exp
155         *            Experiment : The experiment that uses this Scheduler
156         * @param name
157         *            java.lang.String : The scheduler's name
158         * @param eventList
159         *            EventList : The event-list to store scheduled events
160         */
161 
162        public Scheduler(Experiment exp, String name, EventList eventList) {
163 
164                super(name + "_scheduler"); // create a namedObject with given name
165                myExperiment = exp;
166                evList = eventList;
167                clock = new SimClock(name); // set reference to clock
168                simulationFinished = false; // set flag to "not yet finished",
169                _lock = new ReentrantLock();
170                _waitSynchCondition = _lock.newCondition();
171                _realTimeEventQueue = new LinkedBlockingQueue<RealTimeEventWrapper>();
172        }
173 
174        /**
175         * Returns the actual simulation time as displayed by the simulation clock.
176         * 
177         * @return TimeInstant : The current point in simulation time
178         */
179        protected TimeInstant presentTime() {
180 
181                return clock.getTime();
182 
183        }
184 
185        /**
186         * Returns the currently active Entity. Returns <code>null</code> if the current
187         * Schedulable happens to be an external event or a simprocess.
188         * Note that in case the current Event refers to more than one entity
189         * (<code>EventOfTwoEntities</code>, <code>EventOfThreeEntitties</code>),
190         * only the first entity is returned; to obtain all such entities,
191         * use <code>getAllCurrentEntities()</code> instead.
192         * 
193         * @return Entity : The currently active Entity or
194         *         <code>null</code> in case of an external event or a simprocess
195         *         being the currently active Schedulable
196         */
197        protected Entity getCurrentEntity() {
198 
199                return _currentEntity1;
200 
201        }
202        
203    /**
204     * Returns the currently active entities. Returns an empty list 
205     * if the current Schedulable happens to be an external event or a sim-process.
206     * 
207     * @return List<Entity> : A list containing the currently active entities
208     */
209        protected List<Entity> getAllCurrentEntities() {
210 
211        List<Entity> entities = new LinkedList<Entity>();
212        if (_currentEntity1 != null) entities.add(_currentEntity1);
213        if (_currentEntity2 != null) entities.add(_currentEntity2);
214        if (_currentEntity3 != null) entities.add(_currentEntity3);
215            
216        return entities;
217 
218    }
219        
220 
221        /**
222         * Returns the current active Event or <code>null</code>. Note that this
223         * method can also return an external event that can not be handled like an
224         * Event since it does not support scheduling together with an entity.
225         * Returns <code>null</code> if the current Schedulable happens to be a
226         * Sim-process that has been activated, thus no kind of Event is associated
227         * with it.
228         * 
229         * @return Event : The currently active Event or external event or
230         *         <code>null</code> if the current Schedulable happens to be an
231         *         activated SimProcess
232         */
233        protected EventAbstract getCurrentEvent() {
234 
235                return _currentEvent;
236 
237        }
238 
239        /**
240         * Returns the currently active model.
241         * 
242         * @return Model : The currently active model or <code>null</code> in case
243         *         of no model being connected so far.
244         */
245        protected Model getCurrentModel() {
246 
247                return _currentModel;
248 
249        }
250 
251        /**
252         * Returns the currently active Schedulable object. This can be any of its
253         * subtypes Entity, SimProcess or external event in that order.
254         * For events referring to multiple enities, the first entity is returned. 
255         * 
256         * @return Schedulable : The currently active Schedulable
257         * @see Entity
258         * @see SimProcess
259         * @see ExternalEvent
260         */
261        protected Schedulable getCurrentSchedulable() {
262 
263                return _currentSchedulable;
264 
265        }
266 
267        /**
268         * Returns the current SimProcess. Note that this method can only return a
269         * Sim-process. If the currently active Schedulable is not instance of
270         * Sim-process or an external event, <code>null</code> is returned.
271         * 
272         * @return SimProcess : The currently active SimProcess or <code>null</code>
273         */
274        protected SimProcess getCurrentSimProcess() {
275 
276                return _currentProcess;
277 
278        }
279 
280        /**
281         * Returns the current execution Speed Rate.
282         * 
283         * @return double : The current execution speed rate.
284         */
285        protected double getExecutionSpeedRate() {
286                return _executionSpeedRate;
287        }
288 
289        /**
290         * Returns the actual clock for this model.
291         * 
292         * @return SimClock : The actual clock for simulation time
293         */
294        protected SimClock getSimClock() {
295 
296                return clock; // not much else to do
297 
298        }
299 
300        /**
301         * Returns if the event-list processes concurrent Events in random order or
302         * not.
303         * 
304         * @return boolean: <code>true</code> if concurrent Events are randomized,
305         *         <code>false</code> otherwise
306         * @author Ruth Meyer
307         */
308        public boolean isRandomizingConcurrentEvents() {
309                return this._randomizingConcurrentEvents;
310        }
311 
312        /**
313         * Preempts the currently running SimProcess. Method is called whenenver
314         * another Entity or SimProcess is scheduled with <code>TimeSpan.ZERO</code>
315         * or <code>presentTime()</code> as parameter for the simulation time. The
316         * current SimProcess is interrupted and will be scheduled to continue its
317         * lifecycle
318         * 
319         * @param preemptNote
320         *            EventNote - The event-note of the Schedulable preempting
321         *            the current SimProcess
322         */
323        void preemptSimProcess(EventNote preemptNote) {
324 
325                if (_currentProcess == null) {
326                        myExperiment.sendWarning("Can't preempt current SimProcess! "
327                                        + "Command ignored.", "Scheduler : " + getName()
328                                        + " Method: preemptSimProcess(EventNote preemptNote)",
329                                        "The event-note reference passed as parameter is a null "
330                                                        + "reference.",
331                                        "Always make sure to use valid references only.");
332                        return; // preemption of currentprocess only
333                }
334 
335                preemptNote.setTime(presentTime());
336 
337                EventNote currentNote = new EventNote(_currentProcess, null,
338                                presentTime());
339 
340                evList.insertAsFirst(currentNote); // schedule currentProcess..
341                evList.insertAsFirst(preemptNote);
342                // ..to be next after preempting SimPr.
343                _currentProcess.passivate(); // and set current to sleep until then
344 
345        }
346 
347        /**
348         * Processes the next event-note on the event-list. Returns <code>true</code>
349         * if that EventNote has been processed correctly, <code>false</code> if an
350         * error occurred or the event-list is empty.
351         * 
352         * @return boolean : Is <code>true</code> if the next event-note was
353         *         processed correctly, <code>false</code> if not
354         */
355        protected boolean processNextEventNote() {
356                // check if there still are Event notes to be processed
357                if (!(_executionSpeedRate > 0)) {
358                        if (evList.isEmpty()) {
359                                return false; // no more EventNote available -> exit
360                        }
361                } else {
362 
363                        while (true) {
364                                this._lock.lock();
365                                if (evList.isEmpty() && _realTimeEventQueue.isEmpty()) {
366                                        // no Event waiting
367                                        _lock.unlock();
368                                        return false;
369                                }
370                                if (myExperiment.isStopped()) {
371                                        // experiment has been stopped
372                                        _lock.unlock();
373                                        return true; // there is an event
374                                }
375                                if (_timeReset) {
376                                        this._realTimeAtResetInNanos = System.nanoTime();
377                                        this._simulationTimeAtReset = presentTime();
378                                        this._timeReset = false;
379                                }
380 
381                                while (!_realTimeEventQueue.isEmpty()) {
382                                        // an event has been sent by an external system
383 
384                                        RealTimeEventWrapper currentRealTimeWrapper = _realTimeEventQueue
385                                                        .poll();// get the next RealTimeEventWrapper and
386                                        // remove it from the queue
387                                        ExternalEvent currentRealTimeEvent = currentRealTimeWrapper
388                                                        .getExternalEvent();// get the encapsulated
389                                        // ExternalEvent
390 
391                                        long weightedRealTimeEventNanos = (long) ((currentRealTimeWrapper
392                                                        .getNanos() - _realTimeAtResetInNanos) * _executionSpeedRate);
393 
394                                        if (weightedRealTimeEventNanos < 0) {
395                                                // the ExternalEvent is in the future
396                                                myExperiment
397                                                                .sendWarning(
398                                                                                "Can not schedule real time external event! "
399                                                                                                + "The external event is discarded.",
400                                                                                "Scheduler of experiment "
401                                                                                                + myExperiment.getName()
402                                                                                                + " Method processNextEventNote() "
403                                                                                                + "external event: "
404                                                                                                + currentRealTimeEvent
405                                                                                                                .getName()
406                                                                                                + " deviation in nanoseconds: "
407                                                                                                + -weightedRealTimeEventNanos,
408                                                                                "The given real-time time stamp is in the future.",
409                                                                                "Real-time events are not supposed to be scheduled in the (real time) future.");
410                                        } else {
411 
412                                                TimeInstant realTimeNanosEquivalent = TimeOperations
413                                                                .add(_simulationTimeAtReset, new TimeSpan(
414                                                                                weightedRealTimeEventNanos,
415                                                                                TimeUnit.NANOSECONDS));
416                                                // calculate the simulation time equivalent to
417                                                // the real-time time stamp of the external event
418 
419                                                if (TimeInstant.isAfterOrEqual(realTimeNanosEquivalent,
420                                                                presentTime())) {
421                                                        // the event can be scheduled correctly
422                                                        currentRealTimeEvent
423                                                                        .schedule(realTimeNanosEquivalent);
424                                                } else {
425                                                        // the simulation time of the event is in the past
426                                                        currentRealTimeEvent.schedule(presentTime());
427 
428                                                        myExperiment
429                                                                        .sendWarning(
430                                                                                        "Can not schedule real time external event at the simulation time equivalent to the given timeStamp! "
431                                                                                                        + "The external event is scheduled at the present simulation time instead.",
432                                                                                        "Scheduler of experiment "
433                                                                                                        + myExperiment.getName()
434                                                                                                        + " Method processNextEventNote() "
435                                                                                                        + "external event: "
436                                                                                                        + currentRealTimeEvent
437                                                                                                                        .getName()
438                                                                                                        + " deviation in nanoseconds: "
439                                                                                                        + (presentTime()
440                                                                                                                        .getTimeTruncated(
441                                                                                                                                        TimeUnit.NANOSECONDS) - weightedRealTimeEventNanos),
442                                                                                        "The simulation time equivalent of the given time stamp is before the current simulation time. Can not perform a rollback.",
443                                                                                        "Check if this deviation constitutes a problem.");
444                                                }
445 
446                                        }
447 
448                                }
449 
450                                // System.out.println("--------------------------");
451                                // if (!evList.isEmpty()) {
452                                // EventNote note = evList.firstNote();
453                                // System.out.println(note.toString());
454                                // while (!(note == evList.lastNote())) {
455                                // System.out.println(evList.nextNote(note));
456                                // note = evList.nextNote(note);
457                                // }
458                                // System.out.println("--------------------------");
459                                // }
460                                // test code by felix
461 
462                                _currentNote = evList.firstNote(); // get next event-note
463                                long weightedTimeSinceReset = (long) ((System.nanoTime() - _realTimeAtResetInNanos) * _executionSpeedRate);
464                                // calculate the real time passed since the last time reset
465                                // considering the execution speed rate
466 
467                                long timeToWait = (long) ((TimeOperations.diff(
468                                                _currentNote.getTime(), _simulationTimeAtReset)
469                                                .getTimeTruncated(TimeUnit.NANOSECONDS) - weightedTimeSinceReset) / _executionSpeedRate);
470                                // calculate the time the thread has to wait
471                                if (timeToWait > 0) {
472                                        // there is a need to wait
473                                        try {
474                                                _waitSynchCondition.awaitNanos(timeToWait);
475 
476                                        } catch (InterruptedException e) {
477                                                e.printStackTrace();
478                                        } finally {
479                                                this._lock.unlock();
480                                        }
481                                } else {
482                                        this._lock.unlock();
483                                }
484                                if (!_timeReset && _realTimeEventQueue.isEmpty()) {
485                                        break;
486                                }
487 
488                        }
489                }
490                _currentNote = evList.firstNote(); // get next event-note
491                TimeInstant nextTime = _currentNote.getTime();
492                // check if the next event-note is in the future
493                if (TimeInstant.isAfter(nextTime, presentTime())) {
494                        this.advanceTime(presentTime(), nextTime);
495                } else {
496                        // throw an exception if the next event-note is in the past
497                        if (TimeInstant.isBefore(nextTime, presentTime())) {
498                                throw (new desmoj.core.exception.SimAbortedException(
499                                                new desmoj.core.report.ErrorMessage(
500                                                                null,
501                                                                "The simulation Time of the next event is in the past! Simulation aborted.",
502                                                                "Class : Scheduler  Method : processNextEventNote()",
503                                                                "the simulation time of the next event-note ("
504                                                                                + _currentNote
505                                                                                + ") is before the current simulation time : "
506                                                                                + presentTime(),
507                                                                "Make sure not to schedule events in the past.",
508                                                                null)));
509                        }
510                }
511                // update the clock and its observers
512 
513                // changes to event-list and 'current' variables can only be made after
514                // every
515                // Observer registered with the clock has made their updates
516 
517                // take EventNote from EventList
518                evList.remove(_currentNote);
519 
520                // set 'current' variables
521                // determine Entity and SimProcess, if applicable
522                _currentEntity1 = _currentNote.getEntity1(); // multiple entities
523                _currentEntity2 = _currentNote.getEntity2();
524                _currentEntity3 = _currentNote.getEntity3();
525                
526                _currentProcess = null;
527                _currentSchedulable = null;
528 
529                if (_currentEntity1 != null) 
530                {
531                        _currentModel = _currentEntity1.getModel();
532                        _currentSchedulable = _currentEntity1;
533                        _currentEntity1.removeEventNote(_currentNote);
534                        if (_currentEntity1 instanceof SimProcess) { // a real SimProcess
535                                _currentProcess = (SimProcess) _currentEntity1;
536                        }
537                }
538        if (_currentEntity2 != null) 
539        {
540            _currentEntity2.removeEventNote(_currentNote);
541        }
542        if (_currentEntity3 != null) 
543        {
544            _currentEntity3.removeEventNote(_currentNote);
545        }
546        
547                // determine Event resp. external event
548                _currentEvent = _currentNote.getEvent();
549                
550                if (_currentEvent != null && _currentProcess == null) {
551 
552                        _currentEvent.removeEventNote(_currentNote);
553 
554                        if (_currentSchedulable == null) {
555 
556                                _currentSchedulable = _currentEvent;
557                                _currentModel = _currentEvent.getModel();
558                        }
559                }
560 
561                // just check if everything is still allright
562                // currSched. must have been set to something other than null by now
563                // otherwise : throw (new desmoj.exception.DESMOJException());
564                if (_currentSchedulable == null)
565                        return false;
566 
567                // clear time value and discard EventNote
568                _currentNote.setTime(null);
569                _currentNote = null;
570 
571                // determine if event-oriented or process-oriented
572                if (_currentEvent != null) { // event-oriented
573 
574                        if (_currentEvent.getNumberOfEntities()==1) // Event for one entity
575                        {
576                                ((Event<Entity>) _currentEvent).eventRoutine(_currentEntity1);
577                        }
578                        
579                        else if (_currentEvent.getNumberOfEntities()==2)// Event for two entities
580                        {
581                                ((EventOf2Entities<Entity, Entity>) _currentEvent).eventRoutine(_currentEntity1, _currentEntity2);
582                        }
583                        
584                        else if (_currentEvent.getNumberOfEntities()==3)// Event for three entities
585                        {
586                                ((EventOf3Entities<Entity, Entity, Entity>) _currentEvent).eventRoutine(_currentEntity1, _currentEntity2, _currentEntity3);
587                        }
588                        
589                        else //external event!
590                        {
591                                ((ExternalEvent) _currentEvent).eventRoutine();
592                        }
593                        
594                        // this is where it all happens
595                } else { // process-oriented
596 
597                        // The current SimProcess to hand control over to may have terminated
598                        // already
599                        // so the scheduler must not start it
600                        if (!_currentProcess.isTerminated()) {
601 
602                                // The current SimProcess can either be running, thus waiting in a
603                                // block
604                                // or still not have been started
605                                if (_currentProcess.isReady()) {
606                                        // currentProcess is already running
607 
608                                        // main thread passes control over to currentProcess'
609                                        // SimThread
610                                        // executing the sim-process' lifeCycle method until
611                                        // hold / passivate
612                                        // or end of lifeCycle
613                                        _currentProcess.resume();
614 
615                                } else { // currentProcess is starting for the first time
616 
617                                        _currentProcess.start(); // start him up
618 
619                                }
620 
621                                // when hold / passivate or end of lifeCycle are passed, the
622                                // control
623                                // is handed back to the main thread here and there's nothing
624                                // else to do
625                                // but return true to state that this event-note has been
626                                // processed correctly
627 
628                        } else {
629                                // this must not happen, but we check on it anyway
630                                myExperiment
631                                                .sendWarning("Can not activate scheduled SimProcess! "
632                                                                + "Command ignored.",
633                                                                "Scheduler of experiment "
634                                                                                + myExperiment.getName()
635                                                                                + " Method processNextEventNote() "
636                                                                                + "SimProcess : "
637                                                                                + _currentProcess.getName(),
638                                                                "The sim-process to be activated to take over control has "
639                                                                                + "already terminated.",
640                                                                "Internal DESMOJ-Error. Please report to DESMOJ-Support.");
641                        }
642 
643                }
644                if (_executionSpeedRate > 0) {
645                        // calculate deviation
646                        long simTimeSinceReset = TimeOperations.diff(presentTime(),
647                                        _simulationTimeAtReset).getTimeTruncated(
648                                        TimeUnit.NANOSECONDS);
649                        long realTimeSinceReset = (System.nanoTime() - _realTimeAtResetInNanos);
650                        long deviationInNanoseconds = (long) (realTimeSinceReset - (simTimeSinceReset / _executionSpeedRate));
651                        // System.out.println("SimTimeSinceReset: " + simTimeSinceReset
652                        // + ", RealTimeSinceReset: " + realTimeSinceReset
653                        // + ", Weighted deviation: " + deviationInNanoseconds);
654 
655                        if (_currentEvent != null) {
656                                // event-oriented
657 
658                                long deadLine = _currentEvent.getRealTimeConstraint();
659                                // the deadLine of this event
660 
661                                if (deadLine > 0 && deadLine < deviationInNanoseconds) {
662                                        // the real-time deadline was missed
663                                        myExperiment.sendWarning(
664                                                        "The real-time deadline of this event was missed!",
665                                                        "Scheduler of experiment " + myExperiment.getName()
666                                                                        + " Method processNextEventNote() "
667                                                                        + "Event : " + _currentEvent.getName(),
668                                                        "The real-time deadline of this event was "
669                                                                        + deadLine + " nanoseconds. It was missed by "
670                                                                        + (deviationInNanoseconds - deadLine)
671                                                                        + " nanoseconds.",
672                                                        "Check if the deadline can be met.");
673                                }
674                        } else {
675                                // process-oriented
676 
677                                long deadLine = _currentProcess.getRealTimeConstraint();
678                                // the deadLine of this SimProcess
679 
680                                if (deadLine > 0 && deadLine < deviationInNanoseconds) {
681                                        // the real-time deadline was missed
682                                        myExperiment
683                                                        .sendWarning(
684                                                                        "The real-time deadline of this SimProcess was missed!",
685                                                                        "Scheduler of experiment "
686                                                                                        + myExperiment.getName()
687                                                                                        + " Method processNextEventNote() "
688                                                                                        + "SimProcess : "
689                                                                                        + _currentProcess.getName(),
690                                                                        "The real-time deadline of this SimProcess was "
691                                                                                        + deadLine
692                                                                                        + " nanoseconds. It was missed by "
693                                                                                        + (deviationInNanoseconds - deadLine)
694                                                                                        + " nanoseconds.",
695                                                                        "Check if the deadline can be met.");
696                                }
697                        }
698 
699                }
700 
701                return true; // everything processed alright
702 
703        }
704        
705    /**
706     * This method is called to notify simulator about the time 
707     * passed between the execution of two events with a positive 
708     * (non-zero) offset. The implementation of this method just
709     * sets the scheduler's clock to the new instant; note, though,
710     * that extensions to DESMO-J may overwrite this method
711     * to conduct more complex operations, e.g. extrapolate 
712     * variables in continuous simulation.        
713     * 
714     * @param now
715     *          TimeInstant : The current point in simulation time
716     * @param next
717     *          TimeInstant : The next point in simulation time to 
718     *              advance the clock to (e.g. instant of the next event) 
719     */
720    protected void advanceTime(TimeInstant now, TimeInstant next) {
721        
722        // just update the simulation clock to the instant of
723        // the next event
724        clock.setTime(next);
725    }
726        
727 
728        /**
729         * Schedules the external event to happen at the simulation time equivalent
730         * to the current value of wall-clock time.
731         * 
732         * @param what
733         *            ExternalEvent : The external event to be scheduled
734         * 
735         */
736        protected void realTimeSchedule(RealTimeEventWrapper what) {
737                if (!myExperiment.isRunning()) {
738                        myExperiment
739                                        .sendWarning(
740                                                        "Can not schedule real time external event! Command ignored.",
741                                                        "Experiment '"
742                                                                        + getName()
743                                                                        + "' method void realTimeSchedule(ExternalEvent what).",
744                                                        "The experiment is not running.",
745                                                        "events can only be scheduled when the exeriment is running.");
746                        return;
747                }
748                if (what == null) { // check for null reference
749                        myExperiment.sendWarning("Can't schedule ExternalEvent! "
750                                        + "Command ignored.", "Scheduler : " + getName()
751                                        + " Method: realTimeSchedule(ExternalEvent what)",
752                                        "The ExternalEvent reference passed is a "
753                                                        + "null references.",
754                                        "Always make sure to use valid references only.");
755                        return;
756                }
757 
758                try {
759                        // put the given Event wrapper into the thread-safe Event queue
760                        _realTimeEventQueue.put(what);
761                } catch (InterruptedException e) {
762                        myExperiment.sendWarning("Can't schedule external event! "
763                                        + "Command ignored.", "Scheduler : " + getName()
764                                        + " Method: realTimeSchedule(ExternalEvent who)",
765                                        "The Thread waiting to schedule the given external event "
766                                                        + "was interrupted.",
767                                        "A Thread has to wait until space becomes available");
768 
769                }
770                _lock.lock();
771                _waitSynchCondition.signal();// signal that a new real time Event is
772                // available
773                _lock.unlock();
774        }
775 
776        /**
777         * Schedules the event to happen after a specified time. Checks that only
778         * legal combinations of valid parameters are scheduled.
779         * <p>
780         * <DIV align=center>
781         * <TABLE BORDER >
782         * <CAPTION>Valid scheduling types </CAPTION>
783         * <TR>
784         * <TH><DIV align=center>scheduling type</TH>
785         * <TH>Entity object</TH>
786         * <TH>Event object</TH>
787         * </TR>
788         * <TR>
789         * <TH>Event oriented</TH>
790         * <TD>Event or SimProcess</TD>
791         * <TD>Event</TD>
792         * </TR>
793         * <TR>
794         * <TH>process oriented</TH>
795         * <TD>SimProcess</TD>
796         * <TD>null</TD>
797         * </TR>
798         * <TR>
799         * <TH>external event</TH>
800         * <TD>null</TD>
801         * <TD>external event</TD>
802         * </TR>
803         * </TABLE>
804         * </DIV>
805         * 
806         * @param who
807         *            Entity : The Entity to be scheduled
808         * @param dt
809         *            TimeSpan : The point in simulation time for the event to happen
810         *            as an offset to the current simulation time
811         */
812        protected void reSchedule(Schedulable who, TimeSpan dt) {
813 
814                if (dt == null) {
815                        myExperiment
816                                        .sendWarning(
817                                                        "Can't reschedule Schedulable at given time! "
818                                                                        + "Command ignored.",
819                                                        "Scheduler : "
820                                                                        + getName()
821                                                                        + " Method: reSchedule(Schedulable who, TimeSpan dt)",
822                                                        "The simulation time reference passed as parameter is a "
823                                                                        + "null reference.",
824                                                        "Always make sure to use valid references only.");
825                        return; // time missing
826                }
827 
828                if (who == null) {
829                        myExperiment
830                                        .sendWarning(
831                                                        "Can't reschedule Schedulable at given time! "
832                                                                        + "Command ignored.",
833                                                        "Scheduler : "
834                                                                        + getName()
835                                                                        + " Method: reSchedule(Schedulable who, TimeSpan dt)",
836                                                        "The Schedulable reference passed as parameter is a "
837                                                                        + "null reference.",
838                                                        "Always make sure to use valid references only.");
839                        return; // Schedulable missing
840                }
841 
842                if (!who.isScheduled()) {
843                        myExperiment
844                                        .sendWarning(
845                                                        "Can't reschedule Schedulable at given time! "
846                                                                        + "Command ignored.",
847                                                        "Scheduler : "
848                                                                        + getName()
849                                                                        + " Method: reSchedule(Schedulable who, TimeSpan dt)",
850                                                        "The Schedulable given is not scheduled, thus can not be "
851                                                                        + "rescheduled.",
852                                                        "To reschedule a Schedulable, it must already be scheduled. "
853                                                                        + "You can check that by calling the Schedulable's "
854                                                                        + "isScheduled() method");
855                        return;
856                        // I can't be rescheduled, I haven't even been scheduled yet
857                }
858 
859                // all parameters checked, now remove the Schedulable's EventNote
860                // first...
861                List<EventNote> notes = who.getEventNotes();
862                for (EventNote note : notes) {
863                    evList.remove(note);
864                    note.setTime(TimeOperations.add(presentTime(), dt));
865    
866                    if (dt == TimeSpan.ZERO) { // preempting schedule for processes
867    
868                            if (_currentProcess == null) { // currently Event -> no preemption
869                                    // inserted as first in the event-list with the current time as
870                                    // activation
871                                    evList.insertAsFirst(note);
872    
873                            } else { // currently SimProcess -> preempt!
874    
875                                    preemptSimProcess(note);
876                            }
877    
878                    } else {
879    
880                        // all parameters checked, now reinsert note
881                        evList.insert(note);
882    
883                    }
884                }
885        }
886        
887           /**
888     * Schedules the event to happen at the specified time. Checks that only
889     * legal combinations of valid parameters are scheduled.
890     * <p>
891     * <DIV align=center>
892     * <TABLE BORDER >
893     * <CAPTION>Valid scheduling types </CAPTION>
894     * <TR>
895     * <TH><DIV align=center>scheduling type</TH>
896     * <TH>Entity object</TH>
897     * <TH>Event object</TH>
898     * </TR>
899     * <TR>
900     * <TH>Event oriented</TH>
901     * <TD>Event or SimProcess</TD>
902     * <TD>Event</TD>
903     * </TR>
904     * <TR>
905     * <TH>process oriented</TH>
906     * <TD>SimProcess</TD>
907     * <TD>null</TD>
908     * </TR>
909     * <TR>
910     * <TH>external event</TH>
911     * <TD>null</TD>
912     * <TD>external event</TD>
913     * </TR>
914     * </TABLE>
915     * </DIV>
916     * 
917     * @param who
918     *            Entity : The Entity to be scheduled
919     * @param time
920     *            TimeInstant : The point in simulation time for the event to happen
921     */
922        protected void reSchedule(Schedulable who, TimeInstant time) {
923 
924        if (time == null) {
925            myExperiment
926                    .sendWarning(
927                            "Can't reschedule Schedulable at given time! "
928                                    + "Command ignored.",
929                            "Scheduler : "
930                                    + getName()
931                                    + " Method: reSchedule(Schedulable who, TimeInstant time)",
932                            "The simulation time reference passed as parameter is a "
933                                    + "null reference.",
934                            "Always make sure to use valid references only.");
935            return; // time missing
936        }
937 
938        if (who == null) {
939            myExperiment
940                    .sendWarning(
941                            "Can't reschedule Schedulable at given time! "
942                                    + "Command ignored.",
943                            "Scheduler : "
944                                    + getName()
945                                    + " Method: reSchedule(Schedulable who, TimeInstant time)",
946                            "The Schedulable reference passed as parameter is a "
947                                    + "null reference.",
948                            "Always make sure to use valid references only.");
949            return; // Schedulable missing
950        }
951 
952        if (!who.isScheduled()) {
953            myExperiment
954                    .sendWarning(
955                            "Can't reschedule Schedulable at given time! "
956                                    + "Command ignored.",
957                            "Scheduler : "
958                                    + getName()
959                                    + " Method: reSchedule(Schedulable who, TimeInstant time)",
960                            "The Schedulable given is not scheduled, thus can not be "
961                                    + "rescheduled.",
962                            "To reschedule a Schedulable, it must already be scheduled. "
963                                    + "You can check that by calling the Schedulable's "
964                                    + "isScheduled() method");
965            return;
966            // I can't be rescheduled, I haven't even been scheduled yet
967        }
968        
969        if (TimeInstant.isBefore(time, this.presentTime())) {
970            myExperiment
971                    .sendWarning(
972                            "Can't reschedule Schedulable at given time! "
973                                    + "Command ignored.",
974                            "Scheduler : "
975                                    + getName()
976                                    + " Method: reSchedule(Schedulable who, TimeInstant time)",
977                            "The instant given is in the past.",
978                            "To reschedule a Schedulable, use a TimeInstant no earlier than the present time. "
979                                    + "The present time can be obtained using the "
980                                    + "presentTime() method");
981            return;
982            // I can't be rescheduled, TimeInstant has already passed.
983        }
984 
985        // all parameters checked, now remove the Schedulable's EventNote
986        // first...
987        EventNote note = who.getEventNotes().get(0);
988        evList.remove(note);
989        note.setTime(time);
990 
991        if (this.presentTime() == time) { // preempting schedule for processes
992 
993            if (_currentProcess == null) { // currently Event -> no preemption
994                // inserted as first in the event-list with the current time as
995                // activation
996                evList.insertAsFirst(note);
997                return;
998 
999            } else { // currently SimProcess -> preempt!
1000 
1001                preemptSimProcess(note);
1002                return;
1003 
1004            }
1005 
1006        }
1007 
1008        // all parameters checked, now reinsert note
1009        evList.insert(note);
1010 
1011    }
1012 
1013        /**
1014         * Schedules the event to happen after a specified time span. Checks that only
1015         * legal combinations of valid parameters are scheduled.
1016         * <p>
1017         * <DIV align=center>
1018         * <TABLE BORDER >
1019         * <CAPTION>Valid scheduling types </CAPTION>
1020         * <TR>
1021         * <TH><DIV align=center>scheduling type</TH>
1022         * <TH>Entity object</TH>
1023         * <TH>Event object</TH>
1024         * </TR>
1025         * <TR>
1026         * <TH>Event oriented</TH>
1027         * <TD>Event or SimProcess</TD>
1028         * <TD>Event</TD>
1029         * </TR>
1030         * <TR>
1031         * <TH>process oriented</TH>
1032         * <TD>SimProcess</TD>
1033         * <TD>null</TD>
1034         * </TR>
1035         * <TR>
1036         * <TH>external event</TH>
1037         * <TD>null</TD>
1038         * <TD>external event</TD>
1039         * </TR>
1040         * </TABLE>
1041         * </DIV>
1042         * 
1043         * @param who
1044         *            Entity : The Entity to be scheduled
1045         * @param what
1046         *            Event : The event to manipulate the entity
1047         * @param dt
1048         *            TimeSpan : The point in simulation time for the event to happen
1049         *            as an offset to the current simulation time
1050         */
1051        protected void schedule(Entity who, EventAbstract what, TimeSpan dt)
1052        {
1053 
1054                if (dt == null) {
1055                        myExperiment.sendWarning(
1056                                        "Can't schedule Entity and Event at given "
1057                                                        + "time! Command ignored.", "Scheduler : "
1058                                                        + getName() + " Method: schedule(Entity who, "
1059                                                        + "EventAbstract what, TimeSpan dt)",
1060                                        "The simulation time reference passed as parameter is a "
1061                                                        + "null reference.",
1062                                        "Always make sure to use valid references only.");
1063                        return; // time missing
1064                }
1065 
1066                if ((who == null) && (what == null)) {
1067                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1068                                        + "Command ignored.", "Scheduler : " + getName()
1069                                        + " Method: schedule(Entity who, "
1070                                        + "EventAbstract what, TimeSpan dt)",
1071                                        "The Event and Entity references passed are both "
1072                                                        + "null references.",
1073                                        "Either Event or Entity references must be valid.");
1074                        return; // no real parameters here anyway
1075                }
1076 
1077                if ((who == null) && !(what instanceof ExternalEvent)) {
1078                        myExperiment.sendWarning("Can't schedule Event! Command ignored.",
1079                                        "Scheduler : " + getName()
1080                                                        + " Method: schedule(Entity who, "
1081                                                        + "EventAbstract what, TimeSpan dt)",
1082                                        "The Entity reference passed is a null reference but the "
1083                                                        + "Event references is not an external event.",
1084                                        "If no valid Entity is given, the event must be of type "
1085                                                        + "external event.");
1086                        return; // if no Entity it must be ExternalEvent
1087                }
1088 
1089                if (!(who instanceof SimProcess) && (what == null)) {
1090                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1091                                        + "Command ignored.", "Scheduler : " + getName()
1092                                        + " Method: schedule(Entity who, "
1093                                        + "EventAbstract what, TimeSpan dt)",
1094                                        "The Entity needs a valid Event to be scheduled with.",
1095                                        "Only SimProcesses may be scheduled without events.");
1096                        return; // Event needed with Entity
1097                }
1098                
1099                if(what != null)
1100                {
1101                        if (what.getNumberOfEntities() > 1) 
1102                        {
1103                                myExperiment.sendWarning("Can't schedule Entity and Event! "
1104                                                + "Command ignored.", "Scheduler : " + getName()
1105                                                + " Method: schedule(Entity who, "
1106                                                + "EventAbstract what, TimeSpan dt)",
1107                                                "The method needs the correct Event to be scheduled with.",
1108                                                "You are using an event for multiple entities. You need an event for a single entity.");
1109                                return; // Event with only one entity needed
1110                        }
1111                }
1112                
1113                TimeInstant time = TimeOperations.add(presentTime(), dt);
1114                // set time for being scheduled
1115 
1116                EventNote note = new EventNote(who, what, time);
1117 
1118                if (dt == TimeSpan.ZERO) { // preempting schedule for processes
1119                        if (_currentProcess == null) { // currently Event -> no preemption
1120                                // inserted as first in the event-list with the current time as
1121                                // activation
1122                                evList.insertAsFirst(note);
1123                                return;
1124                        } else { // currently SimProcess -> preempt!
1125                                preemptSimProcess(note);
1126                                return;
1127                        }
1128                }
1129 
1130                // all parameters checked, now schedule Event
1131                evList.insert(note);
1132 
1133        }
1134        
1135        /**
1136         * Schedules the event to happen after a specified time span. Checks that only
1137         * legal combinations of valid parameters are scheduled.
1138         * <p>
1139         * <DIV align=center>
1140         * <TABLE BORDER >
1141         * <CAPTION>Valid scheduling types </CAPTION>
1142         * <TR>
1143         * <TH><DIV align=center>scheduling type</TH>
1144         * <TH>Entity object</TH>
1145         * <TH>Event object</TH>
1146         * </TR>
1147         * <TR>
1148         * <TH>Event oriented</TH>
1149         * <TD>Event or SimProcess</TD>
1150         * <TD>Event</TD>
1151         * </TR>
1152         * <TR>
1153         * <TH>process oriented</TH>
1154         * <TD>SimProcess</TD>
1155         * <TD>null</TD>
1156         * </TR>
1157         * <TR>
1158         * <TH>external event</TH>
1159         * <TD>null</TD>
1160         * <TD>external event</TD>
1161         * </TR>
1162         * </TABLE>
1163         * </DIV>
1164         * 
1165         * @param who1
1166         *            Entity : The first entity to be scheduled
1167         *            
1168         * @param who2
1169         *            Entity : The second entity to be scheduled
1170         *            
1171         * @param what
1172         *            EventOf2Entities : The event to manipulate the two entities
1173         * @param dt
1174         *            TimeSpan : The point in simulation time for the event to happen
1175         *            as an offset to the current simulation time
1176         */
1177        protected void schedule(Entity who1, Entity who2, EventOf2Entities<?, ?> what, TimeSpan dt) {
1178        
1179                if (dt == null) {
1180                        myExperiment.sendWarning(
1181                                        "Can't schedule Entity and Event at given "
1182                                                        + "time! Command ignored.", "Scheduler : "
1183                                                        + getName() + " Method: schedule(Entity who1, Entity who2, "
1184                                                        + "EventOf2Entities what, TimeSpan dt)",
1185                                        "The simulation time reference passed as parameter is a "
1186                                                        + "null reference.",
1187                                        "Always make sure to use valid references only.");
1188                        return; // time missing
1189                }
1190        
1191                if ((who1 == null) && (what == null)) {
1192                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1193                                        + "Command ignored.", "Scheduler : " + getName()
1194                                        + " Method: schedule(Entity who1, Entity who2, "
1195                                        + "EventOf2Entities what, TimeSpan dt)",
1196                                        "The event and first entity references passed are both "
1197                                                        + "null references.",
1198                                        "Either Event or first entity references must be valid.");
1199                        return; // no real parameters here anyway
1200                }
1201                
1202                if ((who2 == null) && (what == null)) {
1203                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1204                                        + "Command ignored.", "Scheduler : " + getName()
1205                                        + " Method: schedule(Entity who1, Entity who2, "
1206                                        + "EventOf2Entities what, TimeSpan dt)",
1207                                        "The event and second entity references passed are both "
1208                                                        + "null references.",
1209                                        "Either Event or second entity references must be valid.");
1210                        return; // no real parameters here anyway
1211                }
1212        
1213                if (!(who1 instanceof SimProcess) && (what == null)) {
1214                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1215                                        + "Command ignored.", "Scheduler : " + getName()
1216                                        + " Method: schedule(Entity who1, Entity who2, "
1217                                        + "EventOf2Entities what, TimeSpan dt)",
1218                                        "The first entity needs a valid Event to be scheduled with.",
1219                                        "Only SimProcesses may be scheduled without events.");
1220                        return; // Event needed with Entity
1221                }
1222                
1223                if (!(who2 instanceof SimProcess) && (what == null)) {
1224                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1225                                        + "Command ignored.", "Scheduler : " + getName()
1226                                        + " Method: schedule(Entity who1, Entity who2, "
1227                                        + "EventOf2Entities what, TimeSpan dt)",
1228                                        "The second entity needs a valid Event to be scheduled with.",
1229                                        "Only SimProcesses may be scheduled without events.");
1230                        return; // Event needed with Entity
1231                }
1232                
1233                TimeInstant time = TimeOperations.add(presentTime(), dt);
1234                // set time for being scheduled
1235        
1236                EventNote note = new EventNote(who1, who2, what, time);
1237        
1238                if (dt == TimeSpan.ZERO) { // preempting schedule for processes
1239                        if (_currentProcess == null) { // currently Event -> no preemption
1240                                // inserted as first in the event-list with the current time as
1241                                // activation
1242                                evList.insertAsFirst(note);
1243                                return;
1244                        } else { // currently SimProcess -> preempt!
1245                                preemptSimProcess(note);
1246                                return;
1247                        }
1248                }
1249        
1250                // all parameters checked, now schedule Event
1251                evList.insert(note);
1252        
1253        }
1254        
1255        /**
1256         * Schedules the event to happen after a specified time span. Checks that only
1257         * legal combinations of valid parameters are scheduled.
1258         * <p>
1259         * <DIV align=center>
1260         * <TABLE BORDER >
1261         * <CAPTION>Valid scheduling types </CAPTION>
1262         * <TR>
1263         * <TH><DIV align=center>scheduling type</TH>
1264         * <TH>Entity object</TH>
1265         * <TH>Event object</TH>
1266         * </TR>
1267         * <TR>
1268         * <TH>Event oriented</TH>
1269         * <TD>Event or SimProcess</TD>
1270         * <TD>Event</TD>
1271         * </TR>
1272         * <TR>
1273         * <TH>process oriented</TH>
1274         * <TD>SimProcess</TD>
1275         * <TD>null</TD>
1276         * </TR>
1277         * <TR>
1278         * <TH>external event</TH>
1279         * <TD>null</TD>
1280         * <TD>external event</TD>
1281         * </TR>
1282         * </TABLE>
1283         * </DIV>
1284         * 
1285         * @param who1
1286         *            Entity : The first entity to be scheduled
1287         *            
1288         * @param who2
1289         *            Entity : The second entity to be scheduled
1290         *            
1291         * @param who3
1292         *            Entity : The third entity to be scheduled
1293         *            
1294         * @param what
1295         *            EventOf3Entities : The event to manipulate the two entities
1296         * @param dt
1297         *            TimeSpan : The point in simulation time for the event to happen
1298         *            as an offset to the current simulation time
1299         */
1300        protected void schedule(Entity who1, Entity who2, Entity who3, EventOf3Entities<?, ?, ?> what, TimeSpan dt) {
1301        
1302                if (dt == null) {
1303                        myExperiment.sendWarning(
1304                                        "Can't schedule Entity and Event at given "
1305                                                        + "time! Command ignored.", "Scheduler : "
1306                                                        + getName() + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1307                                                        + "EventOf3Entities what, TimeSpan dt)",
1308                                        "The simulation time reference passed as parameter is a "
1309                                                        + "null reference.",
1310                                        "Always make sure to use valid references only.");
1311                        return; // time missing
1312                }
1313        
1314                if ((who1 == null) && (what == null)) {
1315                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1316                                        + "Command ignored.", "Scheduler : " + getName()
1317                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1318                                        + "EventOf3Entities what, TimeSpan dt)",
1319                                        "The event and first entity references passed are both "
1320                                                        + "null references.",
1321                                        "Either Event or first entity references must be valid.");
1322                        return; // no real parameters here anyway
1323                }
1324                
1325                if ((who2 == null) && (what == null)) {
1326                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1327                                        + "Command ignored.", "Scheduler : " + getName()
1328                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1329                                        + "EventOf3Entities what, TimeSpan dt)",
1330                                        "The event and second entity references passed are both "
1331                                                        + "null references.",
1332                                        "Either Event or second entity references must be valid.");
1333                        return; // no real parameters here anyway
1334                }
1335                
1336                if ((who3 == null) && (what == null)) {
1337                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1338                                        + "Command ignored.", "Scheduler : " + getName()
1339                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1340                                        + "EventOf3Entities what, TimeSpan dt)",
1341                                        "The event and third entity references passed are both "
1342                                                        + "null references.",
1343                                        "Either Event or third entity references must be valid.");
1344                        return; // no real parameters here anyway
1345                }
1346        
1347                if (!(who1 instanceof SimProcess) && (what == null)) {
1348                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1349                                        + "Command ignored.", "Scheduler : " + getName()
1350                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1351                                        + "EventOf3Entities what, TimeSpan dt)",
1352                                        "The first entity needs a valid Event to be scheduled with.",
1353                                        "Only SimProcesses may be scheduled without events.");
1354                        return; // Event needed with Entity
1355                }
1356                
1357                if (!(who2 instanceof SimProcess) && (what == null)) {
1358                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1359                                        + "Command ignored.", "Scheduler : " + getName()
1360                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1361                                        + "EventOf3Entities what, TimeSpan dt)",
1362                                        "The second entity needs a valid Event to be scheduled with.",
1363                                        "Only SimProcesses may be scheduled without events.");
1364                        return; // Event needed with Entity
1365                }
1366                
1367                if (!(who3 instanceof SimProcess) && (what == null)) {
1368                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1369                                        + "Command ignored.", "Scheduler : " + getName()
1370                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1371                                        + "EventOf3Entities what, TimeSpan dt)",
1372                                        "The third entity needs a valid Event to be scheduled with.",
1373                                        "Only SimProcesses may be scheduled without events.");
1374                        return; // Event needed with Entity
1375                }
1376                
1377                TimeInstant time = TimeOperations.add(presentTime(), dt);
1378                // set time for being scheduled
1379        
1380                EventNote note = new EventNote(who1, who2, who3, what, time);
1381        
1382                if (dt == TimeSpan.ZERO) { // preempting schedule for processes
1383                        if (_currentProcess == null) { // currently Event -> no preemption
1384                                // inserted as first in the event-list with the current time as
1385                                // activation
1386                                evList.insertAsFirst(note);
1387                                return;
1388                        } else { // currently SimProcess -> preempt!
1389                                preemptSimProcess(note);
1390                                return;
1391                        }
1392                }
1393        
1394                // all parameters checked, now schedule Event
1395                evList.insert(note);
1396        
1397        }
1398        
1399        /**
1400         * Schedules the event to happen at the specified time. Checks that only
1401         * legal combinations of valid parameters are scheduled.
1402         * <p>
1403         * <DIV align=center>
1404         * <TABLE BORDER >
1405         * <CAPTION>Valid scheduling types </CAPTION>
1406         * <TR>
1407         * <TH><DIV align=center>scheduling type</TH>
1408         * <TH>Entity object</TH>
1409         * <TH>Event object</TH>
1410         * </TR>
1411         * <TR>
1412         * <TH>Event oriented</TH>
1413         * <TD>Event or SimProcess</TD>
1414         * <TD>Event</TD>
1415         * </TR>
1416         * <TR>
1417         * <TH>process oriented</TH>
1418         * <TD>SimProcess</TD>
1419         * <TD>null</TD>
1420         * </TR>
1421         * <TR>
1422         * <TH>external event</TH>
1423         * <TD>null</TD>
1424         * <TD>external event</TD>
1425         * </TR>
1426         * </TABLE>
1427         * </DIV>
1428         * 
1429         * @param who
1430         *            Entity : The Entity to be scheduled
1431         * @param what
1432         *            Event : The event to manipulate the entity
1433         * @param when
1434         *            TimeInstant : The point in simulation time for the event to
1435         *            happen
1436         */
1437        protected void schedule(Entity who, EventAbstract what, TimeInstant when) {
1438 
1439                if (when == null) {
1440                        myExperiment.sendWarning(
1441                                        "Can't schedule Entity and Event at given "
1442                                                        + "time! Command ignored.", "Scheduler : "
1443                                                        + getName() + " Method: schedule(Entity who, "
1444                                                        + "EventAbstract what, TimeInstant when)",
1445                                        "The simulation time reference passed as parameter is a "
1446                                                        + "null reference.",
1447                                        "Always make sure to use valid references only.");
1448                        return; // time missing
1449                }
1450 
1451                if ((who == null) && (what == null)) {
1452                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1453                                        + "Command ignored.", "Scheduler : " + getName()
1454                                        + " Method: schedule(Entity who, "
1455                                        + "EventAbstract what, TimeInstant when)",
1456                                        "The Event and Entity references passed are both "
1457                                                        + "null references.",
1458                                        "Either Event or Entity references must be valid.");
1459                        return; // no real parameters here anyway
1460                }
1461 
1462                if ((who == null) && !(what instanceof ExternalEvent)) {
1463                        myExperiment.sendWarning("Can't schedule Event! Command ignored.",
1464                                        "Scheduler : " + getName()
1465                                                        + " Method: schedule(Entity who, "
1466                                                        + "EventAbstract what, TimeInstant when)",
1467                                        "The Entity reference passed is a null reference but the "
1468                                                        + "Event references is not an external event.",
1469                                        "If no valid Entity is given, the event must be of type "
1470                                                        + "external event.");
1471                        return; // if no Entity it must be ExternalEvent
1472                }
1473 
1474                if (!(who instanceof SimProcess) && (what == null)) {
1475                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1476                                        + "Command ignored.", "Scheduler : " + getName()
1477                                        + " Method: schedule(Entity who, "
1478                                        + "EventAbstract what, TimeInstant when)",
1479                                        "The Entity needs a valid Event to be scheduled with.",
1480                                        "Only SimProcesses may be scheduled without events.");
1481                        return; // Event needed with Entity
1482                }
1483                
1484        if (TimeInstant.isBefore(when, this.presentTime())) {
1485            myExperiment
1486                    .sendWarning(
1487                            "Can't reschedule Schedulable at given time! "
1488                                    + "Command ignored.",
1489                            "Scheduler : "
1490                                    + getName()
1491                                    + " Method: schedule(Entity who, "
1492                                                        + "EventAbstract what, TimeInstant when)",
1493                            "The instant given is in the past.",
1494                            "To schedule a Schedulable, use a TimeInstant no earlier than the present time. "
1495                                    + "The present time can be obtained using the "
1496                                    + "presentTime() method.");
1497            return;
1498            // I can't be scheduled, TimeInstant has already passed.
1499        }
1500        
1501        if(what != null)
1502                {
1503                        if (what.getNumberOfEntities() > 1) 
1504                        {
1505                                myExperiment.sendWarning("Can't schedule Entity and Event! "
1506                                                + "Command ignored.", "Scheduler : " + getName()
1507                                                + " Method: schedule(Entity who, "
1508                                                + "Event what, TimeSpan dt)",
1509                                                "The method needs the correct Event to be scheduled with.",
1510                                                "You are using an event for multiple entities. You need an event for a single entity.");
1511                                return; // Event needed with Entity
1512                        }
1513                }
1514 
1515                EventNote note = new EventNote(who, what, when);
1516 
1517                if (when == presentTime()) { // preempting schedule for processes
1518                        if (_currentProcess == null) { // currently Event -> no preemption
1519                                // inserted as first in the event-list with the current time as
1520                                // activation
1521                                evList.insertAsFirst(note);
1522                                return;
1523                        } else { // currently SimProcess -> preempt!
1524                                preemptSimProcess(note);
1525                                return;
1526                        }
1527 
1528                }
1529 
1530                // all parameters checked, now schedule Event
1531                evList.insert(note);
1532 
1533        }
1534        
1535        /**
1536         * Schedules the event to happen at the specified time. Checks that only
1537         * legal combinations of valid parameters are scheduled.
1538         * <p>
1539         * <DIV align=center>
1540         * <TABLE BORDER >
1541         * <CAPTION>Valid scheduling types </CAPTION>
1542         * <TR>
1543         * <TH><DIV align=center>scheduling type</TH>
1544         * <TH>Entity object</TH>
1545         * <TH>Event object</TH>
1546         * </TR>
1547         * <TR>
1548         * <TH>Event oriented</TH>
1549         * <TD>Event or SimProcess</TD>
1550         * <TD>Event</TD>
1551         * </TR>
1552         * <TR>
1553         * <TH>process oriented</TH>
1554         * <TD>SimProcess</TD>
1555         * <TD>null</TD>
1556         * </TR>
1557         * <TR>
1558         * <TH>external event</TH>
1559         * <TD>null</TD>
1560         * <TD>external event</TD>
1561         * </TR>
1562         * </TABLE>
1563         * </DIV>
1564         * 
1565         * @param who1
1566         *            Entity : The first entity to be scheduled
1567         *            
1568         * @param who2
1569         *            Entity : The second entity to be scheduled
1570         *            
1571         * @param what
1572         *            EventOf2Entities : The event to manipulate the entity
1573         *            
1574         * @param when
1575         *            TimeInstant : The point in simulation time for the event to
1576         *            happen
1577         */
1578        protected void schedule(Entity who1, Entity who2, EventOf2Entities<?, ?> what, TimeInstant when) {
1579        
1580                if (when == null) {
1581                        myExperiment.sendWarning(
1582                                        "Can't schedule Entity and Event at given "
1583                                                        + "time! Command ignored.", "Scheduler : "
1584                                                        + getName() + " Method: schedule(Entity who1, Entity who2, "
1585                                                        + "EventOf2Entities what, TimeInstant when)",
1586                                        "The simulation time reference passed as parameter is a "
1587                                                        + "null reference.",
1588                                        "Always make sure to use valid references only.");
1589                        return; // time missing
1590                }
1591        
1592                if ((who1 == null) && (what == null)) {
1593                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1594                                        + "Command ignored.", "Scheduler : " + getName()
1595                                        + " Method: schedule(Entity who1, Entity who2, "
1596                                        + "EventOf2Entities what, TimeInstant when)",
1597                                        "The event and first entity references passed are both "
1598                                                        + "null references.",
1599                                        "Either Event or first entity references must be valid.");
1600                        return; // no real parameters here anyway
1601                }
1602                
1603                if ((who2 == null) && (what == null)) {
1604                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1605                                        + "Command ignored.", "Scheduler : " + getName()
1606                                        + " Method: schedule(Entity who1, Entity who2, "
1607                                        + "EventOf2Entities what, TimeInstant when)",
1608                                        "The event and second entity references passed are both "
1609                                                        + "null references.",
1610                                        "Either Event or second entity references must be valid.");
1611                        return; // no real parameters here anyway
1612                }
1613        
1614                if (!(who1 instanceof SimProcess) && (what == null)) {
1615                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1616                                        + "Command ignored.", "Scheduler : " + getName()
1617                                        + " Method: schedule(Entity who1, Entity who2, "
1618                                        + "EventOf2Entities what, TimeInstant when)",
1619                                        "The first entity needs a valid Event to be scheduled with.",
1620                                        "Only SimProcesses may be scheduled without events.");
1621                        return; // Event needed with Entity
1622                }
1623                
1624                if (!(who2 instanceof SimProcess) && (what == null)) {
1625                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1626                                        + "Command ignored.", "Scheduler : " + getName()
1627                                        + " Method: schedule(Entity who1, Entity who2, "
1628                                        + "EventOf2Entities what, TimeInstant when)",
1629                                        "The second entity needs a valid Event to be scheduled with.",
1630                                        "Only SimProcesses may be scheduled without events.");
1631                        return; // Event needed with Entity
1632                }
1633                
1634            if (TimeInstant.isBefore(when, this.presentTime())) {
1635                myExperiment
1636                        .sendWarning(
1637                                "Can't reschedule Schedulable at given time! "
1638                                        + "Command ignored.",
1639                                "Scheduler : "
1640                                        + getName()
1641                                        + " Method: schedule(Entity who1, Entity who2, EventOf2Entities what, TimeInstant when)",
1642                                "The instant given is in the past.",
1643                                "To schedule a Schedulable, use a TimeInstant no earlier than the present time. "
1644                                        + "The present time can be obtained using the "
1645                                        + "presentTime() method.");
1646                return;
1647                // I can't be scheduled, TimeInstant has already passed.
1648            }
1649        
1650                EventNote note = new EventNote(who1, who2, what, when);
1651        
1652                if (when == presentTime()) { // preempting schedule for processes
1653                        if (_currentProcess == null) { // currently Event -> no preemption
1654                                // inserted as first in the event-list with the current time as
1655                                // activation
1656                                evList.insertAsFirst(note);
1657                                return;
1658                        } else { // currently SimProcess -> preempt!
1659                                preemptSimProcess(note);
1660                                return;
1661                        }
1662        
1663                }
1664        
1665                // all parameters checked, now schedule Event
1666                evList.insert(note);
1667        
1668        }
1669        
1670        /**
1671         * Schedules the event to happen at the specified time. Checks that only
1672         * legal combinations of valid parameters are scheduled.
1673         * <p>
1674         * <DIV align=center>
1675         * <TABLE BORDER >
1676         * <CAPTION>Valid scheduling types </CAPTION>
1677         * <TR>
1678         * <TH><DIV align=center>scheduling type</TH>
1679         * <TH>Entity object</TH>
1680         * <TH>Event object</TH>
1681         * </TR>
1682         * <TR>
1683         * <TH>Event oriented</TH>
1684         * <TD>Event or SimProcess</TD>
1685         * <TD>Event</TD>
1686         * </TR>
1687         * <TR>
1688         * <TH>process oriented</TH>
1689         * <TD>SimProcess</TD>
1690         * <TD>null</TD>
1691         * </TR>
1692         * <TR>
1693         * <TH>external event</TH>
1694         * <TD>null</TD>
1695         * <TD>external event</TD>
1696         * </TR>
1697         * </TABLE>
1698         * </DIV>
1699         * 
1700         * @param who1
1701         *            Entity : The first entity to be scheduled
1702         *            
1703         * @param who2
1704         *            Entity : The second entity to be scheduled
1705         *            
1706         * @param who3
1707         *            Entity : The third entity to be scheduled
1708         *            
1709         * @param what
1710         *            EventOf3Entities : The event to manipulate the entity
1711         * @param when
1712         *            TimeInstant : The point in simulation time for the event to
1713         *            happen
1714         */
1715        protected void schedule(Entity who1, Entity who2, Entity who3, EventOf3Entities<?, ?, ?> what, TimeInstant when) {
1716        
1717                if (when == null) {
1718                        myExperiment.sendWarning(
1719                                        "Can't schedule Entity and Event at given "
1720                                                        + "time! Command ignored.", "Scheduler : "
1721                                                        + getName() + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1722                                                        + "EventOf3Entities what, TimeInstant when)",
1723                                        "The simulation time reference passed as parameter is a "
1724                                                        + "null reference.",
1725                                        "Always make sure to use valid references only.");
1726                        return; // time missing
1727                }
1728        
1729                if ((who1 == null) && (what == null)) {
1730                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1731                                        + "Command ignored.", "Scheduler : " + getName()
1732                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1733                                        + "EventOf3Entities what, TimeInstant when)",
1734                                        "The first Event and Entity references passed are both "
1735                                                        + "null references.",
1736                                        "Either Event or Entity references must be valid.");
1737                        return; // no real parameters here anyway
1738                }
1739                
1740                if ((who2 == null) && (what == null)) {
1741                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1742                                        + "Command ignored.", "Scheduler : " + getName()
1743                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1744                                        + "EventOf3Entities what, TimeInstant when)",
1745                                        "The EEvent and second entity references passed are both "
1746                                                        + "null references.",
1747                                        "Either Event or second entity references must be valid.");
1748                        return; // no real parameters here anyway
1749                }
1750                
1751                if ((who3 == null) && (what == null)) {
1752                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1753                                        + "Command ignored.", "Scheduler : " + getName()
1754                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1755                                        + "EventOf3Entities what, TimeInstant when)",
1756                                        "The event and third entity references passed are both "
1757                                                        + "null references.",
1758                                        "Either Event or third entity references must be valid.");
1759                        return; // no real parameters here anyway
1760                }
1761        
1762                if (!(who1 instanceof SimProcess) && (what == null)) {
1763                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1764                                        + "Command ignored.", "Scheduler : " + getName()
1765                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1766                                        + "EventOf3Entities what, TimeInstant when)",
1767                                        "The first entity needs a valid Event to be scheduled with.",
1768                                        "Only SimProcesses may be scheduled without events.");
1769                        return; // Event needed with Entity
1770                }
1771                
1772                if (!(who2 instanceof SimProcess) && (what == null)) {
1773                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1774                                        + "Command ignored.", "Scheduler : " + getName()
1775                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1776                                        + "EventOf3Entities what, TimeInstant when)",
1777                                        "The second entity needs a valid Event to be scheduled with.",
1778                                        "Only SimProcesses may be scheduled without events.");
1779                        return; // Event needed with Entity
1780                }
1781                
1782                if (!(who3 instanceof SimProcess) && (what == null)) {
1783                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1784                                        + "Command ignored.", "Scheduler : " + getName()
1785                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, "
1786                                        + "EventOf3Entities what, TimeInstant when)",
1787                                        "The third entity needs a valid Event to be scheduled with.",
1788                                        "Only SimProcesses may be scheduled without events.");
1789                        return; // Event needed with Entity
1790                }
1791                
1792            if (TimeInstant.isBefore(when, this.presentTime())) {
1793                myExperiment
1794                        .sendWarning(
1795                                "Can't reschedule Schedulable at given time! "
1796                                        + "Command ignored.",
1797                                "Scheduler : "
1798                                        + getName()
1799                                        + " Method: schedule(Entity who1, Entity who2, Entity who3, EventOf3Entities what, TimeInstant when)",
1800                                "The instant given is in the past.",
1801                                "To schedule a Schedulable, use a TimeInstant no earlier than the present time. "
1802                                        + "The present time can be obtained using the "
1803                                        + "presentTime() method.");
1804                return;
1805                // I can't be scheduled, TimeInstant has already passed.
1806            }
1807        
1808                EventNote note = new EventNote(who1, who2, who3, what, when);
1809        
1810                if (when == presentTime()) { // preempting schedule for processes
1811                        if (_currentProcess == null) { // currently Event -> no preemption
1812                                // inserted as first in the event-list with the current time as
1813                                // activation
1814                                evList.insertAsFirst(note);
1815                                return;
1816                        } else { // currently SimProcess -> preempt!
1817                                preemptSimProcess(note);
1818                                return;
1819                        }
1820        
1821                }
1822        
1823                // all parameters checked, now schedule Event
1824                evList.insert(note);
1825        
1826        }
1827 
1828        /**
1829         * Schedules the given Entity and Event to happen straight after the given
1830         * Schedulable is set to be activated. Note that the siulation time for the
1831         * newly entered EventNote will be set to the Schedulable's time and the new
1832         * EventNote will be inserted directly after the Schedulable's EventNote.
1833         * <p>
1834         * <DIV align=center>
1835         * <TABLE BORDER >
1836         * <CAPTION>Valid scheduling types </CAPTION>
1837         * <TR>
1838         * <TH><DIV align=center>scheduling type</TH>
1839         * <TH>Entity object</TH>
1840         * <TH>Event object</TH>
1841         * </TR>
1842         * <TR>
1843         * <TH>Event oriented</TH>
1844         * <TD>Event or SimProcess</TD>
1845         * <TD>Event</TD>
1846         * </TR>
1847         * <TR>
1848         * <TH>process oriented</TH>
1849         * <TD>SimProcess</TD>
1850         * <TD>null</TD>
1851         * </TR>
1852         * <TR>
1853         * <TH>external event</TH>
1854         * <TD>null</TD>
1855         * <TD>external event</TD>
1856         * </TR>
1857         * </TABLE>
1858         * </DIV>
1859         * 
1860         * @param after
1861         *            Schedulable : The Schedulable after which the new event-note is
1862         *            to be scheduled
1863         * @param who
1864         *            Entity : The Entity to be scheduled
1865         * @param what
1866         *            Event : The event to be scheduled
1867         */
1868        protected void scheduleAfter(Schedulable after, Entity who, EventAbstract what) {
1869 
1870                if (after == null) {
1871                        myExperiment.sendWarning("Can't schedule after Schedulable! "
1872                                        + "Command ignored.", "Scheduler : " + getName()
1873                                        + " Method: scheduleAfter(Schedulable after "
1874                                        + ", Entity who, EventAbstract what)",
1875                                        "The reference for the Schedulable to schedule after is a "
1876                                                        + "null references.",
1877                                        "Always check to use valid references.");
1878                        return; // relative Schedulable missing
1879                }
1880 
1881                if (!after.isScheduled() && (after != _currentSchedulable)) {
1882                        myExperiment.sendWarning("Can't schedule after Schedulable! "
1883                                        + "Command ignored.", "Scheduler : " + getName()
1884                                        + " Method: scheduleAfter(Schedulable after "
1885                                        + ", Entity who, EventAbstract what)",
1886                                        "The Schedulable to be scheduled after is not scheduled.",
1887                                        "The Schedulable taken as reference must be scheduled.");
1888                        return; // relative Schedulable not scheduled
1889                }
1890 
1891                if ((who == null) && (what == null)) {
1892                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1893                                        + "Command ignored.", "Scheduler : " + getName()
1894                                        + " Method: scheduleAfter(Schedulable after "
1895                                        + ", Entity who, EventAbstract what)",
1896                                        "The Event and Entity references passed are both "
1897                                                        + "null references.",
1898                                        "Either Event or Entity references must be valid.");
1899                        return; // no real parameters here anyway
1900                }
1901 
1902                if ((who == null) && !(what instanceof ExternalEvent)) {
1903                        myExperiment.sendWarning("Can't schedule Event! Command ignored.",
1904                                        "Scheduler : " + getName()
1905                                                        + " Method: scheduleAfter(Schedulabe "
1906                                                        + "after, Entity who, EventAbstract what)",
1907                                        "The Entity reference passed is a null reference but the "
1908                                                        + "Event references is not an external event.",
1909                                        "If no valid Entity is given, the event must be of type "
1910                                                        + "external event.");
1911                        return; // if no Entity it must be ExternalEvent
1912                }
1913 
1914                if (!(who instanceof SimProcess) && (what == null)) {
1915                        myExperiment.sendWarning("Can't schedule Entity and Event! "
1916                                        + "Command ignored.", "Scheduler : " + getName()
1917                                        + " Method: scheduleAfter(Schedulabe "
1918                                        + "after, Entity who, EventAbstract what)",
1919                                        "The Entity needs a valid Event to be scheduled with.",
1920                                        "Only SimProcesses may be scheduled without events.");
1921                        return; // Event needed with Entity
1922                }
1923                
1924                if(what != null)
1925                {
1926                        if (what.getNumberOfEntities() > 1) 
1927                        {
1928                                myExperiment.sendWarning("Can't schedule Entity and Event! "
1929                                                + "Command ignored.", "Scheduler : " + getName()
1930                                                + " Method: scheduleAfter(Schedulabe "
1931                                            + "after, Entity who, EventAbstract what)",
1932                                                "The method needs the correct Event to be scheduled with.",
1933                                                "You are using an event for multiple entities. You need an event for a single entity.");
1934                                return; // Event with only one entity needed
1935                        }
1936                }
1937 
1938                if (after != _currentSchedulable) {
1939                        // all parameters checked, now go on and schedule
1940                        EventNote afterNote = after.getEventNotes().get(after.getEventNotes().size()-1);
1941                        evList.insertAfter(afterNote, new EventNote(who, what, afterNote
1942                                        .getTime()));
1943                        // sets the time equivalent to the Schedulable's
1944                } else {
1945                        evList.insertAsFirst(new EventNote(who, what, presentTime()));
1946                }
1947 
1948        }
1949        
1950        /**
1951         * Schedules the given Entity and Event to happen straight after the given
1952         * Schedulable is set to be activated. Note that the siulation time for the
1953         * newly entered EventNote will be set to the Schedulable's time and the new
1954         * EventNote will be inserted directly after the Schedulable's EventNote.
1955         * <p>
1956         * <DIV align=center>
1957         * <TABLE BORDER >
1958         * <CAPTION>Valid scheduling types </CAPTION>
1959         * <TR>
1960         * <TH><DIV align=center>scheduling type</TH>
1961         * <TH>Entity object</TH>
1962         * <TH>Event object</TH>
1963         * </TR>
1964         * <TR>
1965         * <TH>Event oriented</TH>
1966         * <TD>Event or SimProcess</TD>
1967         * <TD>Event</TD>
1968         * </TR>
1969         * <TR>
1970         * <TH>process oriented</TH>
1971         * <TD>SimProcess</TD>
1972         * <TD>null</TD>
1973         * </TR>
1974         * <TR>
1975         * <TH>external event</TH>
1976         * <TD>null</TD>
1977         * <TD>external event</TD>
1978         * </TR>
1979         * </TABLE>
1980         * </DIV>
1981         * 
1982         * @param after
1983         *            Schedulable : The Schedulable after which the new event-note is
1984         *            to be scheduled
1985         * @param who1
1986         *            Entity : The first entity to be scheduled
1987         *            
1988         * @param who2
1989         *            Entity : The second entity to be scheduled
1990         *            
1991         * @param what
1992         *            EventOf2Entities : The event to be scheduled
1993         */
1994        protected void scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities<?, ?> what) {
1995        
1996                if (after == null) {
1997                        myExperiment.sendWarning("Can't schedule after Schedulable! "
1998                                        + "Command ignored.", "Scheduler : " + getName()
1999                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)",
2000                                        "The reference for the Schedulable to schedule after is a "
2001                                                        + "null references.",
2002                                        "Always check to use valid references.");
2003                        return; // relative Schedulable missing
2004                }
2005        
2006                if (!after.isScheduled() && (after != _currentSchedulable)) {
2007                        myExperiment.sendWarning("Can't schedule after Schedulable! "
2008                                        + "Command ignored.", "Scheduler : " + getName()
2009                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)",
2010                                        "The Schedulable to be scheduled after is not scheduled.",
2011                                        "The Schedulable taken as reference must be scheduled.");
2012                        return; // relative Schedulable not scheduled
2013                }
2014        
2015                if ((who1 == null) && (what == null)) {
2016                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2017                                        + "Command ignored.", "Scheduler : " + getName()
2018                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)",
2019                                        "The event and Entity 'who1' references passed are both "
2020                                                        + "null references.",
2021                                        "Either Event or Entity 'who1' references must be valid.");
2022                        return; // no real parameters here anyway
2023                }
2024                
2025                if ((who2 == null) && (what == null)) {
2026                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2027                                        + "Command ignored.", "Scheduler : " + getName()
2028                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)",
2029                                        "The event and Entity 'who2' references passed are both "
2030                                                        + "null references.",
2031                                        "Either Event or Entity 'who2' references must be valid.");
2032                        return; // no real parameters here anyway
2033                }
2034        
2035                if (!(who1 instanceof SimProcess) && (what == null)) {
2036                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2037                                        + "Command ignored.", "Scheduler : " + getName()
2038                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)",
2039                                        "The Entity 'who1' needs a valid Event to be scheduled with.",
2040                                        "Only SimProcesses may be scheduled without events.");
2041                        return; // Event needed with Entity
2042                }
2043                
2044                if (!(who2 instanceof SimProcess) && (what == null)) {
2045                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2046                                        + "Command ignored.", "Scheduler : " + getName()
2047                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)",
2048                                        "The Entity 'who2' needs a valid Event to be scheduled with.",
2049                                        "Only SimProcesses may be scheduled without events.");
2050                        return; // Event needed with Entity
2051                }
2052        
2053                if (after != _currentSchedulable) {
2054                        // all parameters checked, now go on and schedule
2055                    EventNote afterNote = after.getEventNotes().get(after.getEventNotes().size()-1);
2056                        evList.insertAfter(afterNote, new EventNote(who1, who2, what, afterNote
2057                                        .getTime()));
2058                        // sets the time equivalent to the Schedulable's
2059                } else {
2060                        evList.insertAsFirst(new EventNote(who1, who2, what, presentTime()));
2061                }
2062        
2063        }
2064        
2065        /**
2066         * Schedules the given Entity and Event to happen straight after the given
2067         * Schedulable is set to be activated. Note that the siulation time for the
2068         * newly entered EventNote will be set to the Schedulable's time and the new
2069         * EventNote will be inserted directly after the Schedulable's EventNote.
2070         * <p>
2071         * <DIV align=center>
2072         * <TABLE BORDER >
2073         * <CAPTION>Valid scheduling types </CAPTION>
2074         * <TR>
2075         * <TH><DIV align=center>scheduling type</TH>
2076         * <TH>Entity object</TH>
2077         * <TH>Event object</TH>
2078         * </TR>
2079         * <TR>
2080         * <TH>Event oriented</TH>
2081         * <TD>Event or SimProcess</TD>
2082         * <TD>Event</TD>
2083         * </TR>
2084         * <TR>
2085         * <TH>process oriented</TH>
2086         * <TD>SimProcess</TD>
2087         * <TD>null</TD>
2088         * </TR>
2089         * <TR>
2090         * <TH>external event</TH>
2091         * <TD>null</TD>
2092         * <TD>external event</TD>
2093         * </TR>
2094         * </TABLE>
2095         * </DIV>
2096         * 
2097         * @param after
2098         *            Schedulable : The Schedulable after which the new event-note is
2099         *            to be scheduled
2100         * @param who1
2101         *            Entity : The first entity to be scheduled
2102         *            
2103         * @param who2
2104         *            Entity : The second entity to be scheduled
2105         *            
2106         * @param who3
2107         *            Entity : The third entity to be scheduled
2108         *            
2109         * @param what
2110         *            EventOf3Entities : The event to be scheduled
2111         */
2112        protected void scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities<?, ?, ?> what) {
2113        
2114                if (after == null) {
2115                        myExperiment.sendWarning("Can't schedule after Schedulable! "
2116                                        + "Command ignored.", "Scheduler : " + getName()
2117                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2118                                        "The reference for the Schedulable to schedule after is a "
2119                                                        + "null references.",
2120                                        "Always check to use valid references.");
2121                        return; // relative Schedulable missing
2122                }
2123        
2124                if (!after.isScheduled() && (after != _currentSchedulable)) {
2125                        myExperiment.sendWarning("Can't schedule after Schedulable! "
2126                                        + "Command ignored.", "Scheduler : " + getName()
2127                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2128                                        "The Schedulable to be scheduled after is not scheduled.",
2129                                        "The Schedulable taken as reference must be scheduled.");
2130                        return; // relative Schedulable not scheduled
2131                }
2132        
2133                if ((who1 == null) && (what == null)) {
2134                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2135                                        + "Command ignored.", "Scheduler : " + getName()
2136                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2137                                        "The event and Entity 'who1' references passed are both "
2138                                                        + "null references.",
2139                                        "Either Event or Entity 'who1' references must be valid.");
2140                        return; // no real parameters here anyway
2141                }
2142                
2143                if ((who2 == null) && (what == null)) {
2144                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2145                                        + "Command ignored.", "Scheduler : " + getName()
2146                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2147                                        "The event and Entity 'who2' references passed are both "
2148                                                        + "null references.",
2149                                        "Either Event or Entity 'who2' references must be valid.");
2150                        return; // no real parameters here anyway
2151                }
2152                
2153                if ((who3 == null) && (what == null)) {
2154                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2155                                        + "Command ignored.", "Scheduler : " + getName()
2156                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2157                                        "The event and Entity 'who3' references passed are both "
2158                                                        + "null references.",
2159                                        "Either Event or Entity 'who3' references must be valid.");
2160                        return; // no real parameters here anyway
2161                }
2162        
2163                if (!(who1 instanceof SimProcess) && (what == null)) {
2164                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2165                                        + "Command ignored.", "Scheduler : " + getName()
2166                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2167                                        "The Entity 'who1' needs a valid Event to be scheduled with.",
2168                                        "Only SimProcesses may be scheduled without events.");
2169                        return; // Event needed with Entity
2170                }
2171                
2172                if (!(who2 instanceof SimProcess) && (what == null)) {
2173                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2174                                        + "Command ignored.", "Scheduler : " + getName()
2175                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2176                                        "The Entity 'who2' needs a valid Event to be scheduled with.",
2177                                        "Only SimProcesses may be scheduled without events.");
2178                        return; // Event needed with Entity
2179                }
2180                
2181                if (!(who3 instanceof SimProcess) && (what == null)) {
2182                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2183                                        + "Command ignored.", "Scheduler : " + getName()
2184                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2185                                        "The Entity 'who3' needs a valid Event to be scheduled with.",
2186                                        "Only SimProcesses may be scheduled without events.");
2187                        return; // Event needed with Entity
2188                }
2189        
2190                if (after != _currentSchedulable) {
2191                        // all parameters checked, now go on and schedule
2192                    EventNote afterNote = after.getEventNotes().get(after.getEventNotes().size()-1);
2193                        evList.insertAfter(afterNote, new EventNote(who1, who2, who3, what, afterNote
2194                                        .getTime()));
2195                        // sets the time equivalent to the Schedulable's
2196                } else {
2197                        evList.insertAsFirst(new EventNote(who1, who2, who3, what, presentTime()));
2198                }
2199        
2200        }
2201 
2202        /**
2203         * Schedules the given Entity and Event to happen straight before the given
2204         * Schedulable is scheduled. Note that the simulation time for the newly
2205         * entered EventNote will be set to the Schedulable's time and the new
2206         * EventNote will be inserted directly before the Schedulable's EventNote.
2207         * <p>
2208         * <DIV align=center>
2209         * <TABLE BORDER >
2210         * <CAPTION>Valid scheduling types </CAPTION>
2211         * <TR>
2212         * <TH><DIV align=center>scheduling type</TH>
2213         * <TH>Entity object</TH>
2214         * <TH>Event object</TH>
2215         * </TR>
2216         * <TR>
2217         * <TH>Event oriented</TH>
2218         * <TD>Event or SimProcess</TD>
2219         * <TD>Event</TD>
2220         * </TR>
2221         * <TR>
2222         * <TH>process oriented</TH>
2223         * <TD>SimProcess</TD>
2224         * <TD>null</TD>
2225         * </TR>
2226         * <TR>
2227         * <TH>external event</TH>
2228         * <TD>null</TD>
2229         * <TD>external event</TD>
2230         * </TR>
2231         * </TABLE>
2232         * </DIV>
2233         * 
2234         * @param before
2235         *            Schedulable : The Schedulable before which the new event-note
2236         *            is to be scheduled
2237         * @param who
2238         *            Entity : The Entity to be scheduled
2239         * @param what
2240         *            Event : The event to be scheduled
2241         */
2242        protected void scheduleBefore(Schedulable before, Entity who, EventAbstract what) {
2243 
2244                if (before == null) {
2245                        myExperiment.sendWarning("Can't schedule after Schedulable! "
2246                                        + "Command ignored.", "Scheduler : " + getName()
2247                                        + " Method: Schedulable before, Entity who, EventAbstract what",
2248                                        "The reference for the Schedulable to schedule before is a "
2249                                                        + "null references.",
2250                                        "Always check to use valid references.");
2251                        return; // relative Schedulable missing
2252                }
2253 
2254                if (!before.isScheduled()) {
2255                        myExperiment.sendWarning("Can't schedule after Schedulable! "
2256                                        + "Command ignored.", "Scheduler : " + getName()
2257                                        + " Method: Schedulable before, Entity who, EventAbstract what",
2258                                        "The Schedulable to schedule after is not scheduled.",
2259                                        "The Schedulable taken as reference must be scheduled.");
2260                        return; // relative Schedulable not scheduled
2261                }
2262 
2263                if ((who == null) && (what == null)) {
2264                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2265                                        + "Command ignored.", "Scheduler : " + getName()
2266                                        + " Method: Schedulable before, Entity who, EventAbstract what",
2267                                        "The Event and Entity references passed are both "
2268                                                        + "null references.",
2269                                        "Either Event or Entity references must be valid.");
2270                        return; // no real parameters here anyway
2271                }
2272 
2273                if ((who == null) && !(what instanceof ExternalEvent)) {
2274                        myExperiment.sendWarning("Can't schedule Event! Command ignored.",
2275                                        "Scheduler : " + getName()
2276                                        + " Method: Schedulable before, Entity who, EventAbstract what",
2277                                        "The Entity reference passed is a null reference but the "
2278                                                        + "Event references is not an external event.",
2279                                        "If no valid Entity is given, the event must be of type "
2280                                                        + "external event.");
2281                        return; // if no Entity it must be ExternalEvent
2282                }
2283 
2284                if (!(who instanceof SimProcess) && (what == null)) {
2285                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2286                                        + "Command ignored.", "Scheduler : " + getName()
2287                                        + " Method: Schedulable before, Entity who, EventAbstract what",
2288                                        "The Entity needs a valid Event to be scheduled with.",
2289                                        "Only SimProcesses may be scheduled without events.");
2290                        return; // Event needed with Entity
2291                }
2292                
2293                if(what != null)
2294                {
2295                        if (what.getNumberOfEntities() > 1) 
2296                        {
2297                                myExperiment.sendWarning("Can't schedule Entity and Event! "
2298                                                + "Command ignored.", "Scheduler : " + getName()
2299                                                + " Method: Schedulable before, Entity who, EventAbstract what",
2300                                                "The method needs the correct Event to be scheduled with.",
2301                                                "You are using an event for multiple entities. You need an event for a single entity.");
2302                                return; // Event needed with Entity
2303                        }
2304                }
2305 
2306                // all parameters checked, now go on and schedule
2307                EventNote beforeNote = before.getEventNotes().get(0);
2308                evList.insertBefore(beforeNote, new EventNote(who, what, beforeNote
2309                                .getTime()));
2310                // sets the time equivalent to the Schedulable's
2311        }
2312        
2313        
2314        /**
2315         * Schedules the given Entity and Event to happen straight before the given
2316         * Schedulable is scheduled. Note that the simulation time for the newly
2317         * entered EventNote will be set to the Schedulable's time and the new
2318         * EventNote will be inserted directly before the Schedulable's EventNote.
2319         * <p>
2320         * <DIV align=center>
2321         * <TABLE BORDER >
2322         * <CAPTION>Valid scheduling types </CAPTION>
2323         * <TR>
2324         * <TH><DIV align=center>scheduling type</TH>
2325         * <TH>Entity object</TH>
2326         * <TH>Event object</TH>
2327         * </TR>
2328         * <TR>
2329         * <TH>Event oriented</TH>
2330         * <TD>Event or SimProcess</TD>
2331         * <TD>Event</TD>
2332         * </TR>
2333         * <TR>
2334         * <TH>process oriented</TH>
2335         * <TD>SimProcess</TD>
2336         * <TD>null</TD>
2337         * </TR>
2338         * <TR>
2339         * <TH>external event</TH>
2340         * <TD>null</TD>
2341         * <TD>external event</TD>
2342         * </TR>
2343         * </TABLE>
2344         * </DIV>
2345         * 
2346         * @param before
2347         *            Schedulable : The Schedulable before which the new event-note
2348         *            is to be scheduled
2349         * @param who1
2350         *            Entity : The first entity to be scheduled
2351         *            
2352         * @param who2
2353         *            Entity : The second entity to be scheduled
2354         *            
2355         * @param what
2356         *            EventOf2Entities : The event to be scheduled
2357         */
2358        protected void scheduleBefore(Schedulable before, Entity who1, Entity who2, EventOf2Entities<?, ?> what) {
2359        
2360                if (before == null) {
2361                        myExperiment.sendWarning("Can't schedule after Schedulable! "
2362                                        + "Command ignored.", "Scheduler : " + getName()
2363                                        + " Method: scheduleBefore(Schedulable before, Entity who1, Entity who2, EventOf2Entities what)",
2364                                        "The reference for the Schedulable to schedule before is a "
2365                                                        + "null references.",
2366                                        "Always check to use valid references.");
2367                        return; // relative Schedulable missing
2368                }
2369        
2370                if (!before.isScheduled()) {
2371                        myExperiment.sendWarning("Can't schedule after Schedulable! "
2372                                        + "Command ignored.", "Scheduler : " + getName()
2373                                        + " Method: scheduleBefore(Schedulable before, Entity who1, Entity who2, EventOf2Entities what)",
2374                                        "The Schedulable to schedule after is not scheduled.",
2375                                        "The Schedulable taken as reference must be scheduled.");
2376                        return; // relative Schedulable not scheduled
2377                }
2378        
2379                if ((who1 == null) && (what == null)) {
2380                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2381                                        + "Command ignored.", "Scheduler : " + getName()
2382                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)",
2383                                        "The event and Entity 'who1' references passed are both "
2384                                                        + "null references.",
2385                                        "Either Event or Entity 'who1' references must be valid.");
2386                        return; // no real parameters here anyway
2387                }
2388                
2389                if ((who2 == null) && (what == null)) {
2390                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2391                                        + "Command ignored.", "Scheduler : " + getName()
2392                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)",
2393                                        "The event and Entity 'who2' references passed are both "
2394                                                        + "null references.",
2395                                        "Either Event or Entity 'who2' references must be valid.");
2396                        return; 
2397                        
2398                }
2399        
2400                if (!(who1 instanceof SimProcess) && (what == null)) {
2401                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2402                                        + "Command ignored.", "Scheduler : " + getName()
2403                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)",
2404                                        "The Entity 'who1' needs a valid Event to be scheduled with.",
2405                                        "Only SimProcesses may be scheduled without events.");
2406                        return; // Event needed with Entity
2407                }
2408                
2409                if (!(who2 instanceof SimProcess) && (what == null)) {
2410                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2411                                        + "Command ignored.", "Scheduler : " + getName()
2412                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, EventOf2Entities what)",
2413                                        "The Entity 'who2' needs a valid Event to be scheduled with.",
2414                                        "Only SimProcesses may be scheduled without events.");
2415                        return; // Event needed with Entity
2416                }        
2417        
2418                // all parameters checked, now go on and schedule
2419            EventNote beforeNote = before.getEventNotes().get(0);
2420                evList.insertBefore(beforeNote, new EventNote(who1, who2, what, beforeNote
2421                                .getTime()));
2422                // sets the time equivalent to the Schedulable's
2423        }
2424 
2425        /**
2426         * Schedules the given Entity and Event to happen straight before the given
2427         * Schedulable is scheduled. Note that the simulation time for the newly
2428         * entered EventNote will be set to the Schedulable's time and the new
2429         * EventNote will be inserted directly before the Schedulable's EventNote.
2430         * <p>
2431         * <DIV align=center>
2432         * <TABLE BORDER >
2433         * <CAPTION>Valid scheduling types </CAPTION>
2434         * <TR>
2435         * <TH><DIV align=center>scheduling type</TH>
2436         * <TH>Entity object</TH>
2437         * <TH>Event object</TH>
2438         * </TR>
2439         * <TR>
2440         * <TH>Event oriented</TH>
2441         * <TD>Event or SimProcess</TD>
2442         * <TD>Event</TD>
2443         * </TR>
2444         * <TR>
2445         * <TH>process oriented</TH>
2446         * <TD>SimProcess</TD>
2447         * <TD>null</TD>
2448         * </TR>
2449         * <TR>
2450         * <TH>external event</TH>
2451         * <TD>null</TD>
2452         * <TD>external event</TD>
2453         * </TR>
2454         * </TABLE>
2455         * </DIV>
2456         * 
2457         * @param before
2458         *            Schedulable : The Schedulable before which the new event-note
2459         *            is to be scheduled
2460         * @param who1
2461         *            Entity : The first entity to be scheduled
2462         *            
2463         * @param who2
2464         *            Entity : The second entity to be scheduled
2465         *            
2466         * @param who3
2467         *            Entity : The third entity to be scheduled
2468         *            
2469         * @param what
2470         *            EventOf3Entities : The event to be scheduled
2471         */
2472        protected void scheduleBefore(Schedulable before, Entity who1, Entity who2, Entity who3, EventOf3Entities<?, ?, ?> what) {
2473        
2474                if (before == null) {
2475                        myExperiment.sendWarning("Can't schedule after Schedulable! "
2476                                        + "Command ignored.", "Scheduler : " + getName()
2477                                        + " Method: scheduleBefore(Schedulable before, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2478                                        "The reference for the Schedulable to schedule before is a "
2479                                                        + "null references.",
2480                                        "Always check to use valid references.");
2481                        return; // relative Schedulable missing
2482                }
2483        
2484                if (!before.isScheduled()) {
2485                        myExperiment.sendWarning("Can't schedule after Schedulable! "
2486                                        + "Command ignored.", "Scheduler : " + getName()
2487                                        + " Method: scheduleBefore(Schedulable before, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2488                                        "The Schedulable to schedule after is not scheduled.",
2489                                        "The Schedulable taken as reference must be scheduled.");
2490                        return; // relative Schedulable not scheduled
2491                }
2492        
2493                if ((who1 == null) && (what == null)) {
2494                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2495                                        + "Command ignored.", "Scheduler : " + getName()
2496                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2497                                        "The event and Entity 'who1' references passed are both "
2498                                                        + "null references.",
2499                                        "Either Event or Entity 'who1' references must be valid.");
2500                        return; // no real parameters here anyway
2501                }
2502                
2503                if ((who2 == null) && (what == null)) {
2504                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2505                                        + "Command ignored.", "Scheduler : " + getName()
2506                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2507                                        "The event and Entity 'who2' references passed are both "
2508                                                        + "null references.",
2509                                        "Either Event or Entity 'who2' references must be valid.");
2510                        return; // no real parameters here anyway
2511                }
2512                
2513                if ((who3 == null) && (what == null)) {
2514                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2515                                        + "Command ignored.", "Scheduler : " + getName()
2516                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2517                                        "The event and Entity 'who3' references passed are both "
2518                                                        + "null references.",
2519                                        "Either Event or Entity 'who3' references must be valid.");
2520                        return; // no real parameters here anyway
2521                }
2522        
2523                if (!(who1 instanceof SimProcess) && (what == null)) {
2524                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2525                                        + "Command ignored.", "Scheduler : " + getName()
2526                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2527                                        "The Entity 'who1' needs a valid Event to be scheduled with.",
2528                                        "Only SimProcesses may be scheduled without events.");
2529                        return; // Event needed with Entity
2530                }
2531                
2532                if (!(who2 instanceof SimProcess) && (what == null)) {
2533                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2534                                        + "Command ignored.", "Scheduler : " + getName()
2535                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2536                                        "The Entity 'who2' needs a valid Event to be scheduled with.",
2537                                        "Only SimProcesses may be scheduled without events.");
2538                        return; // Event needed with Entity
2539                }
2540                
2541                if (!(who3 instanceof SimProcess) && (what == null)) {
2542                        myExperiment.sendWarning("Can't schedule Entity and Event! "
2543                                        + "Command ignored.", "Scheduler : " + getName()
2544                                        + " Method: scheduleAfter(Schedulable after, Entity who1, Entity who2, Entity who3, EventOf3Entities what)",
2545                                        "The Entity 'who3' needs a valid Event to be scheduled with.",
2546                                        "Only SimProcesses may be scheduled without events.");
2547                        return; // Event needed with Entity
2548                }
2549        
2550                // all parameters checked, now go on and schedule
2551        EventNote beforeNote = before.getEventNotes().get(0);
2552                evList.insertBefore(beforeNote, new EventNote(who1, who2, who3, what, beforeNote
2553                                .getTime()));
2554                // sets the time equivalent to the Schedulable's
2555        }
2556 
2557        /**
2558         * Creates and sends a debugnote to the experiment's messagedistributor.
2559         * These debugnotes express the internal state of the event-list to visualize
2560         * the changes of state to help find bugs. Classes <code>Scheduler</code>
2561         * and <code>Queue</code> both produce debugnotes if set to do so
2562         * representing the data stored inside them. The information about the
2563         * simulation time is extracted from the experiment and must not be given as
2564         * a parameter.
2565         * 
2566         * @param description
2567         *            java.lang.String : The description of the event-list's internal
2568         *            state to be passed with this debugnote
2569         */
2570        void sendDebugNote(String description) {
2571 
2572                myExperiment.getMessageManager().receive(
2573                                new DebugNote(myExperiment.getModel(), presentTime(),
2574                                                getName(), description));
2575 
2576        }
2577 
2578        /**
2579         * Sets the execution speed rate.
2580         * 
2581         * @param executionSpeedRate
2582         *            double : the execution speed rate
2583         * @author Felix Klueckmann
2584         */
2585        protected void setExecutionSpeedRate(double executionSpeedRate) {
2586                _lock.lock();
2587                this._executionSpeedRate = executionSpeedRate;
2588                this._timeReset = true;
2589                _waitSynchCondition.signal();
2590                _lock.unlock();
2591        }
2592 
2593        /**
2594         * Sets the flag indicating if the event-list processes concurrent Events in
2595         * random order or not. If a change occurred the event-list has to be
2596         * changed accordingly.
2597         * 
2598         * @param randomizing
2599         *            boolean :<code>true</code> forces random order,
2600         *            <code>false</code> forces "linear" order
2601         * @author Ruth Meyer
2602         */
2603        protected void setRandomizingConcurrentEvents(boolean randomizing) {
2604                // nothing new?
2605                if (this._randomizingConcurrentEvents == randomizing) {
2606                        return; // just keep everything as is
2607                }
2608                // ok, we have to change the event-list (oh bother!)
2609                this._randomizingConcurrentEvents = randomizing;
2610                EventList newList;
2611                if (this.evList instanceof EventTreeList) {
2612                        if (randomizing) {
2613                                newList = new RandomizingEventTreeList();
2614                        } else {
2615                                newList = new EventTreeList();
2616                        }
2617                } else {
2618                        if (randomizing) {
2619                                newList = new RandomizingEventVector();
2620                        } else {
2621                                newList = new EventVectorList();
2622                        }
2623                }
2624                // copy old list into new list
2625                EventNote note = this.evList.firstNote();
2626                while (note != null) {
2627                        newList.insert(note);
2628                        note = this.evList.nextNote(note);
2629                }
2630                this.evList = newList;
2631        }
2632 
2633        /**
2634         * Returns the status of the current simulation. Clients should not need to
2635         * use this method explicitly. This method is polled by each thread when it
2636         * exits a lock to check wether it should continue its lifeCycle() method ot
2637         * throw a SimulationFinishedException, which seems to be the only legal way
2638         * to break out of the deep call hierarchies and stop the Process'
2639         * lifeCycle.
2640         * 
2641         * @return boolean : state of the simulation. False if still running, true
2642         *         if the simulation has already finished correctly
2643         */
2644        boolean simFinished() {
2645 
2646                return simulationFinished;
2647 
2648        }
2649 
2650        /**
2651         * Signals that the experiment is stopped.
2652         * 
2653         * @author Felix Klueckmann
2654         */
2655        protected void signalStop() {
2656                _lock.lock();
2657                this._timeReset = true;
2658                _waitSynchCondition.signal();
2659                _lock.unlock();
2660        }
2661 
2662        /**
2663         * Returns a string representation of the current state of the event-list.
2664         * The string is built by concatenating all string representations of the
2665         * contained entities, events and TimeInstant objects calling their
2666         * <code>toString()</code> methods.
2667         * 
2668         * @return java.lang.String : The string representation of the queuelist
2669         */
2670        public String toString() {
2671 
2672                StringBuffer buffer = new StringBuffer(); // strings
2673                StringBuffer enBuff = null; // Buffer for Entities
2674                EventAbstract evBuff; // Buffer for events
2675 
2676                TimeInstant tiBuff; // Buffer for Instants
2677                
2678                buffer.append("At " + this.presentTime());
2679                
2680                if (this._currentEvent != null) {
2681                    buffer.append(" current event [");
2682                    if (this._currentEvent.getNumberOfEntities() == 0) {
2683                        buffer.append("-");
2684                    } else {
2685                        buffer.append(this._currentEntity1);
2686                        if (this._currentEntity2 != null) buffer.append("," + this._currentEntity2);
2687                        if (this._currentEntity3 != null) buffer.append("," + this._currentEntity3);
2688                    }
2689                    buffer.append("][" + this._currentEvent + "]");
2690                } else if (this._currentProcess != null) {
2691            buffer.append(" current process [" + this._currentProcess + "]");
2692        }
2693                
2694                buffer.append(" <br>EvenList: ");
2695 
2696                if (evList.isEmpty()) {
2697                        // if empty, give short note
2698                        buffer.append("- empty -");
2699                        return buffer.toString();
2700                } else {
2701 
2702                        // go thru list and present Event notes
2703                        int i = 0; // counter for position
2704 
2705                        for (EventNote iNote = evList.firstNote(); iNote != null; iNote = evList
2706                                        .nextNote(iNote)) { // loop thru list
2707 
2708                                buffer.append(i + ":");
2709                i++; // increment counter
2710 
2711                                // set the buffers. This saves some calls to EventNote methods
2712                evBuff = iNote.getEvent();
2713                                if (evBuff.getNumberOfEntities() > 0) {
2714                        enBuff = new StringBuffer(iNote.getEntity1().toString());
2715                        if (evBuff.getNumberOfEntities() > 1) {
2716                            enBuff.append("," + iNote.getEntity2());
2717                            if (evBuff.getNumberOfEntities() > 2) {
2718                                enBuff.append("," + iNote.getEntity3());
2719                            }
2720 
2721                        }
2722                                } else {
2723                                    enBuff = null;
2724                                }
2725                                tiBuff = iNote.getTime();
2726 
2727                                // set Entity
2728                                if (enBuff == null)
2729                                        buffer.append("[-]");
2730                                else
2731                                        buffer.append("[" + enBuff.toString() + "]");
2732                                // embrace in brackets
2733 
2734                                // set Event
2735                                if (evBuff == null)
2736                                        buffer.append("[-]");
2737                                else
2738                                        buffer.append("[" + evBuff.toString() + "]");
2739                                // embrace in brackets
2740 
2741                                // set time
2742                                if (tiBuff == null)
2743                                        buffer.append("[-]"); // can never happen...
2744                                else
2745                                        buffer.append("[" + tiBuff.toString() + "]<br>");
2746                                // embrace in brackets
2747                                // and make a linebreak
2748                        }
2749 
2750                }
2751                // get it to the client who asked for it...
2752                return buffer.toString();
2753        }
2754}

[all classes][desmoj.core.simulator]
EMMA 2.0.9414 (unsupported private build) (C) Vladimir Roubtsov