This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 882677e351a535d811bc8d417810240162b417b9 Author: Andrus Adamchik <[email protected]> AuthorDate: Mon Jul 20 15:52:21 2026 +0200 CAY-2980 Improve model name generation fixing more cases of pluralization --- .../apache/cayenne/dbsync/naming/EnglishInflector.java | 18 +++++++++++------- .../cayenne/dbsync/naming/EnglishInflectorTest.java | 10 ++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/EnglishInflector.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/EnglishInflector.java index a43a0bbbf..758878365 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/EnglishInflector.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/EnglishInflector.java @@ -33,12 +33,12 @@ import java.util.regex.Pattern; */ public final class EnglishInflector { - // nouns whose plural form is identical to the singular (including silent-s loanwords that must be - // shielded from the generic "-s -> -ses" rule below) + // nouns whose plural form is identical to the singular (including silent-s loanwords and plural-only + // words like "stats" that must be shielded from the generic "-s -> -ses" rule below) private static final Set<String> UNCOUNTABLE = Set.of( "equipment", "information", "rice", "money", "species", "series", "fish", "sheep", "deer", "news", "police", "aircraft", - "corps", "chassis", "debris"); + "corps", "chassis", "debris", "stats"); // nouns that don't follow any regular rule private static final Map<String, String> IRREGULAR = Map.ofEntries( @@ -97,14 +97,18 @@ public final class EnglishInflector { return noun; } - String lower = noun.toLowerCase(); - if (UNCOUNTABLE.contains(lower)) { + // irregular and uncountable forms are matched on the last "_"-separated word, so that compound + // names inflect their final noun ("playoff_series", "art_person") + int lastWordStart = noun.lastIndexOf('_') + 1; + String lastWord = noun.substring(lastWordStart).toLowerCase(); + + if (UNCOUNTABLE.contains(lastWord)) { return noun; } - String irregular = IRREGULAR.get(lower); + String irregular = IRREGULAR.get(lastWord); if (irregular != null) { - return irregular; + return noun.substring(0, lastWordStart) + irregular; } for (Map.Entry<Pattern, String> e : RULES.entrySet()) { diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/EnglishInflectorTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/EnglishInflectorTest.java index 9f8015870..9fbc281ff 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/EnglishInflectorTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/EnglishInflectorTest.java @@ -112,6 +112,16 @@ public class EnglishInflectorTest { assertEquals("series", EnglishInflector.pluralOf("series")); assertEquals("fish", EnglishInflector.pluralOf("fish")); assertEquals("equipment", EnglishInflector.pluralOf("equipment")); + assertEquals("stats", EnglishInflector.pluralOf("stats")); + } + + @Test + public void compoundNames() { + // irregular and uncountable forms apply to the last "_"-separated word + assertEquals("playoff_series", EnglishInflector.pluralOf("playoff_series")); + assertEquals("team_season_stats", EnglishInflector.pluralOf("team_season_stats")); + assertEquals("art_people", EnglishInflector.pluralOf("art_person")); + assertEquals("order_lines", EnglishInflector.pluralOf("order_line")); } @Test
