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

Reply via email to