Google guice Matchers の OR

Google guiceAOP インターセプターバインド定義で使用される Matchers には、
OR で一致を判定するものを提供していません。
com.google.inject.matcher.Matchers の static メソッドの一覧

any() 全て無条件に一致
only(Object) 指定するObjectに限定
equals(object)で判定
identicalTo(Object) 指定するObjectと一致、onlyと異なるのは、
== で判定している。
annotatedWith(Annotation) 指定するアノテーションに一致
annotatedWith(Class<annotationType>) 指定するアノテーションクラスに一致
inPackage(Package) 指定するpackage内のクラスであることに一致
ネストは効かない
subclassesOf(Class) 指定するクラスのサブクラスであることに一致
ネストでも適用される
returns(Matcher) 指定するMatcherで検査と一致する戻り値を持つメソッドであることに一致
not(Matcher) 指定するMatcherで検査して一致しない(否定)こと。

StackOverFlow では、こんな回答してるものがありますが、
https://stackoverflow.com/questions/53411162/how-to-match-on-type-or-method-annotation-only-once
そんな、第3引数が同じの bindInterceptor() をいくつも書くのを避けたいです。

guice でバインド定義を約束するインターフェース com.google.inject.Binder を覗いてみましょう。

void bindInterceptor(
    Matcher<? super Class<?>> classMatcher,
    Matcher<? super Method> methodMatcher,
    MethodInterceptor... interceptors
);

です。
この第1引数クラスにマッチするもの、第2引数メソッドにマッチするものを
指定する Matchers に、OR がなくて困っているので、
Matchers 同様に
クラス条件での OR メソッド、
メソッド条件での OR メソッド
を static で用意します。
名前は、XMatchers と、なんともセンスないかもしれませんが。。。

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Collectors;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.matcher.Matcher;
/**
 * XMatchers
 */
public class XMatchers{
   private XMatchers(){}

   public static Matcher<Object> or(Object...m) {
       return new OR(m);
   }

   private static class OR extends AbstractMatcher<Object> implements Serializable {
      private static final long serialVersionUID = 1L;
      Object[] ms;

      public OR(Object[] m){
         ms = m;
      }
      @SuppressWarnings({ "unchecked", "rawtypes" })
      @Override
      public boolean matches(Object t){
         boolean rtn = false;
         for(int n=0;n < ms.length; n++){
            rtn = rtn | ((Matcher)ms[n]).matches(t);
         }
         return rtn;
      }
      @Override
      public String toString(){
         StringBuilder sb = new StringBuilder("or(");
         sb.append(Arrays.stream(ms).map(e->e.toString()).collect(Collectors.joining(",")));
         sb.append(")");
         return sb.toString();
      }
   }
}

使い方のサンプル

binder().bindInterceptor(
   XMatchers.or(
      Matchers.inPackage(User.class.getPackage()),
      Matchers.inPackage(Item.class.getPackage())
   ),
   XMatchers.or(
      Matchers.annotatedWith(Names.named("A")).
      Matchers.annotatedWith(Names.named("B"))
   ),
   new MyInterceptor1(),
   new MyInterceptor2()
);