2020
2121import java .util .Collection ;
2222import java .util .Map ;
23+ import java .util .Set ;
2324import java .util .StringJoiner ;
2425import java .util .concurrent .ConcurrentHashMap ;
25- import java .util .concurrent .CopyOnWriteArrayList ;
26+ import java .util .concurrent .CopyOnWriteArraySet ;
27+
28+ import static java .util .Comparator .comparingInt ;
2629
2730/**
2831 * A directory of restrictions that can be looked up by their type.
@@ -33,7 +36,7 @@ public class RestrictionLookup<M> {
3336 /**
3437 * The restrictions.
3538 */
36- private final Collection <Restriction <? super M >> restrictions = new CopyOnWriteArrayList <>();
39+ private final Set <Restriction <? super M >> restrictions = new CopyOnWriteArraySet <>();
3740
3841 /**
3942 * The restrictions by class. As the actual restriction instances are proxied by CDI, this map cannot be
@@ -48,6 +51,7 @@ public class RestrictionLookup<M> {
4851 */
4952 public void addAllRestrictions (Collection <Restriction <? super M >> restrictions ) {
5053 this .restrictions .addAll (restrictions );
54+ restrictionByClass .clear ();
5155 }
5256
5357 /**
@@ -62,10 +66,20 @@ public Restriction<? super M> getRestriction(Class<?> restrictionClass) {
6266 key -> restrictions .stream ()
6367 // we cannot use a map as the classes are proxied by CDI
6468 .filter (key ::isInstance )
65- .findAny ( )
69+ .min ( comparingInt ( restriction -> getInheritanceDistance ( restriction , key )) )
6670 .orElse (null ));
6771 }
6872
73+ private static int getInheritanceDistance (Restriction <?> restriction , Class <?> restrictionClass ) {
74+ int distance = 0 ;
75+ for (Class <?> clazz = restriction .getClass ();
76+ !clazz .equals (restrictionClass ) && restrictionClass .isAssignableFrom (clazz );
77+ clazz = clazz .getSuperclass ()) {
78+ distance ++;
79+ }
80+ return distance ;
81+ }
82+
6983 @ Override
7084 public String toString () {
7185 return new StringJoiner (", " , RestrictionLookup .class .getSimpleName () + "[" , "]" )
0 commit comments