class AnnotationProcessor {
    private static AgentLogger LOGGER = AgentLogger.getLogger(AnnotationProcessor.class);

    protected PluginManager pluginManager;

    public AnnotationProcessor(PluginManager pluginManager) {
        this.pluginManager = pluginManager;
        init(pluginManager);
    }

    protected Map<Class<? extends Annotation>, PluginHandler> handlers =
            new HashMap<Class<? extends Annotation>, PluginHandler>();

    public void init(PluginManager pluginManager) {
        addAnnotationHandler(Init.class, new InitHandler(pluginManager));
        addAnnotationHandler(OnClassLoadEvent.class, new OnClassLoadedHandler(pluginManager));
        addAnnotationHandler(OnClassFileEvent.class, new WatchHandler(pluginManager));
        addAnnotationHandler(OnResourceFileEvent.class, new WatchHandler(pluginManager));
    }

    public void addAnnotationHandler(Class<? extends Annotation> annotation, PluginHandler handler) {
        handlers.put(annotation, handler);
    }

    /**
     * Process annotations on the plugin class - only static methods, methods to hook plugin initialization.
     *
     * @param processClass class to process annotation
     * @param pluginClass main plugin class (annotated with @Plugin)
     * @return true if success
     */
    public boolean processAnnotations(Class processClass, Class pluginClass) {

        try {
            for (Field field : processClass.getDeclaredFields()) {
                if (Modifier.isStatic(field.getModifiers()))
                    if (!processFieldAnnotations(null, field, pluginClass))
                        return false;

            }

            for (Method method : processClass.getDeclaredMethods()) {
                if (Modifier.isStatic(method.getModifiers()))
                    if (!processMethodAnnotations(null, method, pluginClass))
                        return false;
            }

            // process annotations on all supporting classes in addition to the plugin itself
            for (Annotation annotation : processClass.getDeclaredAnnotations()) {
                if (annotation instanceof Plugin) {
                    for (Class supportClass : ((Plugin) annotation).supportClass()) {
                        processAnnotations(supportClass, pluginClass);
                    }
                }
            }

            return true;
        } catch (Throwable e) {
            LOGGER.error("Unable to process plugin annotations '{}'", e, pluginClass);
            return false;
        }
    }

    /**
     * Process annotations on a plugin - non static fields and methods.
     *
     * @param plugin plugin object
     * @return true if success
     */
    public boolean processAnnotations(Object plugin) {
        LOGGER.debug("Processing annotations for plugin '" + plugin + "'.");

        Class pluginClass = plugin.getClass();

        for (Field field : pluginClass.getDeclaredFields()) {
            if (!Modifier.isStatic(field.getModifiers()))
                if (!processFieldAnnotations(plugin, field, pluginClass))
                    return false;

        }

        for (Method method : pluginClass.getDeclaredMethods()) {
            if (!Modifier.isStatic(method.getModifiers()))
                if (!processMethodAnnotations(plugin, method, pluginClass))
                    return false;

        }

        return true;
    }

    @SuppressWarnings("unchecked")
    private boolean processFieldAnnotations(Object plugin, Field field, Class pluginClass) {<FILL_FUNCTION_BODY>}

    @SuppressWarnings("unchecked")
    private boolean processMethodAnnotations(Object plugin, Method method, Class pluginClass) {
        // for all methods and all handlers
        for (Annotation annotation : method.getDeclaredAnnotations()) {
            for (Class<? extends Annotation> handlerAnnotation : handlers.keySet()) {
                if (annotation.annotationType().equals(handlerAnnotation)) {
                    // initialize
                    PluginAnnotation<?> pluginAnnotation = new PluginAnnotation<>(pluginClass, plugin, annotation, method);
                    if (!handlers.get(handlerAnnotation).initMethod(pluginAnnotation)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
}

        // for all fields and all handlers
        for (Annotation annotation : field.getDeclaredAnnotations()) {
            for (Class<? extends Annotation> handlerAnnotation : handlers.keySet()) {
                if (annotation.annotationType().equals(handlerAnnotation)) {
                    // initialize
                    PluginAnnotation<?> pluginAnnotation = new PluginAnnotation<>(pluginClass, plugin, annotation, field);
                    if (!handlers.get(handlerAnnotation).initField(pluginAnnotation)) {
                        return false;
                    }
                }
            }
        }
        return true;
    
<no_super_class>