1 | package desmoj.core.simulator; |
2 | |
3 | /** |
4 | * Provides the class for user defined events to change <b>three</b> entities' |
5 | * internal states. The state of a discrete model is changed by events that occur |
6 | * at distinct points of simulation time.<p> |
7 | * For events changing the state of <b>one</b> or <b>two</b> entities, |
8 | * refer to <code>Event</code> and <code>EventOf2Entities</code>. |
9 | * Events not associated to a specific entity are based on <code>ExternalEvent</code>. |
10 | * <p> |
11 | * For type safety it is recommended to generically assign the entity types an |
12 | * <code>EventOf3Entities</code> operates on by using the generic type |
13 | * <code>EventOf3Entities<E,F,G></code> where |
14 | * <code>E</code>, <code>F</code> and <code>G</code> are derived from <code>Entity</code>. |
15 | * <p> |
16 | * All event object should be used only once. Implement the changes of state for the |
17 | * specific entities associated with this event by overriding the abstract method |
18 | * <code>eventRoutine(E who1, F who2, G who3)</code>. |
19 | * |
20 | * @see Entity |
21 | * @see ExternalEvent |
22 | * @see Event |
23 | * @see EventOf2Entities |
24 | * @see TimeInstant |
25 | * @see TimeSpan |
26 | * |
27 | * @version DESMO-J, Ver. 2.3.3 copyright (c) 2011 |
28 | * @author Tim Lechler |
29 | * @author modified by Justin Neumann |
30 | * |
31 | * Licensed under the Apache License, Version 2.0 (the "License"); |
32 | * you may not use this file except in compliance with the License. You |
33 | * may obtain a copy of the License at |
34 | * http://www.apache.org/licenses/LICENSE-2.0 |
35 | * |
36 | * Unless required by applicable law or agreed to in writing, software |
37 | * distributed under the License is distributed on an "AS IS" |
38 | * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
39 | * or implied. See the License for the specific language governing |
40 | * permissions and limitations under the License. |
41 | * |
42 | */ |
43 | public abstract class EventOf3Entities<E extends Entity, F extends Entity, G extends Entity> extends EventAbstract { |
44 | |
45 | /** |
46 | * Creates a new Event of the given model, with the given name and trace |
47 | * option. |
48 | * |
49 | * @param name |
50 | * java.lang.String : The name of this event |
51 | * @param owner |
52 | * Model : The model this event is associated to |
53 | * @param showInTrace |
54 | * boolean : Flag for showing Event in trace-files. Set it to |
55 | * <code>true</code> if Event should show up in trace. Set it to |
56 | * <code>false</code> if Event should not be shown in trace. |
57 | */ |
58 | public EventOf3Entities(Model owner, String name, boolean showInTrace) { |
59 | |
60 | super(owner, name, showInTrace); |
61 | this.numberOfEntities = 3; |
62 | |
63 | } |
64 | |
65 | /** |
66 | * Implement this abstract method to express the changes of state this event |
67 | * does to three entities (as <code>SimProcess</code> is a subclass of |
68 | * <code>Entity</code>, processes can be passed as well). |
69 | * <p> |
70 | * For type safety, it is recommended to derive your events from the generic |
71 | * type <code>EventOf3Entities<EntityType1,EntityType2,EntityType3></code> where |
72 | * <code>EntityType1</code>, <code>EntityType2</code> and <code>EntityType3</code> |
73 | * (which are derived from class <code>Entity</code>) represent the entity types |
74 | * your event is supposed to operate on. |
75 | * <p> |
76 | * Should you decide to derive your event from the raw type |
77 | * <code>EventOf3Entities</code> (which is not recommended), please take extra care in |
78 | * checking the given Entity parameters to your special eventRoutine since |
79 | * any subtype of Entity will be accepted! If your model uses several |
80 | * different entity types, chances are that while developing the model, |
81 | * wrong entity types might be passed. |
82 | * |
83 | * @param who1 |
84 | * E : The first entity associated to this event. |
85 | * @param who2 |
86 | * F : The second entity associated to this event. |
87 | * @param who3 |
88 | * G : The second entity associated to this event. |
89 | */ |
90 | public abstract void eventRoutine(E who1, F who2, G who3); |
91 | |
92 | /** |
93 | * Schedules this event to act on the given entities at a certain point in |
94 | * simulation time. |
95 | * |
96 | * @param who1 |
97 | * E : The first entity to be manipulated by this event |
98 | * @param who2 |
99 | * F : The second entity to be manipulated by this event |
100 | * @param who3 |
101 | * G : The third entity to be manipulated by this event |
102 | * @param instant |
103 | * TimeInstant : The point in simulation time this event is |
104 | * scheduled to happen. |
105 | */ |
106 | public void schedule(E who1, F who2, G who3, TimeInstant instant) { |
107 | |
108 | if ((instant == null)) { |
109 | sendWarning("Can't schedule Event!", "Event : " + getName() |
110 | + " Method: eventRoutine(E who1, F who2, G who3)", |
111 | "The TimeInstant given as parameter is a null reference.", |
112 | "Be sure to have a valid TimeInstant reference before calling " |
113 | + "this method."); |
114 | return; // no proper parameter |
115 | } |
116 | |
117 | if ((who1 == null)) { |
118 | sendWarning("Can't schedule Event!", "Event : " + getName() |
119 | + " Method: eventRoutine(E who1, F who2, G who3)", |
120 | "The first entity given as parameter is a null reference.", |
121 | "Be sure to have a valid Entity reference for this event to " |
122 | + "be scheduled with."); |
123 | return; // no proper parameter |
124 | } |
125 | |
126 | if ((who2 == null)) { |
127 | sendWarning("Can't schedule Event!", "Event : " + getName() |
128 | + " Method: eventRoutine(E who1, F who2, G who3)", |
129 | "The second entity given as parameter is a null reference.", |
130 | "Be sure to have a valid Entity reference for this event to " |
131 | + "be scheduled with."); |
132 | return; // no proper parameter |
133 | } |
134 | |
135 | if ((who3 == null)) { |
136 | sendWarning("Can't schedule Event!", "Event : " + getName() |
137 | + " Method: eventRoutine(E who1, F who2, G who3)", |
138 | "The third entity given as parameter is a null reference.", |
139 | "Be sure to have a valid Entity reference for this event to " |
140 | + "be scheduled with."); |
141 | return; // no proper parameter |
142 | } |
143 | |
144 | if (isScheduled()) { |
145 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
146 | + getName() |
147 | + " Method: eventRoutine(E who1, F who2, G who3)", |
148 | "The event to be scheduled is already scheduled.", |
149 | "Use method events only once, do not use them multiple " |
150 | + "times."); |
151 | return; // was already scheduled |
152 | } |
153 | |
154 | if (!isModelCompatible(who1)) { |
155 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
156 | + getName() |
157 | + " Method: eventRoutine(E who1, F who2, G who3)", |
158 | "The first entity to be scheduled with this event is not " |
159 | + "modelcompatible.", |
160 | "Make sure to use compatible model components only."); |
161 | return; // is not compatible |
162 | } |
163 | |
164 | if (!isModelCompatible(who2)) { |
165 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
166 | + getName() |
167 | + " Method: eventRoutine(E who1, F who2, G who3)", |
168 | "The second entity to be scheduled with this event is not " |
169 | + "modelcompatible.", |
170 | "Make sure to use compatible model components only."); |
171 | return; // is not compatible |
172 | } |
173 | |
174 | if (!isModelCompatible(who3)) { |
175 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
176 | + getName() |
177 | + " Method: eventRoutine(E who1, F who2, G who3)", |
178 | "The third entity to be scheduled with this event is not " |
179 | + "modelcompatible.", |
180 | "Make sure to use compatible model components only."); |
181 | return; // is not compatible |
182 | } |
183 | |
184 | // generate trace |
185 | this.generateTraceForScheduling(who1, who2, who3, null, null, instant); |
186 | |
187 | // schedule Event |
188 | getModel().getExperiment().getScheduler().schedule(who1, who2, who3, this, instant); |
189 | if (currentlySendDebugNotes()) { |
190 | sendDebugNote("schedules on EventList<br>" |
191 | + getModel().getExperiment().getScheduler().toString()); |
192 | } |
193 | |
194 | } |
195 | |
196 | /** |
197 | * Schedules this event to act on the given entities at the specified point in |
198 | * simulation time. The point of time is given as an offset to the current |
199 | * simulation time as displayed by the simulation clock. |
200 | * |
201 | * @param who1 |
202 | * E : The first entity this event happens to |
203 | * @param who2 |
204 | * F : The second entity this event happens to |
205 | * @param who3 |
206 | * G : The third entity this event happens to |
207 | * @param dt |
208 | * TimeSpan : The offset to the current simulation time this |
209 | * Event is to happen |
210 | * @see SimClock |
211 | */ |
212 | public void schedule(E who1, F who2, G who3, TimeSpan dt) { |
213 | if ((dt == null)) { |
214 | sendWarning("Can't schedule Event!", "Event : " + getName() |
215 | + " Method: schedule(E who1, F who2, G who3, TimeSpan dt)", |
216 | "The TimeSpan given as parameter is a null reference.", |
217 | "Be sure to have a valid TimeSpan reference before calling " |
218 | + "this method."); |
219 | return; // no proper parameter |
220 | } |
221 | |
222 | if ((who1 == null)) { |
223 | sendWarning("Can't schedule Event!", "Event : " + getName() |
224 | + " Method: schedule(E who1, F who2, G who3, TimeSpan dt)", |
225 | "The first entity given as parameter is a null reference.", |
226 | "Be sure to have a valid Entity reference for this event to " |
227 | + "be scheduled with."); |
228 | return; // no proper parameter |
229 | } |
230 | |
231 | if ((who2 == null)) { |
232 | sendWarning("Can't schedule Event!", "Event : " + getName() |
233 | + " Method: schedule(E who1, F who2, G who3, TimeSpan dt)", |
234 | "The second entity given as parameter is a null reference.", |
235 | "Be sure to have a valid Entity reference for this event to " |
236 | + "be scheduled with."); |
237 | return; // no proper parameter |
238 | } |
239 | |
240 | if ((who3 == null)) { |
241 | sendWarning("Can't schedule Event!", "Event : " + getName() |
242 | + " Method: schedule(E who1, F who2, G who3, TimeSpan dt)", |
243 | "The third entity given as parameter is a null reference.", |
244 | "Be sure to have a valid Entity reference for this event to " |
245 | + "be scheduled with."); |
246 | return; // no proper parameter |
247 | } |
248 | |
249 | if (isScheduled()) { |
250 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
251 | + getName() + " Method: schedule(E who1, F who2, G who3, TimeSpan dt)", |
252 | "The event to be scheduled is already scheduled.", |
253 | "Use method events only once, do not use them multiple " |
254 | + "times."); |
255 | return; // was already scheduled |
256 | } |
257 | |
258 | if (!isModelCompatible(who1)) { |
259 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
260 | + getName() + " Method: schedule(E who1, F who2, G who3, TimeSpan dt)", |
261 | "The first entity to be scheduled with this event is not " |
262 | + "modelcompatible.", |
263 | "Make sure to use compatible model components only."); |
264 | return; // is not compatible |
265 | } |
266 | |
267 | if (!isModelCompatible(who2)) { |
268 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
269 | + getName() + " Method: schedule(E who1, F who2, G who3, TimeSpan dt)", |
270 | "The second entity to be scheduled with this event is not " |
271 | + "modelcompatible.", |
272 | "Make sure to use compatible model components only."); |
273 | return; // is not compatible |
274 | } |
275 | |
276 | if (!isModelCompatible(who3)) { |
277 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
278 | + getName() + " Method: schedule(E who1, F who2, G who3, TimeSpan dt)", |
279 | "The third entity to be scheduled with this event is not " |
280 | + "modelcompatible.", |
281 | "Make sure to use compatible model components only."); |
282 | return; // is not compatible |
283 | } |
284 | |
285 | // generate trace |
286 | this.generateTraceForScheduling(who1, who2, who3, null, null, TimeOperations.add(presentTime(), dt)); |
287 | |
288 | // schedule Event |
289 | getModel().getExperiment().getScheduler().schedule(who1, who2, who3, this, dt); |
290 | |
291 | if (currentlySendDebugNotes()) { |
292 | sendDebugNote("schedules on EventList<br>" |
293 | + getModel().getExperiment().getScheduler().toString()); |
294 | } |
295 | |
296 | } |
297 | |
298 | /** |
299 | * Schedules this event to act on the given Entities directly after the given |
300 | * Schedulable is already set to be activated. Note that this event's point |
301 | * of simulation time will be set to be the same as the Schedulable's time. |
302 | * Thus this event will occur directly after the given Schedulable but the |
303 | * simulation clock will not change. Make sure that the Schedulable given as |
304 | * parameter is actually scheduled. |
305 | * |
306 | * @param after |
307 | * Schedulable : The Schedulable this entity should be scheduled |
308 | * after |
309 | * @param who1 |
310 | * E : The first entity to be manipulated by this event |
311 | * @param who2 |
312 | * F : The second entity to be manipulated by this event |
313 | * @param who3 |
314 | * G : The third entity to be manipulated by this event |
315 | */ |
316 | public void scheduleAfter(Schedulable after, E who1, F who2, G who3) { |
317 | |
318 | if (who1 == null) { |
319 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
320 | + getName() + " Method: scheduleAfter(Schedulable after, E who1, F who2, G who3)", |
321 | "The Entity 'who1' given as parameter is a null reference.", |
322 | "Be sure to have a valid Entity reference before calling " |
323 | + "this method."); |
324 | return; // no proper parameter |
325 | } |
326 | |
327 | if (who2 == null) { |
328 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
329 | + getName() + " Method: scheduleAfter(Schedulable after, E who1, F who2, G who3)", |
330 | "The Entity 'who2' given as parameter is a null reference.", |
331 | "Be sure to have a valid Entity reference before calling " |
332 | + "this method."); |
333 | return; // no proper parameter |
334 | } |
335 | |
336 | if (who3 == null) { |
337 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
338 | + getName() + " Method: scheduleAfter(Schedulable after, E who1, F who2, G who3)", |
339 | "The Entity 'who3' given as parameter is a null reference.", |
340 | "Be sure to have a valid Entity reference before calling " |
341 | + "this method."); |
342 | return; // no proper parameter |
343 | } |
344 | |
345 | if (after == null) { |
346 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
347 | + getName() + " Method: scheduleAfter(Schedulable after, E who1, F who2, G who3)", |
348 | "The Schedulable given as parameter is a null reference.", |
349 | "Be sure to have a valid Schedulable reference for this " |
350 | + "Event to be scheduled with."); |
351 | return; // no proper parameter |
352 | } |
353 | |
354 | if (isScheduled()) { |
355 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
356 | + getName() + " Method: scheduleAfter(Schedulable after, E who1, F who2, G who3)", |
357 | "The event to be scheduled is already scheduled.", |
358 | "Use method events only once, do not use them multiple " |
359 | + "times."); |
360 | return; // was already scheduled |
361 | } |
362 | |
363 | if (!after.isScheduled()) { |
364 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
365 | + getName() + " Method: scheduleAfter(Schedulable after, E who1, F who2, G who3)", |
366 | "The Schedulable '" + after.getName() |
367 | + "' given as a positioning " |
368 | + "reference has to be already scheduled but is not.", |
369 | "Use method isScheduled() of any Schedulable to find out " |
370 | + "if it is already scheduled."); |
371 | return; // was not scheduled |
372 | } |
373 | |
374 | if (!isModelCompatible(who1)) { |
375 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
376 | + getName() + " Method: scheduleAfter(Schedulable after, E who1, F who2, G who3)", |
377 | "The first Entity to be scheduled with this event is not " |
378 | + "modelcompatible.", |
379 | "Make sure to use compatible model components only."); |
380 | return; // is not compatible |
381 | } |
382 | |
383 | if (!isModelCompatible(who2)) { |
384 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
385 | + getName() + " Method: scheduleAfter(Schedulable after, E who1, F who2, G who3)", |
386 | "The second entity to be scheduled with this event is not " |
387 | + "modelcompatible.", |
388 | "Make sure to use compatible model components only."); |
389 | return; // is not compatible |
390 | } |
391 | |
392 | if (!isModelCompatible(who3)) { |
393 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
394 | + getName() + " Method: scheduleAfter(Schedulable after, E who1, F who2, G who3)", |
395 | "The third entity to be scheduled with this event is not " |
396 | + "modelcompatible.", |
397 | "Make sure to use compatible model components only."); |
398 | return; // is not compatible |
399 | } |
400 | |
401 | // generate trace |
402 | this.generateTraceForScheduling(who1, who2, who3, after, null, after.getEventNotes().get(after.getEventNotes().size()-1).getTime()); |
403 | |
404 | // schedule Event |
405 | getModel().getExperiment().getScheduler().scheduleAfter(after, who1, who2, who3, |
406 | this); |
407 | |
408 | if (currentlySendDebugNotes()) { |
409 | sendDebugNote("scheduleAfter " + after.getQuotedName() |
410 | + " on EventList<br>" |
411 | + getModel().getExperiment().getScheduler().toString()); |
412 | } |
413 | |
414 | } |
415 | |
416 | /** |
417 | * Schedules this event to act on the given Entities directly before the given |
418 | * Schedulable is already set to be activated. Note that this event's point |
419 | * of simulation time will be set to be the same as the Schedulable's time. |
420 | * Thus this event will occur directly before the given Schedulable but the |
421 | * simulation clock will not change. Make sure that the Schedulable given as |
422 | * parameter is actually scheduled. |
423 | * |
424 | * @param before |
425 | * Schedulable : The Schedulable this entity should be scheduled |
426 | * before |
427 | * @param who1 |
428 | * E : The first entity to be manipulated by this event |
429 | * @param who2 |
430 | * F : The second entity to be manipulated by this event |
431 | * @param who3 |
432 | * G : The third entity to be manipulated by this event |
433 | */ |
434 | public void scheduleBefore(Schedulable before, E who1, F who2, G who3) { |
435 | |
436 | if (who1 == null) { |
437 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
438 | + getName() + " Method: scheduleBefore(Schedulable after, E who1, F who2, G who3)", |
439 | "The Entity 'who1' given as parameter is a null reference.", |
440 | "Be sure to have a valid Entity reference before calling " |
441 | + "this method."); |
442 | return; // no proper parameter |
443 | } |
444 | |
445 | if (who2 == null) { |
446 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
447 | + getName() + " Method: scheduleBefore(Schedulable after, E who1, F who2, G who3)", |
448 | "The Entity 'who2' given as parameter is a null reference.", |
449 | "Be sure to have a valid Entity reference before calling " |
450 | + "this method."); |
451 | return; // no proper parameter |
452 | } |
453 | |
454 | if (who3 == null) { |
455 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
456 | + getName() + " Method: scheduleBefore(Schedulable after, E who1, F who2, G who3)", |
457 | "The Entity 'who3' given as parameter is a null reference.", |
458 | "Be sure to have a valid Entity reference before calling " |
459 | + "this method."); |
460 | return; // no proper parameter |
461 | } |
462 | |
463 | if ((before == null)) { |
464 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
465 | + getName() |
466 | + " Method: scheduleBefore(Schedulable before, E who1, F who2, G who3)", |
467 | "The Schedulable given as parameter is a null reference.", |
468 | "Be sure to have a valid Schedulable reference for this " |
469 | + "Event to be scheduled with."); |
470 | return; // no proper parameter |
471 | } |
472 | |
473 | if (isScheduled()) { |
474 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
475 | + getName() |
476 | + " Method: scheduleBefore(Schedulable before, E who1, F who2, G who3)", |
477 | "The event to be scheduled is already scheduled.", |
478 | "Use method events only once, do not use them multiple " |
479 | + "times."); |
480 | return; // was already scheduled |
481 | } |
482 | |
483 | if (!before.isScheduled()) { |
484 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
485 | + getName() + " Method: scheduleBefore(Schedulable after, " |
486 | + " Method: scheduleBefore(Schedulable before, E who1, F who2, G who3)", |
487 | "The Schedulable '" + before.getName() |
488 | + "' given as a " |
489 | + "positioning reference has to be already scheduled but " |
490 | + "is not.", |
491 | "Use method isScheduled() of any Schedulable to find out " |
492 | + "if it is already scheduled."); |
493 | return; // was not scheduled |
494 | } |
495 | |
496 | if (!isModelCompatible(who1)) { |
497 | sendWarning("Can't schedule Event! Command ignored", "Event : " |
498 | + getName() |
499 | + " Method: scheduleBefore(Schedulable before, E who1, F who2, G who3)", |
500 | "The first entity to be scheduled with this event is not " |
501 | + "modelcompatible.", |
502 | "Make sure to use compatible model components only."); |
503 | return; // is not compatible |
504 | } |
505 | |
506 | if (!isModelCompatible(who2)) { |
507 | sendWarning("Can't schedule Event! Command ignored", "Event : " |
508 | + getName() |
509 | + " Method: scheduleBefore(Schedulable before, E who1, F who2, G who3)", |
510 | "The second entity to be scheduled with this event is not " |
511 | + "modelcompatible.", |
512 | "Make sure to use compatible model components only."); |
513 | return; // is not compatible |
514 | } |
515 | |
516 | if (!isModelCompatible(who3)) { |
517 | sendWarning("Can't schedule Event! Command ignored", "Event : " |
518 | + getName() |
519 | + " Method: scheduleBefore(Schedulable before, E who1, F who2, G who3)", |
520 | "The third entity to be scheduled with this event is not " |
521 | + "modelcompatible.", |
522 | "Make sure to use compatible model components only."); |
523 | return; // is not compatible |
524 | } |
525 | |
526 | // generate trace |
527 | this.generateTraceForScheduling(who1, who2, who3, null, before, before.getEventNotes().get(0).getTime()); |
528 | |
529 | // schedule Event |
530 | getModel().getExperiment().getScheduler().scheduleBefore(before, who1, who2, who3, |
531 | this); |
532 | |
533 | if (currentlySendDebugNotes()) { |
534 | sendDebugNote("scheduleBefore " + before.getQuotedName() |
535 | + " on EventList<br>" |
536 | + getModel().getExperiment().getScheduler().toString()); |
537 | } |
538 | |
539 | } |
540 | |
541 | /** |
542 | * Creates and returns a copy of this event. |
543 | * Note that subclasses have to implement the interface |
544 | * </code>java.lang.Cloneable</code> to actually use this method as |
545 | * otherwise, a </code>CloneNotSupportedException</code> will be thrown. |
546 | * |
547 | * @return EventOf3Entities<E,F,G> : A copy of this event. |
548 | */ |
549 | protected EventOf3Entities<E,F,G> clone() throws CloneNotSupportedException { |
550 | return (EventOf3Entities<E,F,G>) super.clone(); |
551 | } |
552 | } |