MATSIM
SingleHandlerEventsManager.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * SingleHandlerEventsManager.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2014 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.core.events;
22 
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Map;
28 import java.util.Set;
29 
30 import org.apache.logging.log4j.LogManager;
31 import org.apache.logging.log4j.Logger;
75 
82 public final class SingleHandlerEventsManager implements EventsManager {
83 
84  private static final Logger log = LogManager.getLogger(SingleHandlerEventsManager.class);
85 
86  /*
87  * This cannot be just a map<Class, Method> since we need to differentiate between
88  * a) Class is handled the first time, therefore we have to check whether the Handler can handle it (no HandlerInfo object)
89  * b) Class cannot be handled (HandlerInfo with empty Method field)
90  */
91  private final Map<Class<?>, HandlerInfo> methodToHandle = new HashMap<Class<?>, HandlerInfo>();
92 
93  private final EventHandler eventHandler;
94 
95  private final boolean isLeaveLinkHandler;
96  private final boolean isLinkEnterHandler;
97  private final boolean isWait2LinkHandler;
98  private final boolean isPersonArrivalHandler;
99  private final boolean isPersonDepatureHandler;
100  private final boolean isActivityEndHandler;
101  private final boolean isActivityStartHandler;
102  private final boolean isTeleportationArrivalHandler;
103  private final boolean isTransitDriverStartsHandler;
104  private final boolean isPersonStuckHandler;
105  private final boolean isPersonMoneyHandler;
106  private final boolean isPersonScoreHandler;
107  private final boolean isAgentWaitingForPtHandler;
108  private final boolean isPersonEntersVehicleHandler;
109  private final boolean isPersonLeavesVehicleHandler;
110  private final boolean isVehicleDepartsAtFacilityHandler;
111  private final boolean isVehicleArrivesAtFacilityHandler;
112  private final boolean isVehicleLeavesTrafficHandler;
113  private final boolean isVehicleAbortsHandler;
114  private final boolean isBasicEventHandler;
115 
116  private long counter = 0;
117  private long nextCounterMsg = 1;
118 
119  private boolean isActive = true;
120 
122  this.eventHandler = eventHandler;
123 
124  this.isLeaveLinkHandler = this.eventHandler instanceof LinkLeaveEventHandler;
125  this.isLinkEnterHandler = this.eventHandler instanceof LinkEnterEventHandler;
126  this.isWait2LinkHandler = this.eventHandler instanceof VehicleEntersTrafficEventHandler;
127  this.isPersonArrivalHandler = this.eventHandler instanceof PersonArrivalEventHandler;
128  this.isPersonDepatureHandler = this.eventHandler instanceof PersonDepartureEventHandler;
129  this.isActivityEndHandler = this.eventHandler instanceof ActivityEndEventHandler;
130  this.isActivityStartHandler = this.eventHandler instanceof ActivityStartEventHandler;
131  this.isTeleportationArrivalHandler = this.eventHandler instanceof TeleportationArrivalEventHandler;
132  this.isTransitDriverStartsHandler = this.eventHandler instanceof TransitDriverStartsEventHandler;
133  this.isPersonStuckHandler = this.eventHandler instanceof PersonStuckEventHandler;
134  this.isPersonMoneyHandler = this.eventHandler instanceof PersonMoneyEventHandler;
135  this.isPersonScoreHandler = this.eventHandler instanceof PersonScoreEventHandler;
136  this.isAgentWaitingForPtHandler = this.eventHandler instanceof AgentWaitingForPtEventHandler;
137  this.isPersonEntersVehicleHandler = this.eventHandler instanceof PersonEntersVehicleEventHandler;
138  this.isPersonLeavesVehicleHandler = this.eventHandler instanceof PersonLeavesVehicleEventHandler;
139  this.isVehicleDepartsAtFacilityHandler = this.eventHandler instanceof VehicleDepartsAtFacilityEventHandler;
140  this.isVehicleArrivesAtFacilityHandler = this.eventHandler instanceof VehicleArrivesAtFacilityEventHandler;
141  this.isVehicleLeavesTrafficHandler = this.eventHandler instanceof VehicleLeavesTrafficEventHandler;
142  this.isVehicleAbortsHandler = this.eventHandler instanceof VehicleAbortsEventHandler;
143  this.isBasicEventHandler = this.eventHandler instanceof BasicEventHandler;
144 
145  // identify the implemented Handler Interfaces
146  Set<Class<?>> addedHandlers = new HashSet<Class<?>>();
147  Class<?> test = eventHandler.getClass();
148  log.info("adding Event-Handler: " + test.getName());
149  while (test != Object.class) {
150  for (Class<?> theInterface: test.getInterfaces()) {
151  if (!addedHandlers.contains(theInterface)) {
152  log.info(" " + theInterface.getName());
153  addHandlerInterfaces(theInterface);
154  addedHandlers.add(theInterface);
155  }
156  }
157  test = test.getSuperclass();
158  }
159  log.info("");
160  }
161 
162  static private class HandlerInfo {
163  protected final Method method;
164  protected HandlerInfo(final Method method) {
165  this.method = method;
166  }
167  }
168 
169  public void deactivate() {
170  this.isActive = false;
171  }
172 
173  @Override
174  public void processEvent(final Event event) {
175 
176  if (!this.isActive) return;
177 
178  this.counter++;
179  if (this.counter == this.nextCounterMsg) {
180  this.nextCounterMsg *= 4;
181  log.info(" event # " + this.counter);
182  }
183  computeEvent(event);
184  }
185 
186  @Override
187  public void addHandler(final EventHandler handler) {
188  throw new UnsupportedOperationException("This implementation supports only a single EventHandler which "
189  + "has to be provided upon creation. Aborting!");
190  }
191 
192  @Override
193  public void removeHandler(final EventHandler handler) {
194  throw new UnsupportedOperationException("This implementation supports only a single EventHandler which "
195  + "has to be provided upon creation. Aborting!");
196  }
197 
198  @Override
199  public void resetHandlers(final int iteration) {
200  log.info("resetting Event-Handler");
201  this.counter = 0;
202  this.nextCounterMsg = 1;
203  this.eventHandler.reset(iteration);
204  }
205 
206  @Override
207  public void initProcessing() {
208  // nothing to do in this implementation
209  }
210 
211  @Override
212  public void afterSimStep(double time) {
213  // Maybe we can move stuff from the ParallelEventsManager here?
214  }
215 
216  @Override
217  public void finishProcessing() {
218  // nothing to do in this implementation
219  }
220 
222  return this.eventHandler;
223  }
224 
225  public String getEventHandlerClassName() {
226  return this.eventHandler.getClass().toString();
227  }
228 
229  private void computeEvent(final Event event) {
230  if (callHandlerFast(event)) return;
231  try {
232  Method method = this.getHandlersForClass(event.getClass());
233  if (method != null) method.invoke(this.eventHandler, event);
234  } catch(InvocationTargetException e) {
235  throw new RuntimeException("problem invoking EventHandler " + this.eventHandler.getClass().getCanonicalName() + " for event-class " + event.getClass().getCanonicalName(), e.getTargetException());
236  }
237  catch (IllegalArgumentException | IllegalAccessException e) {
238  throw new RuntimeException("problem invoking EventHandler " + this.eventHandler.getClass().getCanonicalName() + " for event-class " + event.getClass().getCanonicalName(), e);
239  }
240  }
241 
242  private Method getHandlersForClass(final Class<?> eventClass) {
243  Class<?> klass = eventClass;
244 
245  HandlerInfo info = this.methodToHandle.get(eventClass);
246  if (info != null) return info.method;
247 
248  Method method = null;
249 
250  // first search in class-hierarchy
251  while (klass != Object.class) {
252  info = this.methodToHandle.get(klass);
253  if (info != null) {
254  method = info.method;
255  break;
256  }
257  klass = klass.getSuperclass();
258  }
259 
260  // second search in implemented interfaces if no method was found yet
261  if (method == null) {
262  for (Class<?> intfc : ClassUtils.getAllInterfaces(eventClass )) {
263  info = this.methodToHandle.get(intfc);
264  if (info != null) {
265  method = info.method;
266  break;
267  }
268  }
269  }
270 
271  info = new HandlerInfo(method);
272  this.methodToHandle.put(eventClass, new HandlerInfo(info.method));
273 
274  return method;
275  }
276 
277  private void addHandlerInterfaces(final Class<?> handlerClass) {
278  Method[] classmethods = handlerClass.getMethods();
279  for (Method method : classmethods) {
280  if (method.getName().equals("handleEvent")) {
281  Class<?>[] params = method.getParameterTypes();
282  if (params.length == 1) {
283  Class<?> eventClass = params[0];
284  log.info(" > " + eventClass.getName());
285  if (!this.methodToHandle.containsKey(eventClass)) {
286  HandlerInfo info = new HandlerInfo(method);
287  this.methodToHandle.put(eventClass, info);
288  }
289  }
290  }
291  }
292  }
293 
294  // this method is purely for performance reasons and need not be implemented
295  private boolean callHandlerFast(final Event ev) {
296  boolean ret = false;
297  Class<?> klass = ev.getClass();
298  if (this.isBasicEventHandler) {
299  ((BasicEventHandler) this.eventHandler).handleEvent(ev);
300  ret = true;
301  }
302  if (this.isLeaveLinkHandler && klass == LinkLeaveEvent.class) {
303  ((LinkLeaveEventHandler) this.eventHandler).handleEvent((LinkLeaveEvent)ev);
304  return true;
305  }
306  if (this.isLinkEnterHandler && klass == LinkEnterEvent.class) {
307  ((LinkEnterEventHandler) this.eventHandler).handleEvent((LinkEnterEvent)ev);
308  return true;
309  }
310  if (this.isWait2LinkHandler && klass == VehicleEntersTrafficEvent.class) {
311  ((VehicleEntersTrafficEventHandler) this.eventHandler).handleEvent((VehicleEntersTrafficEvent)ev);
312  return true;
313  }
314  if (this.isPersonArrivalHandler && klass == PersonArrivalEvent.class) {
315  ((PersonArrivalEventHandler) this.eventHandler).handleEvent((PersonArrivalEvent)ev);
316  return true;
317  }
318  if (this.isPersonDepatureHandler && klass == PersonDepartureEvent.class) {
319  ((PersonDepartureEventHandler) this.eventHandler).handleEvent((PersonDepartureEvent)ev);
320  return true;
321  }
322  if (this.isActivityEndHandler && klass == ActivityEndEvent.class) {
323  ((ActivityEndEventHandler) this.eventHandler).handleEvent((ActivityEndEvent)ev);
324  return true;
325  }
326  if (this.isActivityStartHandler && klass == ActivityStartEvent.class) {
327  ((ActivityStartEventHandler) this.eventHandler).handleEvent((ActivityStartEvent)ev);
328  return true;
329  }
330  if (this.isTeleportationArrivalHandler && klass == TeleportationArrivalEvent.class) {
331  ((TeleportationArrivalEventHandler) this.eventHandler).handleEvent((TeleportationArrivalEvent)ev);
332  return true;
333  }
334  if (this.isTransitDriverStartsHandler && klass == TransitDriverStartsEvent.class) {
335  ((TransitDriverStartsEventHandler) this.eventHandler).handleEvent((TransitDriverStartsEvent) ev);
336  return true;
337  }
338  if (this.isPersonStuckHandler && klass == PersonStuckEvent.class) {
339  ((PersonStuckEventHandler) this.eventHandler).handleEvent((PersonStuckEvent)ev);
340  return true;
341  }
342  if (this.isPersonMoneyHandler && klass == PersonMoneyEvent.class) {
343  ((PersonMoneyEventHandler) this.eventHandler).handleEvent((PersonMoneyEvent)ev);
344  return true;
345  }
346  if (this.isPersonScoreHandler && klass == PersonScoreEvent.class) {
347  ((PersonScoreEventHandler) this.eventHandler).handleEvent((PersonScoreEvent)ev);
348  return true;
349  }
350  if (this.isAgentWaitingForPtHandler && klass == AgentWaitingForPtEvent.class) {
351  ((AgentWaitingForPtEventHandler) this.eventHandler).handleEvent((AgentWaitingForPtEvent)ev);
352  return true;
353  }
354  if (this.isPersonEntersVehicleHandler && klass == PersonEntersVehicleEvent.class) {
355  ((PersonEntersVehicleEventHandler) this.eventHandler).handleEvent((PersonEntersVehicleEvent)ev);
356  return true;
357  }
358  if (this.isPersonLeavesVehicleHandler && klass == PersonLeavesVehicleEvent.class) {
359  ((PersonLeavesVehicleEventHandler) this.eventHandler).handleEvent((PersonLeavesVehicleEvent)ev);
360  return true;
361  }
362  if (this.isVehicleDepartsAtFacilityHandler && klass == VehicleDepartsAtFacilityEvent.class) {
363  ((VehicleDepartsAtFacilityEventHandler) this.eventHandler).handleEvent((VehicleDepartsAtFacilityEvent) ev);
364  return true;
365  }
366  if (this.isVehicleArrivesAtFacilityHandler && klass == VehicleArrivesAtFacilityEvent.class) {
367  ((VehicleArrivesAtFacilityEventHandler) this.eventHandler).handleEvent((VehicleArrivesAtFacilityEvent) ev);
368  return true;
369  }
370  if (this.isVehicleLeavesTrafficHandler && klass == VehicleLeavesTrafficEvent.class) {
371  ((VehicleLeavesTrafficEventHandler) this.eventHandler).handleEvent((VehicleLeavesTrafficEvent) ev);
372  return true;
373  }
374  if (this.isVehicleAbortsHandler && klass == VehicleAbortsEvent.class) {
375  ((VehicleAbortsEventHandler) this.eventHandler).handleEvent((VehicleAbortsEvent) ev);
376  return true;
377  }
378  return ret;
379  }
380 }
static Set< Class<?> > getAllInterfaces(final Class<?> klass)
Definition: ClassUtils.java:59