Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8065554

MatchResult should provide values of named-capturing groups

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P4 P4
    • 20
    • 19
    • core-libs

      A DESCRIPTION OF THE REQUEST :
      Method String group(String name) has been added in class java.util.regex.Matcher since 1.7 to deal with named-capturing groups.
      Unfortunately, interface java.util.regex.MatchResult has not been extended with the same method, even though now it would be possible with a default method without breaking backwards compatibility.
       

      JUSTIFICATION :
      Expressions like matcher.toMatchResult().group("MY GROUP") cannot be typechecked when matcher has static type java.util.regex.Matcher, even though class java.util.regex.Matcher defines method String group(String name)

      Note that toMatchResult() is very useful if one wants the result to be unaffected by subsequent operations performed upon the matcher; for instance, this is necessary if one has to synchronize the matcher with a character stream with methods Matcher region(int start, int end) or Matcher reset(CharSequence input).
      But toMatchResult() is useless if one has to deal with named-capturing groups, because method String group(String name) cannot be invoked on the result of toMatchResult()

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      import java.util.regex.MatchResult;
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;

      public class RequestTest {

         public static void main(String[] args) {
            Matcher matcher = Pattern.compile("(?<NUMBER>[0-9]+)|(?<BLANKS>\\s+)").matcher("42 0");
            matcher.lookingAt();
            MatchResult res = matcher.toMatchResult();
            matcher.region(res.end(), matcher.regionEnd());
            // assert res.group("NUMBER").equals("42"); // this line should compile, and assert should succeed
          }
      }
           
      ACTUAL -
      The commented line in the code snippet above cannot be compiled, as expected, since method group(String name) cannot be found in interface java.util.regex.MatchResult

      ---------- BEGIN SOURCE ----------
      import java.util.regex.MatchResult;
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;

      public class RequestTest {

         public static void main(String[] args) {
            Matcher matcher = Pattern.compile("(?<NUMBER>[0-9]+)|(?<BLANKS>\\s+)").matcher("42 0");
            matcher.lookingAt();
            assert matcher.group("NUMBER").equals("42");
            MatchResult res = matcher.toMatchResult();
            matcher.region(res.end(), matcher.regionEnd());
            // assert matcher.group("NUMBER").equals("42"); // throws java.lang.IllegalStateException
            // assert res.group("NUMBER").equals("42"); // this line should compile, and assert should succeed
          }
      }
          
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      One can either use method String group(int group), but this implies giving up using named-capturing groups, or has to resort to reflection (!).

      import java.lang.reflect.InvocationTargetException;
      import java.util.regex.MatchResult;
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;

      public class RequestReport {

      public static void main(String[] args) throws NoSuchMethodException,
      IllegalAccessException, IllegalArgumentException,
      InvocationTargetException, SecurityException {
      Matcher matcher = Pattern.compile("(?<NUMBER>[0-9]+)|(?<BLANKS>\\s+)").matcher("42 0");
      matcher.lookingAt();
      assert matcher.group("NUMBER").equals("42");
      MatchResult res = matcher.toMatchResult();
      matcher.region(res.end(), matcher.regionEnd());
      assert res.group(1).equals("42");
      assert res.getClass().getDeclaredMethod("group", String.class)
      .invoke(res, "NUMBER").equals("42");
      matcher.lookingAt();
      assert matcher.group("BLANKS") != null;
      }
      }


            rgiulietti Raffaello Giulietti
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: