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

MatchResult should be enhanced or extended to support named capturing groups

    XMLWordPrintable

    Details

    • Type: Enhancement
    • Status: Open
    • Priority: P4
    • Resolution: Unresolved
    • Affects Version/s: 8u25
    • Fix Version/s: None
    • Component/s: core-libs
    • Labels:

      Description

      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 metod 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;
      }
      }


        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                sherman Xueming Shen
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                5 Start watching this issue

                Dates

                • Created:
                  Updated: