MATSIM
EventsManagerImpl.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * EventsManagerImpl.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007, 2009 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.ArrayList;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.concurrent.ConcurrentHashMap;
31 
32 import org.apache.logging.log4j.LogManager;
33 import org.apache.logging.log4j.Logger;
34 import org.matsim.api.core.v01.events.*;
45 
61 public final class EventsManagerImpl implements EventsManager {
62 
63  private static final Logger log = LogManager.getLogger(EventsManagerImpl.class);
64 
65  static private class HandlerData {
66 
67  protected Class<? extends Event> eventClass;
68  protected ArrayList<EventHandler> handlerList = new ArrayList<EventHandler>(5);
69  protected Method method;
70 
71  protected HandlerData(final Class<? extends Event> eventClass, final Method method) {
72  this.eventClass = eventClass;
73  this.method = method;
74  }
75 
76  protected void removeHandler(final EventHandler handler) {
77  this.handlerList.remove(handler);
78  }
79  }
80 
81  static private class HandlerInfo {
82  protected final Class<? extends Event> eventClass;
83  protected final EventHandler eventHandler;
84  protected final Method method;
85 
86  protected HandlerInfo(final Class<? extends Event> eventClass, final EventHandler eventHandler,
87  final Method method) {
88  this.eventClass = eventClass;
89  this.eventHandler = eventHandler;
90  this.method = method;
91  }
92  }
93 
94  private final List<HandlerData> handlerData = new ArrayList<>();
95 
96  private final Map<Class<? extends Event>, HandlerInfo[]> cacheHandlers = new ConcurrentHashMap<>(15);
97 
98  private long counter = 0;
99  private long nextCounterMsg = 1;
100 
101  private HandlerData findHandler(final Class<? extends Event> evklass) {
102  for (HandlerData handler : this.handlerData) {
103  if (handler.eventClass == evklass) {
104  return handler;
105  }
106  }
107  return null;
108  }
109 
110  @Override
111  public void processEvent(final Event event) {
112  this.counter++;
113  if (this.counter == this.nextCounterMsg) {
114  this.nextCounterMsg *= 4;
115  log.info(" event # " + this.counter);
116  }
117  for (HandlerInfo info : getHandlersForClass( event.getClass() )) {
118  synchronized(info.eventHandler) {
119  if (callHandlerFast(info.eventClass, event, info.eventHandler )) {
120  continue;
121  }
122  try {
123  info.method.invoke(info.eventHandler, event );
124  } catch (IllegalArgumentException | IllegalAccessException e) {
125  throw new RuntimeException("problem invoking EventHandler " + info.eventHandler.getClass().getCanonicalName() + " for event-class " + info.eventClass.getCanonicalName(), e);
126  } catch (InvocationTargetException e) {
127  throw new RuntimeException("problem invoking EventHandler " + info.eventHandler.getClass().getCanonicalName() + " for event-class " + info.eventClass.getCanonicalName(), e.getCause());
128  }
129  }
130  }
131  }
132 
133  @Override
134  public void addHandler (final EventHandler handler) {
135  Set<Class<?>> addedHandlers = new HashSet<>();
136  Class<?> test = handler.getClass();
137  log.debug("adding Event-Handler: " + test.getName());
138  do {
139  for (Class<?> theInterface : test.getInterfaces()) {
140  if (EventHandler.class.isAssignableFrom(theInterface)) {
141  Class<? extends EventHandler> eventHandlerInterface = (Class<? extends EventHandler>)theInterface;
142  if (!addedHandlers.contains(theInterface)) {
143  log.debug(" " + theInterface.getName());
144  addHandlerInterfaces(handler, eventHandlerInterface);
145  addedHandlers.add(theInterface);
146  }
147  }
148  }
149  test = test.getSuperclass();
150  } while ((EventHandler.class.isAssignableFrom(test)));
151 
152  this.cacheHandlers.clear();
153  log.debug("");
154  }
155 
156  @Override
157  public void removeHandler(final EventHandler handler) {
158  log.info("removing Event-Handler: " + handler.getClass().getName());
159  for (HandlerData handlerList : this.handlerData) {
160  handlerList.removeHandler(handler);
161  }
162  this.cacheHandlers.clear();
163  }
164 
165  @Override
166  public void resetHandlers(final int iteration) {
167  log.info("resetting Event-Handlers");
168  this.counter = 0;
169  this.nextCounterMsg = 1;
170  Set<EventHandler> resetHandlers = new HashSet<EventHandler>();
171  for (HandlerData handlerdata : this.handlerData) {
172  for (EventHandler handler : handlerdata.handlerList) {
173  if (!resetHandlers.contains(handler)) {
174  log.info(" " + handler.getClass().getName());
175  handler.reset(iteration);
176  resetHandlers.add(handler);
177  }
178  }
179  }
180  }
181 
182  @Override
183  public void initProcessing() {
184  // nothing to do in this implementation
185  }
186 
187  @Override
188  public void afterSimStep(double time) {
189  // nothing to do in this implementation
190  }
191 
192  @Override
193  public void finishProcessing() {
194  // nothing to do in this implementation
195  }
196 
197  private void addHandlerInterfaces(final EventHandler handler, final Class<? extends EventHandler> handlerClass) {
198  Method[] classmethods = handlerClass.getMethods();
199  for (Method method : classmethods) {
200  if (method.getName().equals("handleEvent")) {
201  Class<?>[] params = method.getParameterTypes();
202  if (params.length == 1) {
203  Class<? extends Event> eventClass = params[0].asSubclass(Event.class);
204  log.info(" > " + eventClass.getName());
205  HandlerData dat = findHandler(eventClass);
206  if (dat == null) {
207  dat = new HandlerData(eventClass, method);
208  this.handlerData.add(dat);
209  }
210  dat.handlerList.add(handler);
211  }
212  }
213  }
214  }
215 
216  private HandlerInfo[] getHandlersForClass(final Class<? extends Event> eventClass) {
217  HandlerInfo[] cache = this.cacheHandlers.get(eventClass);
218  if (cache != null) {
219  return cache;
220  }
221 
222  ArrayList<HandlerInfo> info = new ArrayList<>();
223  // search in class hierarchy
224  Class<?> klass = eventClass;
225  do {
226  Class<? extends Event> eventKlass = (Class<? extends Event>)klass;
227  HandlerData dat = findHandler(eventKlass);
228  if (dat != null) {
229  for (EventHandler handler : dat.handlerList) {
230  info.add(new HandlerInfo(eventKlass, handler, dat.method));
231  }
232  }
233  klass = klass.getSuperclass();
234  } while (Event.class.isAssignableFrom(klass));
235 
236  cache = info.toArray(new HandlerInfo[0]);
237  this.cacheHandlers.put(eventClass, cache);
238  return cache;
239  }
240 
241  // this method is purely for performance reasons and need not be implemented
242  private static boolean callHandlerFast(final Class<? extends Event> klass, final Event ev,
243  final EventHandler handler) {
244  if (klass == LinkLeaveEvent.class) {
245  ((LinkLeaveEventHandler)handler).handleEvent((LinkLeaveEvent)ev);
246  return true;
247  } else if (klass == LinkEnterEvent.class) {
248  ((LinkEnterEventHandler)handler).handleEvent((LinkEnterEvent)ev);
249  return true;
250  } else if (klass == VehicleEntersTrafficEvent.class) {
251  ((VehicleEntersTrafficEventHandler) handler).handleEvent((VehicleEntersTrafficEvent) ev);
252  return true;
253  } else if (klass == VehicleLeavesTrafficEvent.class) {
254  ((VehicleLeavesTrafficEventHandler) handler).handleEvent((VehicleLeavesTrafficEvent) ev);
255  return true;
256  } else if (klass == PersonArrivalEvent.class) {
257  ((PersonArrivalEventHandler)handler).handleEvent((PersonArrivalEvent)ev);
258  return true;
259  } else if (klass == PersonDepartureEvent.class) {
260  ((PersonDepartureEventHandler)handler).handleEvent((PersonDepartureEvent)ev);
261  return true;
262  } else if (klass == ActivityEndEvent.class) {
263  ((ActivityEndEventHandler)handler).handleEvent((ActivityEndEvent)ev);
264  return true;
265  } else if (klass == ActivityStartEvent.class) {
266  ((ActivityStartEventHandler)handler).handleEvent((ActivityStartEvent)ev);
267  return true;
268  } else if (klass == TransitDriverStartsEvent.class) {
269  ((TransitDriverStartsEventHandler) handler).handleEvent((TransitDriverStartsEvent) ev);
270  return true;
271  } else if (klass == PersonStuckEvent.class) {
272  ((PersonStuckEventHandler)handler).handleEvent((PersonStuckEvent)ev);
273  return true;
274  } else if (klass == PersonMoneyEvent.class) {
275  ((PersonMoneyEventHandler)handler).handleEvent((PersonMoneyEvent)ev);
276  return true;
277  } else if (klass == AgentWaitingForPtEvent.class) {
278  ((AgentWaitingForPtEventHandler)handler).handleEvent((AgentWaitingForPtEvent)ev);
279  return true;
280  } else if (klass == PersonEntersVehicleEvent.class) {
281  ((PersonEntersVehicleEventHandler)handler).handleEvent((PersonEntersVehicleEvent)ev);
282  return true;
283  } else if (klass == PersonLeavesVehicleEvent.class) {
284  ((PersonLeavesVehicleEventHandler)handler).handleEvent((PersonLeavesVehicleEvent)ev);
285  return true;
286  } else if (klass == VehicleDepartsAtFacilityEvent.class) {
288  return true;
289  } else if (klass == VehicleArrivesAtFacilityEvent.class) {
291  return true;
292  } else if (klass == Event.class) {
293  ((BasicEventHandler)handler).handleEvent(ev);
294  return true;
295  }
296  return false;
297  }
298 
299  public void printEventHandlers() {
300  log.info("currently registered event-handlers:");
301  for (HandlerData handlerType : this.handlerData) {
302  log.info("+ " + handlerType.eventClass.getName());
303  for (EventHandler handler : handlerType.handlerList) {
304  log.info(" - " + handler.getClass().getName());
305  }
306  }
307  }
308 
309 }
void removeHandler(final EventHandler handler)
HandlerInfo(final Class<? extends Event > eventClass, final EventHandler eventHandler, final Method method)
void addHandlerInterfaces(final EventHandler handler, final Class<? extends EventHandler > handlerClass)
final Map< Class<? extends Event >, HandlerInfo[]> cacheHandlers
HandlerData findHandler(final Class<? extends Event > evklass)
static boolean callHandlerFast(final Class<? extends Event > klass, final Event ev, final EventHandler handler)
HandlerInfo [] getHandlersForClass(final Class<? extends Event > eventClass)
void addHandler(final EventHandler handler)
HandlerData(final Class<? extends Event > eventClass, final Method method)