/**
   * Creates {@link EventDispatcher}s by unsing the {@link EventMethodCache}. That means, that the
   * class of the passed handler has already be scanned for {@link EventHandler} annotations and all
   * information about building the {@link EventDispatcher}s are present in the {@link
   * EventMethodCache}.
   *
   * @param handler
   */
  private boolean createEventDispatchersFromCache(Object handler) {

    Set<Method> methods = eventMethodChache.getMethods(handler.getClass());

    if (methods == null)
      throw new Error(
          "The class "
              + handler.getClass().getName()
              + " has not been cached until now. However the EventBus tries to create a EventDispatcher from the cache.");

    for (Method m : methods) {
      EventDispatcher disp = new EventDispatcher(handler, m);
      addEventDispatcher(getEventClass(m), disp);
    }

    return !methods.isEmpty();
  }
  /**
   * Registers an {@link EventHandler} for the specified {@link EventType}
   *
   * @param handler
   */
  public void addHandler(Object handler) {

    boolean added = false;

    if (caching) {
      if (!eventMethodChache.isClassCached(handler.getClass()))
        added =
            scanHandlerAndCreateEventDispatcher(
                handler); // This class is not cached, so scan the class
      else
        // This class has been cached (has been already scanned), so build the EventDispatcher from
        // Cache
        added = createEventDispatchersFromCache(handler);
    } else added = scanHandlerAndCreateEventDispatcher(handler);

    if (!added)
      throw new Error("No @EventHandler annotated Method found in " + handler.getClass().getName());
  }
  private boolean scanHandlerAndCreateEventDispatcher(Object handler) {
    boolean added = false;
    for (Method m : handler.getClass().getMethods()) {
      if (!m.isAnnotationPresent(EventHandler.class)) continue;

      Class<?> params[] = m.getParameterTypes();
      if (params.length == 1 && isEventClass(params[0])) {
        // This Method is a Valid EventHandler
        EventDispatcher disp = new EventDispatcher(handler, m);
        addEventDispatcher(getEventClass(m), disp);
        added = true;

        if (caching) eventMethodChache.addMethodToCache(handler.getClass(), m);
      } else
        throw new Error(
            "You have annotated the Method "
                + m.getName()
                + " with @EventHandler, "
                + "but this method did not match the required one Parameter (exactly one) of the type Event");
    }

    return added;
  }