public static String extractFromURIPattern(String paramsRuleString, String pattern, String realURI) {
      Map<String, String> criteriaMap = new TreeMap<>();
      pattern = sanitizeURLForRegExp(pattern);
      realURI = sanitizeURLForRegExp(realURI);

      // Build a pattern for extracting parts from pattern and a pattern for extracting values
      // from realURI. Supporting both {id} and :id.
      String partsPattern = null;
      String valuesPattern = null;
      if (pattern.indexOf("/{") != -1) {
         partsPattern = pattern.replaceAll(CURLY_PART_PATTERN, CURLY_PART_EXTRACTION_PATTERN);
         valuesPattern = pattern.replaceAll(CURLY_PART_PATTERN, "(.+)");
      } else {
         partsPattern = pattern.replaceAll("(:[^:^/]+)", "\\:(.+)");
         valuesPattern = pattern.replaceAll("(:[^:^/]+)", "(.+)");
      }
      if (pattern.contains("$")) {
         partsPattern = partsPattern.replace("$", "\\$");
         valuesPattern = valuesPattern.replace("$", "\\$");
      }
      Pattern partsP = Pattern.compile(partsPattern);
      Matcher partsM = partsP.matcher(pattern);

      Pattern valuesP = Pattern.compile(valuesPattern);
      Matcher valuesM = valuesP.matcher(realURI);

      // Rule string can be a URI_ELEMENT rule and containers ?? elements.
      // We must remove them before parsing the URI parts.
      if (paramsRuleString.contains("??")) {
         paramsRuleString = paramsRuleString.split("\\?\\?")[0];
      }
      final var paramsRule = Arrays.stream(paramsRuleString.split("&&")).map(String::trim).distinct()
            .collect(Collectors.toUnmodifiableSet());

      // Both should match and have the same group count.
      if (valuesM.matches() && partsM.matches() && valuesM.groupCount() == partsM.groupCount()) {
         for (int i = 1; i < partsM.groupCount() + 1; i++) {
            final String paramName = partsM.group(i);
            final String paramValue = valuesM.group(i);
            if (paramsRule.contains(paramName)) {
               criteriaMap.put(paramName, paramValue);
            }
         }
      }

      // Just appends sorted entries, separating them with /.
      StringBuilder result = new StringBuilder();
      for (Map.Entry<String, String> criteria : criteriaMap.entrySet()) {
         result.append("/").append(criteria.getKey()).append("=").append(criteria.getValue());
      }
      return result.toString();
   }
@Test
   void testExtractFromURIPattern2() {
      String resourcePath = "/pet/2";
      String operationName = "/pet/:petId";
      String paramRule = "petId";

      String dispatchCriteria = DispatchCriteriaHelper.extractFromURIPattern(paramRule, operationName, resourcePath);
      assertEquals("/petId=2", dispatchCriteria);

      resourcePath = "/order/123456";
      operationName = "/order/:id";
      paramRule = "id";

      dispatchCriteria = DispatchCriteriaHelper.extractFromURIPattern(paramRule, operationName, resourcePath);
      assertEquals("/id=123456", dispatchCriteria);
   }