1 | package desmoj.core.simulator; |
2 | |
3 | /** |
4 | * Provides the class for user defined events to change <b>a single</b> entity's |
5 | * internal state. 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>two</b> or <b>three</b> entities, |
8 | * refer to <code>EventOf2Entities</code> and <code>EventOf3Entities</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 type an |
12 | * Event operates on by using the generic type |
13 | * <code>Event<E></code> where |
14 | * <code>E</code> is 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 entity associated with this event by overriding the abstract method |
18 | * <code>eventRoutine(E who)</code>. |
19 | * |
20 | * @see Entity |
21 | * @see ExternalEvent |
22 | * @see EventOf2Entities |
23 | * @see EventOf3Entities |
24 | * @see TimeInstant |
25 | * @see TimeSpan |
26 | * |
27 | * @version DESMO-J, Ver. 2.3.3 copyright (c) 2011 |
28 | * @author Tim Lechler |
29 | * |
30 | * Licensed under the Apache License, Version 2.0 (the "License"); |
31 | * you may not use this file except in compliance with the License. You |
32 | * may obtain a copy of the License at |
33 | * http://www.apache.org/licenses/LICENSE-2.0 |
34 | * |
35 | * Unless required by applicable law or agreed to in writing, software |
36 | * distributed under the License is distributed on an "AS IS" |
37 | * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
38 | * or implied. See the License for the specific language governing |
39 | * permissions and limitations under the License. |
40 | * |
41 | */ |
42 | public abstract class Event<E extends Entity> extends EventAbstract { |
43 | |
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 Event(Model owner, String name, boolean showInTrace) { |
59 | |
60 | super(owner, name, showInTrace); |
61 | this.numberOfEntities = 1; |
62 | |
63 | } |
64 | |
65 | /** |
66 | * Implement this abstract method to express the changes of state this event |
67 | * does to a single entity. This event is related to the entity it has been |
68 | * scheduled with. That Entity is given note that since class |
69 | * <code>SimProcess</code> inherits from class <code>Entity</code>, an event |
70 | * can also be given a process to operate on. In this case, the process is |
71 | * scheduled and manipulated by this event just like an entity. |
72 | * |
73 | * Implement this abstract method to express the changes of state this event |
74 | * does to an entity (as <code>SimProcess</code> is a subclass of |
75 | * <code>Entity</code>, a process can be passed as well). |
76 | * <p> |
77 | * For type safety, it is recommended to derive your events from the generic |
78 | * type <code>Event<EntityOperatingOn></code> where |
79 | * <code>EntityOperatingOn</code> (which is derived from class |
80 | * <code>Entity</code>) represents the entity type your event is supposed to |
81 | * operate on. |
82 | * <p> |
83 | * Should you decide to derive your event from the raw type |
84 | * <code>Event</code> (which is not recommended), please take extra care in |
85 | * checking the given Entity parameter to your special eventRoutine since |
86 | * any subtype of Entity will be accepted! If your model uses several |
87 | * different entity types, chances are that while developing the model, |
88 | * wrong entity types might be passed. |
89 | * |
90 | * @param who |
91 | * Entity : The Entity associated to this event. |
92 | */ |
93 | public abstract void eventRoutine(E who); |
94 | |
95 | /** |
96 | * Schedules this event to act on the given entity at a certain point in |
97 | * simulation time. |
98 | * |
99 | * @param who |
100 | * E : The first entity to be manipulated by this event |
101 | * @param instant |
102 | * TimeInstant : The point in simulation time this event is |
103 | * scheduled to happen. |
104 | */ |
105 | public void schedule(E who, TimeInstant instant) { |
106 | |
107 | if ((instant == null)) { |
108 | sendWarning("Can't schedule Event!", "Event : " + getName() |
109 | + " Method: schedule(Entity who, TimeInstant instant)", |
110 | "The TimeInstant given as parameter is a null reference.", |
111 | "Be sure to have a valid TimeInstant reference before calling " |
112 | + "this method."); |
113 | return; // no proper parameter |
114 | } |
115 | |
116 | if ((who == null)) { |
117 | sendWarning("Can't schedule Event!", "Event : " + getName() |
118 | + " Method: schedule(Entity who, TimeInstant instant)", |
119 | "The Entity given as parameter is a null reference.", |
120 | "Be sure to have a valid Entity reference for this event to " |
121 | + "be scheduled with."); |
122 | return; // no proper parameter |
123 | } |
124 | |
125 | if (isScheduled()) { |
126 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
127 | + getName() |
128 | + " Method: schedule(Entity wo, TimeInstant instant)", |
129 | "The event to be scheduled is already scheduled.", |
130 | "Use method events only once, do not use them multiple " |
131 | + "times."); |
132 | return; // was already scheduled |
133 | } |
134 | |
135 | if (!isModelCompatible(who)) { |
136 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
137 | + getName() |
138 | + " Method: schedule(Entity who, TimeInstant instant)", |
139 | "The Entity to be scheduled with this event is not " |
140 | + "modelcompatible.", |
141 | "Make sure to use compatible model components only."); |
142 | return; // is not compatible |
143 | } |
144 | |
145 | // generate trace |
146 | this.generateTraceForScheduling(who, null, null, null, null, instant); |
147 | |
148 | // schedule Event |
149 | getModel().getExperiment().getScheduler().schedule(who, this, instant); |
150 | |
151 | if (currentlySendDebugNotes()) { |
152 | sendDebugNote("schedules on EventList<br>" |
153 | + getModel().getExperiment().getScheduler().toString()); |
154 | } |
155 | |
156 | } |
157 | |
158 | /** |
159 | * Schedules this event to act on the given Entity at the specified point in |
160 | * simulation time. The point of time is given as an offset to the current |
161 | * simulation time as displayed by the simulation clock. |
162 | * |
163 | * @param who |
164 | * E : The Entity this event happens to |
165 | * @param dt |
166 | * TimeSpan : The offset to the current simulation time this |
167 | * Event is to happen |
168 | * @see SimClock |
169 | */ |
170 | public void schedule(E who, TimeSpan dt) { |
171 | if ((dt == null)) { |
172 | sendWarning("Can't schedule Event!", "Event : " + getName() |
173 | + " Method: schedule(Entity who, TimeSpan dt)", |
174 | "The TimeSpan given as parameter is a null reference.", |
175 | "Be sure to have a valid TimeSpan reference before calling " |
176 | + "this method."); |
177 | return; // no proper parameter |
178 | } |
179 | |
180 | if ((who == null)) { |
181 | sendWarning("Can't schedule Event!", "Event : " + getName() |
182 | + " Method: schedule(Entity who, TimeSpan dt)", |
183 | "The Entity given as parameter is a null reference.", |
184 | "Be sure to have a valid Entity reference for this event to " |
185 | + "be scheduled with."); |
186 | return; // no proper parameter |
187 | } |
188 | |
189 | if (isScheduled()) { |
190 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
191 | + getName() + " Method: schedule(Entity wo, TimeSpan dt)", |
192 | "The event to be scheduled is already scheduled.", |
193 | "Use method events only once, do not use them multiple " |
194 | + "times."); |
195 | return; // was already scheduled |
196 | } |
197 | |
198 | if (!isModelCompatible(who)) { |
199 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
200 | + getName() + " Method: schedule(Entity who, TimeSpan dt)", |
201 | "The Entity to be scheduled with this event is not " |
202 | + "modelcompatible.", |
203 | "Make sure to use compatible model components only."); |
204 | return; // is not compatible |
205 | } |
206 | |
207 | // generate trace |
208 | this.generateTraceForScheduling(who, null, null, null, null, TimeOperations.add(presentTime(), dt)); |
209 | |
210 | // schedule Event |
211 | getModel().getExperiment().getScheduler().schedule(who, this, dt); |
212 | |
213 | if (currentlySendDebugNotes()) { |
214 | sendDebugNote("schedules on EventList<br>" |
215 | + getModel().getExperiment().getScheduler().toString()); |
216 | } |
217 | |
218 | } |
219 | |
220 | /** |
221 | * @deprecated Replaced by schedule(E who,TimeSpan dt). Schedules this event |
222 | * to act on the given Entity at the specified point in |
223 | * simulation time. The point of time is given as an offset to |
224 | * the current simulation time as displayed by the simulation |
225 | * clock. |
226 | * |
227 | * @param who |
228 | * E : The Entity this event happens to |
229 | * @param dt |
230 | * SimTime : The offset to the current simulation time this event |
231 | * is to happen |
232 | * @see SimClock |
233 | */ |
234 | @Deprecated |
235 | public void schedule(E who, SimTime dt) { |
236 | schedule(who, SimTime.toTimeSpan(dt)); |
237 | } |
238 | |
239 | /** |
240 | * Schedules this event to act on the given Entity directly after the given |
241 | * Schedulable is already set to be activated. Note that this event's point |
242 | * of simulation time will be set to be the same as the Schedulable's time. |
243 | * Thus this event will occur directly after the given Schedulable but the |
244 | * simulation clock will not change. Make sure that the Schedulable given as |
245 | * parameter is actually scheduled. |
246 | * |
247 | * @param after |
248 | * Schedulable : The Schedulable this entity should be scheduled |
249 | * after |
250 | * @param who |
251 | * E : The Entity to be manipulated by this event |
252 | */ |
253 | public void scheduleAfter(Schedulable after, E who) { |
254 | |
255 | if (who == null) { |
256 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
257 | + getName() + " Method: scheduleAfter(Schedulable after, " |
258 | + "Entity who)", |
259 | "The Entity 'who' given as parameter is a null reference.", |
260 | "Be sure to have a valid Entity reference before calling " |
261 | + "this method."); |
262 | return; // no proper parameter |
263 | } |
264 | |
265 | if (after == null) { |
266 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
267 | + getName() + " Method: scheduleAfter(Schedulable after, " |
268 | + "Entity who)", |
269 | "The Schedulable given as parameter is a null reference.", |
270 | "Be sure to have a valid Schedulable reference for this " |
271 | + "Event to be scheduled with."); |
272 | return; // no proper parameter |
273 | } |
274 | |
275 | if (isScheduled()) { |
276 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
277 | + getName() + " Method: scheduleAfter(Schedulable after, " |
278 | + "Entity who)", |
279 | "The event to be scheduled is already scheduled.", |
280 | "Use method events only once, do not use them multiple " |
281 | + "times."); |
282 | return; // was already scheduled |
283 | } |
284 | |
285 | if (who.isScheduled()) { |
286 | sendWarning("Can't schedule Event! Command ignored.", "Entity : " |
287 | + getName() + " Method: scheduleAfter(Schedulable after, " |
288 | + "Entity who)", "The Entity '" + who.getName() |
289 | + "'to be scheduled with this " |
290 | + "Event is already scheduled.", |
291 | "Use method reSchedule(TimeSpan dt) to shift the entity " |
292 | + "to be scheduled at some other point of time."); |
293 | return; // was already scheduled |
294 | } |
295 | |
296 | if (!after.isScheduled()) { |
297 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
298 | + getName() + " Method: scheduleAfter(Schedulable after, " |
299 | + "Entity who)", "The Schedulable '" + after.getName() |
300 | + "' given as a positioning " |
301 | + "reference has to be already scheduled but is not.", |
302 | "Use method isScheduled() of any Schedulable to find out " |
303 | + "if it is already scheduled."); |
304 | return; // was not scheduled |
305 | } |
306 | |
307 | if (!isModelCompatible(who)) { |
308 | sendWarning("Can't schedule Event! Command ignored", "Entity : " |
309 | + getName() + " Method: scheduleAfter(Schedulable after, " |
310 | + "Entity who)", |
311 | "The Entity to be scheduled with this event is not " |
312 | + "modelcompatible.", |
313 | "Make sure to use compatible model components only."); |
314 | return; // is not compatible |
315 | } |
316 | |
317 | // generate trace |
318 | this.generateTraceForScheduling(who, null, null, after, null, after.getEventNotes().get(after.getEventNotes().size()-1).getTime()); |
319 | |
320 | // schedule Event |
321 | getModel().getExperiment().getScheduler().scheduleAfter(after, who, |
322 | this); |
323 | |
324 | if (currentlySendDebugNotes()) { |
325 | sendDebugNote("scheduleAfter " + after.getQuotedName() |
326 | + " on EventList<br>" |
327 | + getModel().getExperiment().getScheduler().toString()); |
328 | } |
329 | |
330 | } |
331 | |
332 | /** |
333 | * Schedules this event to act on the given Entity directly before the given |
334 | * Schedulable is already set to be activated. Note that this event's point |
335 | * of simulation time will be set to be the same as the Schedulable's time. |
336 | * Thus this event will occur directly before the given Schedulable but the |
337 | * simulation clock will not change. Make sure that the Schedulable given as |
338 | * parameter is actually scheduled. |
339 | * |
340 | * @param before |
341 | * Schedulable : The Schedulable this entity should be scheduled |
342 | * before |
343 | * @param who |
344 | * E : The Entity to be manipulated by this event |
345 | */ |
346 | public void scheduleBefore(Schedulable before, E who) { |
347 | |
348 | if ((who == null)) { |
349 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
350 | + getName() |
351 | + " Method: scheduleBefore(Schedulable before, " |
352 | + "Entity who)", |
353 | "The Entity given as parameter is a null reference.", |
354 | "Be sure to have a valid Entity reference before calling " |
355 | + "this method."); |
356 | return; // no proper parameter |
357 | } |
358 | |
359 | if ((before == null)) { |
360 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
361 | + getName() |
362 | + " Method: scheduleBefore(Schedulable before, " |
363 | + "Entity who)", |
364 | "The Schedulable given as parameter is a null reference.", |
365 | "Be sure to have a valid Schedulable reference for this " |
366 | + "Event to be scheduled with."); |
367 | return; // no proper parameter |
368 | } |
369 | |
370 | if (isScheduled()) { |
371 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
372 | + getName() |
373 | + " Method: scheduleBefore(Schedulable before, " |
374 | + "Entity who)", |
375 | "The event to be scheduled is already scheduled.", |
376 | "Use method events only once, do not use them multiple " |
377 | + "times."); |
378 | return; // was already scheduled |
379 | } |
380 | |
381 | if (who.isScheduled()) { |
382 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
383 | + getName() |
384 | + " Method: scheduleBefore(Schedulable before, " |
385 | + "Entity who)", "The Entity '" + who.getName() |
386 | + "'to be scheduled with this " |
387 | + "Event is already scheduled.", |
388 | "Use method reSchedule(TimeSpan dt) to shift the entity " |
389 | + "to be scheduled at some other point of time."); |
390 | return; // was already scheduled |
391 | } |
392 | |
393 | if (!before.isScheduled()) { |
394 | sendWarning("Can't schedule Event! Command ignored.", "Event : " |
395 | + getName() + " Method: scheduleBefore(Schedulable after, " |
396 | + "Entity who)", "The Schedulable '" + before.getName() |
397 | + "' given as a " |
398 | + "positioning reference has to be already scheduled but " |
399 | + "is not.", |
400 | "Use method isScheduled() of any Schedulable to find out " |
401 | + "if it is already scheduled."); |
402 | return; // was not scheduled |
403 | } |
404 | |
405 | if (!isModelCompatible(who)) { |
406 | sendWarning("Can't schedule Event! Command ignored", "Event : " |
407 | + getName() |
408 | + " Method: scheduleBeforer(Schedulable before, " |
409 | + "Entity who)", |
410 | "The Entity to be scheduled with this event is not " |
411 | + "modelcompatible.", |
412 | "Make sure to use compatible model components only."); |
413 | return; // is not compatible |
414 | } |
415 | |
416 | // generate trace |
417 | this.generateTraceForScheduling(who, null, null, null, before, before.getEventNotes().get(0).getTime()); |
418 | |
419 | // schedule Event |
420 | getModel().getExperiment().getScheduler().scheduleBefore(before, who, |
421 | this); |
422 | |
423 | if (currentlySendDebugNotes()) { |
424 | sendDebugNote("scheduleBefore " + before.getQuotedName() |
425 | + " on EventList<br>" |
426 | + getModel().getExperiment().getScheduler().toString()); |
427 | } |
428 | |
429 | } |
430 | |
431 | /** |
432 | * Creates and returns a copy of this event. |
433 | * Note that subclasses have to implement the interface |
434 | * </code>java.lang.Cloneable</code> to actually use this method as |
435 | * otherwise, a </code>CloneNotSupportedException</code> will be thrown. |
436 | * |
437 | * @return Event<E> : A copy of this event. |
438 | */ |
439 | protected Event<E> clone() throws CloneNotSupportedException { |
440 | return (Event<E>) super.clone(); |
441 | } |
442 | } |