All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.lessvoid.nifty.NiftyEventAnnotationProcessor Maven / Gradle / Ivy

Go to download

Nifty GUI is a Java Library that supports the building of interactive user interfaces for games or similar applications. It utilizes OpenGL for rendering and it can be easily integrated into many rendering systems. The configuration of the GUI is stored in xml files with little supporting Java code. In short Nifty helps you to layout stuff, display it in a cool way and interact with it :)

There is a newer version: 1.4.3
Show newest version
package de.lessvoid.nifty;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.bushe.swing.event.EventService;
import org.bushe.swing.event.EventServiceLocator;
import org.bushe.swing.event.EventTopicSubscriber;

public class NiftyEventAnnotationProcessor {
  private static final Logger log = Logger.getLogger(NiftyEventAnnotationProcessor.class.getName());

  public static void process(final Object obj) {
    processOrUnprocess(obj, true);
  }

  public static void unprocess(final Object obj) {
    processOrUnprocess(obj, false);
  }

  private static void processOrUnprocess(@Nullable final Object obj, final boolean add) {
    if (obj == null) {
      return;
    }
    Class cl = obj.getClass();
    Method[] methods = cl.getMethods();
    if (log.isLoggable(Level.FINE)) {
      log.fine("Looking for EventBus annotations for class " + cl + ", methods:" + Arrays.toString(methods));
    }
    for (Method method : methods) {
      NiftyEventSubscriber niftyEventSubscriber = method.getAnnotation(NiftyEventSubscriber.class);
      if (niftyEventSubscriber != null) {
        if (log.isLoggable(Level.FINE)) {
          log.fine("Found NiftyEventSubscriber:" + niftyEventSubscriber + " on method:" + method);
        }
        process(niftyEventSubscriber, obj, method, add);
      }
    }
  }

  private static void process(@Nonnull final NiftyEventSubscriber annotation, final Object obj, @Nonnull final Method method, final boolean add) {
    String id = annotation.id();
    String pattern = annotation.pattern();
    ensureNotNull(id, pattern);
    ensureMethodParamCount(method.getParameterTypes());
    EventService eventService = getEventService();
    Class eventClass = method.getParameterTypes()[1];
    if (isSet(id)) {
      idProcess(obj, method, add, id, eventClass, eventService);
    } else {
      patternProcess(obj, method, add, pattern, eventClass, eventService);
    }
  }

  private static boolean isSet(@Nullable final String value) {
    return value != null && value.length() > 0;
  }

  private static void ensureNotNull(final String id, final String pattern) {
    if (!isSet(id) && !isSet(pattern)) {
      throw new IllegalArgumentException("id or pattern must have a value for NiftyEventSubscriber annotation");
    }
  }

  private static void ensureMethodParamCount(@Nullable final Class[] params) {
    if (params == null || params.length != 2 || !String.class.equals(params[0]) || params[1].isPrimitive()) {
       throw new IllegalArgumentException("The subscriptionMethod must have the two parameters, the first one must be a String and the second a non-primitive (Object or derivative).");
    }
  }

  private static void patternProcess(final Object obj, final Method method, final boolean add, @Nonnull final String topicPattern, final Class eventClass, @Nonnull final EventService eventService) {
    Pattern pattern = Pattern.compile(topicPattern);
    Subscriber subscriber = new Subscriber(obj, method, eventClass);
    StringBuilder sb = new StringBuilder(" [{0}] -> [{1}]");
    if (add) {      
      sb.insert(0, "-> subscribe");
      if(!eventService.subscribeStrongly(pattern, subscriber)){
          sb.insert(2, " failed to");
      }
      log.log(Level.FINE, sb.toString(), new Object[]{pattern, subscriber});
    } else {
      sb.insert(0, "<- unsubscribe");
      if(!eventService.unsubscribe(pattern, subscriber)){
          sb.insert(2, " failed to");
      }
      log.log(Level.FINE, sb.toString(), new Object[]{pattern, subscriber});
    }
  }

  private static void idProcess(final Object obj, final Method method, final boolean add, final String id, final Class eventClass, @Nonnull final EventService eventService) {
    Subscriber subscriber = new Subscriber(obj, method, eventClass);
    StringBuilder sb = new StringBuilder(" [{0}] -> [{1}]");
    if (add) {      
      sb.insert(0, "-> subscribe");
      if(!eventService.subscribeStrongly(id, subscriber)){
          sb.insert(2, " failed to");
      }
      log.log(Level.FINE, sb.toString(), new Object[]{id, subscriber});
    } else {
      sb.insert(0, "<- unsubscribe");
      if(!eventService.unsubscribe(id, subscriber)){
          sb.insert(2, " failed to");
      }
      log.log(Level.FINE, sb.toString(), new Object[]{id, subscriber});
    }
  }

  private static EventService getEventService() {
    return EventServiceLocator.getEventService("NiftyEventBus");
  }

  private static class Subscriber implements EventTopicSubscriber {
    private final Object obj;
    private final Method method;
    private final Class eventClass;

    private Subscriber(final Object obj, final Method method, final Class eventClass) {
      this.obj = obj;
      this.method = method;
      this.eventClass = eventClass;
    }

    @Override
    public void onEvent(final String topic, final Object data) {
      if (eventClass.isInstance(data)) {
        try {
          method.invoke(obj, topic, eventClass.cast(data));
        } catch (Throwable e) {
          log.log(Level.WARNING, "failed to invoke method [" + method + "] with Exception [" + e.getMessage() + "][" + e.getCause() + "]", e);
        }
      }
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((eventClass == null) ? 0 : eventClass.hashCode());
      result = prime * result + ((method == null) ? 0 : method.hashCode());
      result = prime * result + ((obj == null) ? 0 : obj.hashCode());
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      Subscriber other = (Subscriber) obj;
      if (eventClass == null) {
        if (other.eventClass != null)
          return false;
      } else if (!eventClass.equals(other.eventClass))
        return false;
      if (method == null) {
        if (other.method != null)
          return false;
      } else if (!method.equals(other.method))
        return false;
      if (this.obj == null) {
        if (other.obj != null)
          return false;
      } else if (!this.obj.equals(other.obj))
        return false;
      return true;
    }
  }
}