public boolean handleEvent(Object emitter, Object type, Object data) {
        final Object object = provider.get();
        if (object == null) {
            return true;
        }

        final int paramCount = method.getParameterTypes().length;

        final boolean wasAccessible = method.isAccessible();
        method.setAccessible(true);
        try {
            // This duplication is an optimization.
            // Instead of creating list and then making subList(size - parameterCount, size)
            // this will make simple and quick method invocation.

            final Object result;
            switch (paramCount) {
                case 0:
                    result = method.invoke(object);
                    break;

                case 1:
                    result = method.invoke(object, data);
                    break;

                case 2:
                    result = method.invoke(object, type, data);
                    break;

                case 3:
                    result = method.invoke(object, emitter, type, data);
                    break;

                default:
                    throw new IllegalArgumentException("listener method has too many arguments: " + method);
            }
            if (result instanceof Boolean) {
                return (Boolean) result;
            }
            return true;

        } catch (IllegalAccessException e) {
            throw new RuntimeException("unable to access listener method: " + method, e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("unable to invoke listener method: " + method, e);
        } finally {
            method.setAccessible(wasAccessible);
        }
    }