1010import io .jooby .Router ;
1111
1212import java .util .Arrays ;
13- import java .util .Collections ;
1413import java .util .Map ;
1514import java .util .Objects ;
1615import java .util .concurrent .ConcurrentHashMap ;
@@ -31,24 +30,71 @@ class Chi implements RouteTree {
3130
3231 private static final int NODE_SIZE = ntCatchAll + 1 ;
3332
34- static final StaticRoute NO_MATCH = new StaticRoute (Collections .emptyMap ());
35-
3633 static final char ZERO_CHAR = (char ) 0 ;
3734 private MessageEncoder encoder ;
3835
39- static class StaticRoute {
40- private final Map <String , StaticRouterMatch > methods ;
36+ private interface MethodMatcher {
37+ StaticRouterMatch get (String method );
38+
39+ void put (String method , StaticRouterMatch route );
40+
41+ boolean matches (String method );
42+ }
43+
44+ private static class SingleMethodMatcher implements MethodMatcher {
45+ private String method ;
46+ private StaticRouterMatch route ;
47+
48+ @ Override public void put (String method , StaticRouterMatch route ) {
49+ this .method = method ;
50+ this .route = route ;
51+ }
4152
42- public StaticRoute ( Map < String , StaticRouterMatch > methods ) {
43- this .methods = methods ;
53+ @ Override public StaticRouterMatch get ( String method ) {
54+ return this .method . equals ( method ) ? route : null ;
4455 }
4556
46- public StaticRoute ( ) {
47- this ( new ConcurrentHashMap <>( Router . METHODS . size ()) );
57+ @ Override public boolean matches ( String method ) {
58+ return this . method . equals ( method );
4859 }
4960
61+ public void clear () {
62+ this .method = null ;
63+ this .route = null ;
64+ }
65+ }
66+
67+ private static class MultipleMethodMatcher implements MethodMatcher {
68+ private Map <String , StaticRouterMatch > methods = new ConcurrentHashMap <>();
69+
70+ public MultipleMethodMatcher (SingleMethodMatcher matcher ) {
71+ methods .put (matcher .method , matcher .route );
72+ matcher .clear ();
73+ }
74+
75+ @ Override public StaticRouterMatch get (String method ) {
76+ return methods .get (method );
77+ }
78+
79+ @ Override public void put (String method , StaticRouterMatch route ) {
80+ methods .put (method , route );
81+ }
82+
83+ @ Override public boolean matches (String method ) {
84+ return this .methods .containsKey (method );
85+ }
86+ }
87+
88+ static class StaticRoute {
89+ private MethodMatcher matcher ;
90+
5091 public void put (String method , Route route ) {
51- methods .put (method , new StaticRouterMatch (route ));
92+ if (matcher == null ) {
93+ matcher = new SingleMethodMatcher ();
94+ } else if (matcher instanceof SingleMethodMatcher ) {
95+ matcher = new MultipleMethodMatcher ((SingleMethodMatcher ) matcher );
96+ }
97+ matcher .put (method , new StaticRouterMatch (route ));
5298 }
5399 }
54100
@@ -707,24 +753,27 @@ public void destroy() {
707753 }
708754
709755 public boolean exists (String method , String path ) {
710- if (!staticPaths .getOrDefault (path , NO_MATCH ).methods .containsKey (method )) {
711- return root .findRoute (new RouterMatch (), method , path ) != null ;
712- }
713- return true ;
756+ return find (method , path ) != null ;
714757 }
715758
716759 @ Override public Router .Match find (String method , String path ) {
717- StaticRouterMatch match = staticPaths .getOrDefault (path , NO_MATCH ).methods .get (method );
718- if (match == null ) {
719- // use radix tree
720- RouterMatch result = new RouterMatch ();
721- Route route = root .findRoute (result , method , path );
722- if (route == null ) {
723- return result .missing (method , path , encoder );
724- }
725- return result .found (route );
760+ StaticRoute staticRoute = staticPaths .get (path );
761+ if (staticRoute == null ) {
762+ return findInternal (method , path );
763+ } else {
764+ StaticRouterMatch match = staticRoute .matcher .get (method );
765+ return match == null ? findInternal (method , path ) : match ;
766+ }
767+ }
768+
769+ private Router .Match findInternal (String method , String path ) {
770+ // use radix tree
771+ RouterMatch result = new RouterMatch ();
772+ Route route = root .findRoute (result , method , path );
773+ if (route == null ) {
774+ return result .missing (method , path , encoder );
726775 }
727- return match ;
776+ return result . found ( route ) ;
728777 }
729778
730779 public void setEncoder (MessageEncoder encoder ) {
0 commit comments