code: public Map<String, String> getMatch(URI uri) {
      // verify that the schemes match
      if (pattern.isAbsolute()) {
        // if there should be a scheme, make sure it matches
        if (!pattern.getScheme().equalsIgnoreCase(uri.getScheme())) {
          return null;
        }
      } else if (uri.getScheme() != null) {
        return null;
      }
  
      Map<String, String> result = Maps.newLinkedHashMap(defaults);
  
      if (pattern.isOpaque()) {
        if (!uri.isOpaque()) {
          return null;
        }
  
        Iterator<String> pathQuery = PATH_QUERY_SPLITTER
            .split(uri.getRawSchemeSpecificPart()).iterator();
  
        if (!addPath(patternPath, Iterators.getNext(pathQuery, null), result)) {
          return null;
        }
  
        addQuery(Iterators.getNext(pathQuery, null), result);
  
      } else if (!uri.isOpaque()) {
        addAuthority(uri, result);
  
        if (patternPath.isEmpty() && !uri.getRawPath().isEmpty()) {
          return null;
        }
  
        if (!addPath(patternPath, uri.getRawPath(), result)) {
          return null;
        }
  
        addQuery(uri.getRawQuery(), result);
  
      } else {
        return null;
      }
  
      if (!addComplexMatch(pattern.getFragment(), uri.getFragment(), result)) {
        return null;
      }
  
      // save this match
      this.lastMatch = result;
  
      // return the new result, so that this is thread-safe
      return result;
    }
docs: Returns results from parsing a {@link java.net.URI} with this pattern.
  If the URI doesn't match the pattern, this will return null.
  
  @param uri A URI to match against this URIPattern
  @return A Map of the pattern's variable names to values from the parsed URI