package calfpath;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Util {

    private static final Map<?, String> EMPTY_PARAMS = Collections.emptyMap();

    public static Map<?, String> matchURI(String uri, List<?> patternTokens) {
        // if length==1, then token must be string
        if (patternTokens.size() == 1) {
            if (uri.equals(patternTokens.get(0))) {
                return EMPTY_PARAMS;
            } else {
                return null;
            }
        }
        final int n = uri.length();
        final Map<Object, String> params = new HashMap<Object, String>();
        int i = 0;
        OUTER:
        for (final Object token: patternTokens) {
            if (i > n) {
                return null;
            }
            if (token instanceof String) {
                final String tokenStr = (String) token;
                if (uri.startsWith(tokenStr, i)) {
                    i += tokenStr.length();
                } else {
                    return null;
                }
            } else {
                final StringBuilder sb = new StringBuilder();
                for (int j = i; j < n; j++) {
                    final char ch = uri.charAt(j);
                    if (ch == '/') {
                        params.put(token, sb.toString());
                        i = j;
                        continue OUTER;
                    } else {
                        sb.append(ch);
                    }
                }
                params.put(token, sb.toString());
                i = Integer.MAX_VALUE;
            }
        }
        return params;
    }

}

@@ -135,16 +135,51 @@
 Util %7B%0A%0A
+    @SuppressWarnings(%22unchecked%22)%0A
     priv
@@ -241,17 +241,45 @@
 ons.
-emptyMap(
+unmodifiableMap(Collections.EMPTY_MAP
 );%0A%0A
@@ -825,16 +825,17 @@
  if (i %3E
+=
  n) %7B%0A  
@@ -1072,33 +1072,112 @@
 h();
-%0A                %7D else %7B
+  // now i==n if last string token%0A                %7D else %7B  // 'string token mismatch' implies no match
 %0A   
@@ -1352,16 +1352,52 @@
 ; j++) %7B
+  // capture param chars in one pass
 %0A       
@@ -1476,16 +1476,71 @@
 = '/') %7B
+  // separator implies we got param value, now continue
 %0A       
@@ -1789,80 +1789,237 @@
     
-params.put(token, sb.toString());%0A                i = Integer.MAX_VALUE;
+// 'separator not found' implies URI has ended%0A                params.put(token, sb.toString());%0A                i = n;%0A            %7D%0A        %7D%0A        if (i %3C n) %7B  // 'tokens finished but URI still in progress' implies no match
 %0A   
@@ -2019,33 +2019,44 @@
 tch%0A            
-%7D
+return null;
 %0A        %7D%0A     

add correctness and code comments to Java URI-matcher