class EventStubGenerator {

    public List<GeneratedClass> getEvents() {
        List<GeneratedClass> events = new ArrayList<>();
        for (JavaMethod method : listenerMethods) {
            List<JavaVar> arguments = method.getArguments();

            ClassBuilder cb = new ClassBuilder(myEventWrapperName(method), stubsPackage);
            addGeneratedAnnotation(cb);
            cb.implement(eventInterface);
            cb.implement(JavaType.of(Serializable.class));
            cb.fieldsAndConstructorParameters(arguments);

            String eventToString = cb.imports.getSimpleName(JavaType.of(EventToString.class));
            String listenerName = cb.imports.getSimpleName(listenerInterface);

            for (JavaVar argument : arguments) {
                cb.addMethod("" +
                        "    public " + cb.imports.getSimpleName(argument.getType()) + " " + getterName(argument.getName()) + "() {\n" +
                        "        return " + argument.getName() + ";\n" +
                        "    }\n");
            }

            cb.addMethod("" +
                    "    @Override\n" +
                    "    public void fireOn(" + listenerName + " target) {\n" +
                    "        target." + method.getName() + "(" + JavaVar.toActualArguments(arguments) + ");\n" +
                    "    }\n");

            cb.addMethod("" +
                    "    @Override\n" +
                    "    public String toString() {\n" +
                    "        return " + eventToString + ".format(\"" + listenerName + "\", \"" + method.getName() + "\"" + JavaVar.toActualVarargs(arguments) + ");\n" +
                    "    }\n");

            events.add(cb.build());
        }

        Collections.sort(events, (o1, o2) -> o1.name.compareTo(o2.name));
        return events;
    }

    public  EventStubGenerator(TypeElement listenerType, String targetPackage);

}