Skip to content

Commit

Permalink
Merge pull request #74 from tony19/feat/named-groups-jdk20
Browse files Browse the repository at this point in the history
feat!: rename MatchResult#namedGroups to avoid conflict in JDK 20
  • Loading branch information
tony19 authored Jan 21, 2024
2 parents bd39b01 + 9552147 commit 2c43791
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 46 deletions.
24 changes: 4 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ on:
workflow_dispatch:

jobs:
build-8-11:
runs-on: ubuntu-22.04
build:
runs-on: ubuntu-latest
strategy:
matrix:
jdk: [ '8', '9', '10', '11' ]
jdk: [ '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21' ]
name: JDK ${{ matrix.jdk }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
Expand All @@ -18,20 +18,4 @@ jobs:
distribution: 'zulu'
java-version: ${{ matrix.jdk }}
cache: 'maven'
- run: mvn verify -Dgpg.skip -Dmaven.compiler.source=6 -Dmaven.compiler.target=6

# JDK12+ no longer supports JDK6 as source/target
build-12-plus:
runs-on: ubuntu-22.04
strategy:
matrix:
jdk: [ '12', '13', '14', '15', '16', '17', '18' ]
name: JDK ${{ matrix.jdk }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
- uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: ${{ matrix.jdk }}
cache: 'maven'
- run: mvn verify -Dgpg.skip -Dmaven.compiler.source=7 -Dmaven.compiler.target=7
- run: mvn verify -Dgpg.skip
21 changes: 12 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
named-regexp [![GitHub release](https://img.shields.io/github/release/tony19/named-regexp.svg?maxAge=2592000)](https://github.com/tony19/named-regexp/releases/) [![Build](https://github.com/tony19/named-regexp/actions/workflows/ci.yml/badge.svg)](https://github.com/tony19/named-regexp/actions/workflows/ci.yml)
---

This lightweight library adds support for [named capture groups](http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#groupname) in Java 5/6 (and on Android).

This is a fork of the [named-regexp](http://code.google.com/p/named-regexp) project from Google Code (currently inactive).

This library backports [named capture groups](http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#groupname) from Java 7 to Java 5/6.

Usage
-----
You can use the same constructs for named capture groups from Java 7 (i.e., `(?<name>patt)`, etc.), as in the following example:
You can use the same constructs for named capture groups from Java 7
(i.e., `(?<name>patt)`, etc.), as in the following example:

```java
import com.google.code.regexp.Pattern;
Expand All @@ -29,15 +27,15 @@ Install

### Gradle
```gradle
implementation 'com.github.tony19:named-regexp:0.2.8'
implementation 'com.github.tony19:named-regexp:1.0.0'
```

### Maven
```xml
<dependency>
<groupId>com.github.tony19</groupId>
<artifactId>named-regexp</artifactId>
<version>0.2.8</version>
<version>1.0.0</version>
</dependency>
```

Expand All @@ -54,6 +52,10 @@ $ cd named-regexp
$ mvn package
```

To create Java 5/6 compatible bytecode, use JDK 11 or older to build this library.
The build automatically targets Java 8 (the minimum supported version) if using a
newer JDK to build.

Release
-------

Expand All @@ -65,7 +67,8 @@ $ ./release.sh

*Releases are deployed to https://repo1.maven.org/maven2/com/github/tony19/named-regexp/*

To release a `SNAPSHOT` (i.e., the version in `pom.xml` ends with `-SNAPSHOT`), run the following command:
To release a `SNAPSHOT` (i.e., the version in `pom.xml` ends with `-SNAPSHOT`),
run the following command:

```bash
$ mvn clean deploy
Expand All @@ -76,7 +79,7 @@ $ mvn clean deploy
License
-------

Copyright 2022 Anthony Trinh.
Copyright 2024 Anthony Trinh.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
16 changes: 15 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<packaging>jar</packaging>
<name>named-regexp</name>
<description>Named capturing groups for Java 5/6</description>
<version>0.2.9-SNAPSHOT</version>
<version>1.0.0-SNAPSHOT</version>
<url>https://github.com/tony19/named-regexp</url>

<licenses>
Expand Down Expand Up @@ -120,6 +120,20 @@
</build>

<profiles>
<profile>
<!--
If using JDK 12+, switch to Java 8 here (the minimum
supported version). Some users that mainly depend on newer
JDKS are still using this library for backward compatibility.
-->
<id>set-compiler-release</id>
<activation>
<jdk>[12,)</jdk>
</activation>
<properties>
<maven.compiler.release>8</maven.compiler.release>
</properties>
</profile>
<profile>
<id>release-sign-artifacts</id>
<activation>
Expand Down
28 changes: 25 additions & 3 deletions src/main/java/com/google/code/regexp/MatchResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,33 @@ public interface MatchResult extends java.util.regex.MatchResult {
public List<String> orderedGroups();

/**
* Returns the named capture groups
* Finds all named groups that exist in the input string
*
* @return the named capture groups
* @return a list of maps, each containing name-value matches
* (empty if no match found).
*
* Example:
* pattern: (?&lt;dote&gt;\d+).(?&lt;day&gt;\w+)
* input: 1 Sun foo bar 2 Mon foo
* output: [{"date":"1", "day":"Sun"}, {"date":"2", "day":"Mon"}]
*
* @since 1.0.0
*/
public List<Map<String, String>> namedGroupsList();

/**
* Returns a map of the pattern's named groups and indexes within the pattern.
*
* @return an unmodifiable map of group names to 1-based indexes
* (empty if named groups not found).
*
* Example:
* pattern: (a)(b)(?&lt;group1&gt;x)(c)(?&lt;group2&gt;y)
* output: {"group1": 3, "group2": 5}
*
* @since 1.0.0
*/
public List<Map<String, String>> namedGroups();
public Map<String, Integer> namedGroups();

/**
* Returns the input subsequence captured by the given group during the
Expand Down
33 changes: 32 additions & 1 deletion src/main/java/com/google/code/regexp/Matcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.google.code.regexp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -298,6 +300,33 @@ public String group(String groupName) {
return group(idx);
}

/**
* Returns a map of the pattern's named groups and indexes within the pattern.
*
* @return an unmodifiable map of group names to 1-based indexes
* (empty if named groups not found).
*
* Example:
* pattern: (a)(b)(?&lt;group1&gt;x)(c)(?&lt;group2&gt;y)
* output: {"group1": 3, "group2": 5}
*
* @since 1.0.0
*/
public Map<String, Integer> namedGroups() {
// Normally, this API isn't needed as this library is a backport
// of named groups, introduced in JDK7, but some users are
// using on this library in newer JDKs for whatever reason.
// https://github.com/tony19/named-regexp/issues/73
Map<String, Integer> result = new HashMap<String, Integer>();
Map<String, List<GroupInfo>> groupInfo = parentPattern.groupInfo();

for (Map.Entry<String, List<GroupInfo>> entry : groupInfo.entrySet()) {
// groupIndex() is 0-based and we need it 1-based for capture groups
result.put(entry.getKey(), entry.getValue().get(0).groupIndex() + 1);
}
return Collections.unmodifiableMap(result);
}

/**
* Finds all named groups that exist in the input string. This resets the
* matcher and attempts to match the input against the pre-specified
Expand All @@ -310,8 +339,10 @@ public String group(String groupName) {
* pattern: (?&lt;dote&gt;\d+).(?&lt;day&gt;\w+)
* input: 1 Sun foo bar 2 Mon foo
* output: [{"date":"1", "day":"Sun"}, {"date":"2", "day":"Mon"}]
*
* @since 1.0.0
*/
public List<Map<String, String>> namedGroups() {
public List<Map<String, String>> namedGroupsList() {
List<Map<String, String>> result = new ArrayList<Map<String, String>>();
List<String> groupNames = parentPattern.groupNames();

Expand Down
35 changes: 23 additions & 12 deletions src/test/java/com/google/code/regexp/MatcherTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void beforeTest() {
}

@Test
public void testFindSucceedsInFindingTaret() {
public void testFindSucceedsInFindingTarget() {
assertTrue(P.matcher("abcfoo").find());
}

Expand Down Expand Up @@ -279,7 +279,7 @@ public void testOrderedGroupsHasMatchesInOrder() {

@Test
public void testNamedGroupsDoesNotThrowIndexOutOfBounds() {
// NamedMatcher.namedGroups() is used to get a map of
// Matcher#namedGroupsList() is used to get a map of
// group names to group values. This should ignore unnamed
// groups (exclude them from the map), but the unnamed
// groups were throwing off the function, causing it to
Expand All @@ -288,7 +288,7 @@ public void testNamedGroupsDoesNotThrowIndexOutOfBounds() {
Pattern p = Pattern.compile("(a)(?<foo>b)(?:c)(?<bar>d(?<named>x))");
Matcher m = p.matcher("abcdx");
try {
m.namedGroups();
m.namedGroupsList();
// verified here: IndexOutOfBoundsException did not occur
} catch (IndexOutOfBoundsException e) {
fail("IndexOutOfBoundsException should have been fixed");
Expand All @@ -300,7 +300,7 @@ public void testNamedGroupsGetsOnlyNamedGroups() {
Pattern p = Pattern.compile("(a)(?<foo>b)(?:c)(?<bar>d(?<named>x))");
Matcher m = p.matcher("abcdxyz");

List<Map<String, String>> list = m.namedGroups();
List<Map<String, String>> list = m.namedGroupsList();
assertEquals(1, list.size());

Map<String, String> map = list.get(0);
Expand All @@ -315,7 +315,7 @@ public void testNamedGroupsWithNoMatchGetsEmptyMap() {
Pattern p = Pattern.compile("(a)(?<foo>b)(?:c)(?<bar>d(?<named>x))");
Matcher m = p.matcher("nada");

List<Map<String, String>> list = m.namedGroups();
List<Map<String, String>> list = m.namedGroupsList();
assertEquals(0, list.size());
}

Expand Down Expand Up @@ -757,7 +757,7 @@ public void testNamedGroupsGetsAllMatchesInSingleGroup() {
Pattern pattern = Pattern.compile("(?<digit>\\d)(\\w)");
Matcher matcher = pattern.matcher("2foo3bar4");

final List<Map<String, String>> groups = matcher.namedGroups();
final List<Map<String, String>> groups = matcher.namedGroupsList();
assertEquals(2, groups.size());
assertEquals("2", groups.get(0).get("digit"));
assertEquals("3", groups.get(1).get("digit"));
Expand All @@ -768,7 +768,7 @@ public void testNamedGroupsGetsAllMatchesInMultipleGroups() {
Pattern pattern = Pattern.compile("(?<dayOfYear>\\d+).(?<dayName>\\w+)");
Matcher matcher = pattern.matcher("1 Sunday foo bar 2 Monday foo bar 3 Tuesday foo bar 4 Wednesday foo bar 5 Thursday foo bar 6 Friday foo bar 7 Saturday foo bar 8 Sunday foo bar 9 Monday foo bar 10 Tuesday foo bar ");

final List<Map<String, String>> groups = matcher.namedGroups();
final List<Map<String, String>> groups = matcher.namedGroupsList();
final String[] DAYS = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday"};
assertEquals(DAYS.length, groups.size());

Expand All @@ -784,15 +784,15 @@ public void testNamedGroupsReturnsEmptyListWhenNoGroupPresent() {
Pattern pattern = Pattern.compile("\\d+ no groups");
Matcher matcher = pattern.matcher("123 no groups");

final List<Map<String, String>> groups = matcher.namedGroups();
final List<Map<String, String>> groups = matcher.namedGroupsList();
assertTrue(groups.isEmpty());
}

// Specify 1 second timeout to account for potential infinite loop (Issue #16)
@Test(timeout=1000)
public void testNamedGroupsReturnsWhenMatchesEmptyString() {
com.google.code.regexp.Matcher matcher = com.google.code.regexp.Pattern.compile("(?<foo>.*)").matcher("bar");
final List<Map<String, String>> groups = matcher.namedGroups();
final List<Map<String, String>> groups = matcher.namedGroupsList();
assertEquals(1, groups.size());
assertEquals("bar", groups.get(0).get("foo"));
}
Expand All @@ -804,11 +804,22 @@ public void testNamedGroupsCanBeCalledMultipleTimes() {
final String url = "/teamDrawer/12345";

final Matcher matcher = Pattern.compile(regex).matcher(url);
final Integer count = matcher.namedGroups().size();
final Integer count = matcher.namedGroupsList().size();
assertEquals(Integer.valueOf(1), count);
final Integer mapCount = matcher.namedGroups().get(0).size();
final Integer mapCount = matcher.namedGroupsList().get(0).size();
assertEquals(Integer.valueOf(1), mapCount);
final String value = matcher.namedGroups().get(0).get("roomId");
final String value = matcher.namedGroupsList().get(0).get("roomId");
assertEquals("12345", value);
}

@Test
public void testMatcherNamedGroupsGetsMapsOfGroupIndexes() {
// Test compatibility with MatchResult#namedGroups added in JDK20
// https://github.com/tony19/named-regexp/issues/73
Pattern p = Pattern.compile("(b)(c)(?<named1>x)(d)(?<named2>y)");
MatchResult m = p.matcher("abcxdy");
Map<String, Integer> groupIndexes = m.namedGroups();
assertEquals(Integer.valueOf(3), groupIndexes.get("named1"));
assertEquals(Integer.valueOf(5), groupIndexes.get("named2"));
}
}

0 comments on commit 2c43791

Please sign in to comment.