fork download
  1. import java.lang.annotation.ElementType;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. import java.lang.annotation.Target;
  5. import java.lang.reflect.Method;
  6. import java.lang.reflect.Modifier;
  7. import java.util.HashMap;
  8. import java.util.Map;
  9.  
  10. @Retention(RetentionPolicy.RUNTIME)
  11. @Target(ElementType.METHOD)
  12. @interface PatternHandler {
  13. String value();
  14. }
  15.  
  16. interface TownyChatReplacerCallable {
  17. String call(String match, String event);
  18. }
  19.  
  20. class AnnotationRegistry {
  21. private static final Map<String, TownyChatReplacerCallable> MAP = new HashMap<String, TownyChatReplacerCallable>();
  22.  
  23. public static void register(String pattern, TownyChatReplacerCallable handler) {
  24. System.out.println("Registering pattern:" + pattern + " handler:" + handler);
  25. MAP.put(pattern, handler);
  26. }
  27.  
  28. public static void handle(String pattern, String event) {
  29. TownyChatReplacerCallable handler = MAP.get(pattern);
  30. if (handler != null) {
  31. String result = handler.call(pattern, event);
  32. System.out.println("Handler returned:" + result);
  33. } else {
  34. System.out.println("No Handler for:" + pattern);
  35. }
  36. }
  37.  
  38. public static void register(Class<?> clazz) {
  39. Method[] methods = clazz.getDeclaredMethods();
  40. method_loop: for (Method method : methods) {
  41. PatternHandler annotation = method.getAnnotation(PatternHandler.class);
  42. if (annotation != null) {
  43. if (!Modifier.isStatic(method.getModifiers())) {
  44. System.out.println("Method must be static: " + method.getName());
  45. continue;
  46. }
  47. if (!(method.getReturnType() == String.class)) {
  48. System.out.println("Method must return String: " + method.getName()
  49. + " returns:" + method.getReturnType().getName());
  50. continue;
  51. }
  52. Class<?>[] parameterTypes = method.getParameterTypes();
  53. if (parameterTypes.length != 2) {
  54. System.out.println("Method must take 2 parameters: String, String");
  55. continue;
  56. }
  57. // this would need to be different for different types
  58. for (Class<?> paramType : parameterTypes) {
  59. if (!paramType.isAssignableFrom(String.class)) {
  60. System.out.println("Method parameter does not take String: "
  61. + method.getName() + " param:" + paramType.getName());
  62. continue method_loop;
  63. }
  64. }
  65. // could check even more... not public etc
  66. register(annotation.value(), new MethodAdapter(method));
  67. }
  68. }
  69. }
  70. }
  71.  
  72. class Callables {
  73.  
  74. @PatternHandler("foo")
  75. public static String fooMethod(String match, String event) {
  76. return "This is foo handler called with " + match + "," + event;
  77. }
  78.  
  79. @PatternHandler("bar")
  80. public static String barMethod(String match, String event) {
  81. return "This is bar handler called with " + match + "," + event;
  82. }
  83.  
  84. @PatternHandler("bad")
  85. public String nonStaticMethod(String match, String event) {
  86. return "broken";
  87. }
  88.  
  89. @PatternHandler("bad")
  90. public static Integer wrongReturnTypeMethod(String match, String event) {
  91. return 42;
  92. }
  93.  
  94. @PatternHandler("bad")
  95. public static String wrongParameterTypeMethod(String match, Integer event) {
  96. return "broken";
  97. }
  98.  
  99. @PatternHandler("bad")
  100. public static String wrongParameterCountMethod(String match, String event, String foo) {
  101. return "broken";
  102. }
  103.  
  104. }
  105.  
  106. class MethodAdapter implements TownyChatReplacerCallable {
  107. private final Method method;
  108.  
  109. public MethodAdapter(Method m) {
  110. method = m;
  111. }
  112.  
  113. @Override
  114. public String call(String match, String event) {
  115. try {
  116. return (String) method.invoke(null, match, event);
  117. } catch (Exception e) {
  118. e.printStackTrace();
  119. return "OMGZ";
  120. }
  121. }
  122. }
  123.  
  124. public class Main {
  125. public static void main(String[] args) {
  126. AnnotationRegistry.register(Callables.class);
  127. System.out.println("\n-- Done with registration --\n");
  128.  
  129. AnnotationRegistry.handle("foo", "event1");
  130. AnnotationRegistry.handle("bar", "event2");
  131. AnnotationRegistry.handle("zoom", "event3");
  132. }
  133. }
  134.  
Success #stdin #stdout 0.09s 380352KB
stdin
Standard input is empty
stdout
Registering pattern:foo handler:MethodAdapter@1fccfe3
Registering pattern:bar handler:MethodAdapter@b481ba
Method must be static: nonStaticMethod
Method must return String: wrongReturnTypeMethod returns:java.lang.Integer
Method parameter does not take String: wrongParameterTypeMethod param:java.lang.Integer
Method must take 2 parameters: String, String

-- Done with registration --

Handler returned:This is foo handler called with foo,event1
Handler returned:This is bar handler called with bar,event2
No Handler for:zoom