From cb27a846996c625312d37e648e5be33e40de5e36 Mon Sep 17 00:00:00 2001 From: ytanida Date: Wed, 18 Oct 2023 21:27:48 +0900 Subject: [PATCH 1/5] Perf improvement fixes - Increase concurrency of String Interner. - GrammaticalTerm#makeSkinny now uses ImmutableMap. SortedMap could be better in terms of memory usage, but generation cost was too high - use read/writeUTF for string output in ComplexGrammaticalForm --- .../commons/util/settings/IniFileUtil.java | 2 +- .../force/i18n/grammar/GrammaticalTerm.java | 20 ++++++----- .../grammar/impl/ComplexGrammaticalForm.java | 34 +++++++++++++++---- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/force/i18n/commons/util/settings/IniFileUtil.java b/src/main/java/com/force/i18n/commons/util/settings/IniFileUtil.java index 7a2f488..b096fc2 100644 --- a/src/main/java/com/force/i18n/commons/util/settings/IniFileUtil.java +++ b/src/main/java/com/force/i18n/commons/util/settings/IniFileUtil.java @@ -19,7 +19,7 @@ */ public class IniFileUtil { - private static final Interner INTERNER = Interners.newWeakInterner(); + private static final Interner INTERNER = Interners.newBuilder().weak().concurrencyLevel(16).build(); /** * For the given {@link String}, return reference to equal String. Useful for {@link String} deduping. diff --git a/src/main/java/com/force/i18n/grammar/GrammaticalTerm.java b/src/main/java/com/force/i18n/grammar/GrammaticalTerm.java index b46e3f2..e06640d 100644 --- a/src/main/java/com/force/i18n/grammar/GrammaticalTerm.java +++ b/src/main/java/com/force/i18n/grammar/GrammaticalTerm.java @@ -9,13 +9,18 @@ import static com.force.i18n.commons.util.settings.IniFileUtil.intern; -import java.io.*; -import java.util.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Comparator; +import java.util.Map; +import java.util.Objects; import com.force.i18n.HumanLanguage; import com.force.i18n.LanguageProviderFactory; import com.force.i18n.grammar.impl.LanguageDeclensionFactory; -import com.google.common.collect.ImmutableSortedMap; +import com.ibm.icu.impl.locale.XCldrStub.ImmutableMap; /** * Represents a grammatical term; generally one that is declined based on a noun form or other @@ -138,19 +143,18 @@ public void makeSkinny() { } /** - * Utility method used to convert static {@link Map}'s concrete type to a {@link ImmutableSortedMap}. - * {@link ImmutableSortedMap} have a 8 byte overhead per element and are useful for reducing the per element - * overhead, that is traditionally high on most {@code Map} implementations. + * Utility method used to convert static {@link Map}'s concrete type to a {@link ImmutableMap}. + * This copy could take a lot of cost. Used to use SortedMap but hash is way more cheaper. * * @param * the type of the grammatical form for this term * @param map * the map to make skinny - * @return A {@link ImmutableSortedMap} created from a {@link Map} of {@link GrammaticalForm}'s (key) to + * @return A {@link ImmutableMap} created from a {@link Map} of {@link GrammaticalForm}'s (key) to * {@link String}'s (value). */ protected Map makeSkinny(Map map) { - return ImmutableSortedMap.copyOf(map, new KeyComparator()); + return ImmutableMap.copyOf(map); } private static class KeyComparator implements Comparator, Serializable { diff --git a/src/main/java/com/force/i18n/grammar/impl/ComplexGrammaticalForm.java b/src/main/java/com/force/i18n/grammar/impl/ComplexGrammaticalForm.java index cee9cb0..cc4b62a 100644 --- a/src/main/java/com/force/i18n/grammar/impl/ComplexGrammaticalForm.java +++ b/src/main/java/com/force/i18n/grammar/impl/ComplexGrammaticalForm.java @@ -9,14 +9,36 @@ import static com.force.i18n.commons.util.settings.IniFileUtil.intern; -import java.io.*; -import java.util.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; import com.force.i18n.HumanLanguage; import com.force.i18n.LanguageProviderFactory; -import com.force.i18n.grammar.*; +import com.force.i18n.grammar.Adjective; +import com.force.i18n.grammar.AdjectiveForm; +import com.force.i18n.grammar.ArticleForm; +import com.force.i18n.grammar.ArticledDeclension; import com.force.i18n.grammar.ArticledDeclension.LegacyArticledNoun; import com.force.i18n.grammar.GrammaticalTerm.TermType; +import com.force.i18n.grammar.LanguageArticle; +import com.force.i18n.grammar.LanguageCase; +import com.force.i18n.grammar.LanguageDeclension; +import com.force.i18n.grammar.LanguageGender; +import com.force.i18n.grammar.LanguageNumber; +import com.force.i18n.grammar.LanguagePosition; +import com.force.i18n.grammar.LanguagePossessive; +import com.force.i18n.grammar.LanguageStartsWith; +import com.force.i18n.grammar.ModifierForm; +import com.force.i18n.grammar.Noun; +import com.force.i18n.grammar.NounForm; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; @@ -250,8 +272,8 @@ static void serializeFormMap(ObjectOutputStre } else { out.writeByte(values.size()); for (Map.Entry entry : values.entrySet()) { - out.writeByte(entry.getKey().getOrdinal()); - out.writeObject(entry.getValue()); // Serialize the "object" because it's been uniquefied + out.writeByte(entry.getKey().getOrdinal()); + out.writeUTF(entry.getValue()); // Serialize the "object" because it's been uniquefied } } } @@ -272,7 +294,7 @@ static Map deserializeFormMap(Obje assert formList != null; for (int i = 0; i < size; i++) { int ordinal = in.readByte(); - String value = intern((String) in.readObject()); + String value = intern(in.readUTF()); result.put(formList.get(ordinal), value); } return result; From 821a273c587350245e87c31243a0d0a4531870e9 Mon Sep 17 00:00:00 2001 From: ytanida Date: Thu, 19 Oct 2023 11:14:31 +0900 Subject: [PATCH 2/5] - Fixed wrong import of ImmutableMap - Improve HumanLanguage's serialization - Remove unused class. --- .../force/i18n/grammar/GrammaticalTerm.java | 14 ++------- .../grammar/impl/ComplexGrammaticalForm.java | 31 +++++-------------- .../i18n/grammar/parser/TermAttributes.java | 23 +++++++++++--- 3 files changed, 29 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/force/i18n/grammar/GrammaticalTerm.java b/src/main/java/com/force/i18n/grammar/GrammaticalTerm.java index e06640d..e1f7823 100644 --- a/src/main/java/com/force/i18n/grammar/GrammaticalTerm.java +++ b/src/main/java/com/force/i18n/grammar/GrammaticalTerm.java @@ -13,14 +13,13 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.util.Comparator; import java.util.Map; import java.util.Objects; import com.force.i18n.HumanLanguage; import com.force.i18n.LanguageProviderFactory; import com.force.i18n.grammar.impl.LanguageDeclensionFactory; -import com.ibm.icu.impl.locale.XCldrStub.ImmutableMap; +import com.google.common.collect.ImmutableMap; /** * Represents a grammatical term; generally one that is declined based on a noun form or other @@ -124,13 +123,13 @@ public int hashCode() { private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); - out.writeObject(this.declension.getLanguage().getLocaleString()); + out.writeInt(this.declension.getLanguage().ordinal()); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); this.name = intern(name); - HumanLanguage ul = LanguageProviderFactory.get().getProvider().getLanguage((String)in.readObject()); + HumanLanguage ul = LanguageProviderFactory.get().getProvider().getAll().get(in.readInt()); this.declension = LanguageDeclensionFactory.get().getDeclension(ul); } @@ -156,11 +155,4 @@ public void makeSkinny() { protected Map makeSkinny(Map map) { return ImmutableMap.copyOf(map); } - - private static class KeyComparator implements Comparator, Serializable { - @Override - public int compare(T o1, T o2) { - return o1.getKey().compareTo(o2.getKey()); - } - } } diff --git a/src/main/java/com/force/i18n/grammar/impl/ComplexGrammaticalForm.java b/src/main/java/com/force/i18n/grammar/impl/ComplexGrammaticalForm.java index cc4b62a..430f4ca 100644 --- a/src/main/java/com/force/i18n/grammar/impl/ComplexGrammaticalForm.java +++ b/src/main/java/com/force/i18n/grammar/impl/ComplexGrammaticalForm.java @@ -40,6 +40,7 @@ import com.force.i18n.grammar.Noun; import com.force.i18n.grammar.NounForm; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Multimap; /** @@ -254,12 +255,12 @@ public void appendJsFormReplacement(Appendable a, String termFormVar, String gen */ private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); - out.writeObject(this.declension.getLanguage().getLocaleString()); + out.writeInt(this.declension.getLanguage().ordinal()); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - HumanLanguage ul = LanguageProviderFactory.get().getProvider().getLanguage((String)in.readObject()); + HumanLanguage ul = LanguageProviderFactory.get().getProvider().getAll().get(in.readInt()); this.declension = LanguageDeclensionFactory.get().getDeclension(ul); } @@ -281,10 +282,10 @@ static void serializeFormMap(ObjectOutputStre @SuppressWarnings("unchecked") // Deserializing a map using trickery static Map deserializeFormMap(ObjectInputStream in, LanguageDeclension declension, TermType termType) throws IOException, ClassNotFoundException { int size = in.readByte(); - Map result = new HashMap<>(size << 1); if (size == 0) { - return result; + return ImmutableMap.of(); } + ImmutableMap.Builder builder = ImmutableMap.builder(); List formList = null; switch (termType) { case Noun: formList = (List)declension.getAllNounForms(); break; @@ -295,9 +296,9 @@ static Map deserializeFormMap(Obje for (int i = 0; i < size; i++) { int ordinal = in.readByte(); String value = intern(in.readUTF()); - result.put(formList.get(ordinal), value); + builder.put(formList.get(ordinal), value); } - return result; + return builder.build(); } @@ -534,12 +535,6 @@ private void writeObject(ObjectOutputStream out) throws IOException { private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Adjective); - makeSkinny(); - } - - @Override - public void makeSkinny() { - values = makeSkinny(values); } } @@ -594,12 +589,6 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE in.defaultReadObject(); this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Noun); - makeSkinny(); - } - - @Override - public void makeSkinny() { - values = makeSkinny(values); } } @@ -656,12 +645,6 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE in.defaultReadObject(); this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Noun); - makeSkinny(); - } - - @Override - public void makeSkinny() { - values = makeSkinny(values); } } } diff --git a/src/main/java/com/force/i18n/grammar/parser/TermAttributes.java b/src/main/java/com/force/i18n/grammar/parser/TermAttributes.java index 0062974..1b9e253 100644 --- a/src/main/java/com/force/i18n/grammar/parser/TermAttributes.java +++ b/src/main/java/com/force/i18n/grammar/parser/TermAttributes.java @@ -7,13 +7,28 @@ package com.force.i18n.grammar.parser; -import java.io.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; import org.xml.sax.Attributes; import com.force.i18n.HumanLanguage; import com.force.i18n.LanguageProviderFactory; -import com.force.i18n.grammar.*; +import com.force.i18n.grammar.AdjectiveForm; +import com.force.i18n.grammar.ArticleForm; +import com.force.i18n.grammar.GrammaticalTerm; +import com.force.i18n.grammar.LanguageArticle; +import com.force.i18n.grammar.LanguageCase; +import com.force.i18n.grammar.LanguageDeclension; +import com.force.i18n.grammar.LanguageGender; +import com.force.i18n.grammar.LanguageNumber; +import com.force.i18n.grammar.LanguagePosition; +import com.force.i18n.grammar.LanguagePossessive; +import com.force.i18n.grammar.LanguageStartsWith; +import com.force.i18n.grammar.Noun; +import com.force.i18n.grammar.NounForm; import com.force.i18n.grammar.impl.LanguageDeclensionFactory; /** @@ -282,12 +297,12 @@ private static String toNullStr(Object o) { private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); - out.writeObject(this.declension.getLanguage().getLocaleString()); + out.writeInt(this.declension.getLanguage().ordinal()); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); - HumanLanguage ul = LanguageProviderFactory.get().getProvider().getLanguage((String)in.readObject()); + HumanLanguage ul = LanguageProviderFactory.get().getProvider().getAll().get(in.readInt()); this.declension = LanguageDeclensionFactory.get().getDeclension(ul); } } From 46160614a2b088201bdc7b2d3f9f9622cf783dd6 Mon Sep 17 00:00:00 2001 From: ytanida Date: Thu, 19 Oct 2023 13:20:41 +0900 Subject: [PATCH 3/5] - Remove more makeSkinny using ComplexGrammaticalForm#deserializeFormMap - use more read/writeUTF instead of -Object --- .../grammar/impl/DravidianDeclension.java | 32 +++++++++---- .../i18n/grammar/impl/GermanicDeclension.java | 47 ++++++++++++++----- .../force/i18n/grammar/parser/TermRefTag.java | 11 +++-- 3 files changed, 65 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/force/i18n/grammar/impl/DravidianDeclension.java b/src/main/java/com/force/i18n/grammar/impl/DravidianDeclension.java index 96db4f4..7eab243 100644 --- a/src/main/java/com/force/i18n/grammar/impl/DravidianDeclension.java +++ b/src/main/java/com/force/i18n/grammar/impl/DravidianDeclension.java @@ -8,12 +8,31 @@ import static com.force.i18n.commons.util.settings.IniFileUtil.intern; -import java.io.*; -import java.util.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; import com.force.i18n.HumanLanguage; -import com.force.i18n.grammar.*; +import com.force.i18n.grammar.AbstractLanguageDeclension; +import com.force.i18n.grammar.Adjective; +import com.force.i18n.grammar.AdjectiveForm; +import com.force.i18n.grammar.LanguageArticle; +import com.force.i18n.grammar.LanguageCase; +import com.force.i18n.grammar.LanguageDeclension; +import com.force.i18n.grammar.LanguageGender; +import com.force.i18n.grammar.LanguageNumber; +import com.force.i18n.grammar.LanguagePosition; +import com.force.i18n.grammar.LanguagePossessive; +import com.force.i18n.grammar.LanguageStartsWith; +import com.force.i18n.grammar.Noun; import com.force.i18n.grammar.Noun.NounType; +import com.force.i18n.grammar.NounForm; import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexNounForm; import com.google.common.collect.ImmutableList; @@ -123,11 +142,6 @@ protected boolean validateValues(String name, LanguageCase _case) { return defaultValidate(name, getDeclension().getFieldForms()); } - @Override - public void makeSkinny() { - values = makeSkinny(values); - } - /** * Need to override so that a cloned DravidianNoun's values map is a HashMap. * Else, if you clone() after makeSkinny() has been called, you won't @@ -157,7 +171,6 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE in.defaultReadObject(); this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Noun); - makeSkinny(); } } @@ -272,7 +285,6 @@ public EnumSet getRequiredCases() { LanguageCase.GENITIVE, LanguageCase.ACCUSATIVE, LanguageCase.DATIVE, - LanguageCase.ABLATIVE, // Ablative & Instrumental merger LanguageCase.LOCATIVE); } diff --git a/src/main/java/com/force/i18n/grammar/impl/GermanicDeclension.java b/src/main/java/com/force/i18n/grammar/impl/GermanicDeclension.java index 02abd96..cad1dbb 100644 --- a/src/main/java/com/force/i18n/grammar/impl/GermanicDeclension.java +++ b/src/main/java/com/force/i18n/grammar/impl/GermanicDeclension.java @@ -9,16 +9,47 @@ import static com.force.i18n.commons.util.settings.IniFileUtil.intern; -import java.io.*; -import java.util.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.logging.Logger; import com.force.i18n.HumanLanguage; import com.force.i18n.commons.text.CaseFolder; -import com.force.i18n.grammar.*; +import com.force.i18n.grammar.Adjective; +import com.force.i18n.grammar.AdjectiveForm; +import com.force.i18n.grammar.Article; +import com.force.i18n.grammar.ArticleForm; +import com.force.i18n.grammar.ArticledDeclension; +import com.force.i18n.grammar.LanguageArticle; +import com.force.i18n.grammar.LanguageCase; +import com.force.i18n.grammar.LanguageDeclension; +import com.force.i18n.grammar.LanguageGender; +import com.force.i18n.grammar.LanguageNumber; +import com.force.i18n.grammar.LanguagePosition; +import com.force.i18n.grammar.LanguagePossessive; +import com.force.i18n.grammar.LanguageStartsWith; +import com.force.i18n.grammar.Noun; import com.force.i18n.grammar.Noun.NounType; -import com.force.i18n.grammar.impl.ComplexGrammaticalForm.*; -import com.google.common.collect.*; +import com.force.i18n.grammar.NounForm; +import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexAdjective; +import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexAdjectiveForm; +import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexArticleForm; +import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexArticledNoun; +import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexNounForm; +import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ModifierFormMap; +import com.force.i18n.grammar.impl.ComplexGrammaticalForm.NounFormMap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; /** * Provide a declension system for a germanic language. Generally, there are @@ -341,12 +372,6 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE in.defaultReadObject(); this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Article); - makeSkinny(); - } - - @Override - public void makeSkinny() { - values = makeSkinny(values); } } diff --git a/src/main/java/com/force/i18n/grammar/parser/TermRefTag.java b/src/main/java/com/force/i18n/grammar/parser/TermRefTag.java index ef6b766..9f689ce 100644 --- a/src/main/java/com/force/i18n/grammar/parser/TermRefTag.java +++ b/src/main/java/com/force/i18n/grammar/parser/TermRefTag.java @@ -10,9 +10,12 @@ import static com.force.i18n.commons.util.settings.IniFileUtil.intern; import java.io.IOException; -import java.util.*; +import java.util.Collections; +import java.util.List; +import java.util.Set; -import com.force.i18n.grammar.*; +import com.force.i18n.grammar.GrammaticalForm; +import com.force.i18n.grammar.GrammaticalTerm; import com.force.i18n.grammar.GrammaticalTerm.TermType; import com.force.i18n.grammar.LanguageDictionary; @@ -129,13 +132,13 @@ public Set getTermsInUse(LanguageDictionary dictionary) { private void writeObject(java.io.ObjectOutputStream s) throws IOException { // Write out the threshold, loadfactor, and any hidden stuff s.defaultWriteObject(); - s.writeObject(this.name); + s.writeUTF(this.name); } private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { // Read in the threshold, loadfactor, and any hidden stuff s.defaultReadObject(); - this.name = intern((String)s.readObject()); + this.name = intern(s.readUTF()); } protected Object readResolve() { From d5e9f3948aff3f714392d2ae3b37f5846f9a0acb Mon Sep 17 00:00:00 2001 From: ytanida Date: Thu, 19 Oct 2023 14:11:52 +0900 Subject: [PATCH 4/5] another makeskinny fix --- .../i18n/grammar/impl/BengaliDeclension.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/force/i18n/grammar/impl/BengaliDeclension.java b/src/main/java/com/force/i18n/grammar/impl/BengaliDeclension.java index be9cf60..599ab17 100644 --- a/src/main/java/com/force/i18n/grammar/impl/BengaliDeclension.java +++ b/src/main/java/com/force/i18n/grammar/impl/BengaliDeclension.java @@ -9,12 +9,35 @@ import static com.force.i18n.commons.util.settings.IniFileUtil.intern; -import java.io.*; -import java.util.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; import com.force.i18n.HumanLanguage; -import com.force.i18n.grammar.*; +import com.force.i18n.grammar.Adjective; +import com.force.i18n.grammar.AdjectiveForm; +import com.force.i18n.grammar.Article; +import com.force.i18n.grammar.ArticleForm; +import com.force.i18n.grammar.ArticledDeclension; +import com.force.i18n.grammar.LanguageArticle; +import com.force.i18n.grammar.LanguageCase; +import com.force.i18n.grammar.LanguageDeclension; +import com.force.i18n.grammar.LanguageGender; +import com.force.i18n.grammar.LanguageNumber; +import com.force.i18n.grammar.LanguagePosition; +import com.force.i18n.grammar.LanguagePossessive; +import com.force.i18n.grammar.LanguageStartsWith; +import com.force.i18n.grammar.Noun; import com.force.i18n.grammar.Noun.NounType; +import com.force.i18n.grammar.NounForm; import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexNounForm; import com.google.common.collect.ImmutableList; @@ -137,11 +160,6 @@ protected boolean validateValues(String name, LanguageCase _case) { return defaultValidate(name, getDeclension().getFieldForms()); } - @Override - public void makeSkinny() { - values = makeSkinny(values); - } - /** * Need to override so that a cloned BengaliNoun's values map is a HashMap. * Else, if you clone() after makeSkinny() has been called, you won't @@ -163,7 +181,6 @@ private void writeObject(ObjectOutputStream out) throws IOException { private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Noun); - makeSkinny(); } } From 068e1e0e99ff9fa0596e7b8d6a22ce32aabffb6b Mon Sep 17 00:00:00 2001 From: ytanida Date: Thu, 19 Oct 2023 14:29:13 +0900 Subject: [PATCH 5/5] Revive 1 line --- .../java/com/force/i18n/grammar/impl/DravidianDeclension.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/force/i18n/grammar/impl/DravidianDeclension.java b/src/main/java/com/force/i18n/grammar/impl/DravidianDeclension.java index 7eab243..158f95b 100644 --- a/src/main/java/com/force/i18n/grammar/impl/DravidianDeclension.java +++ b/src/main/java/com/force/i18n/grammar/impl/DravidianDeclension.java @@ -285,6 +285,7 @@ public EnumSet getRequiredCases() { LanguageCase.GENITIVE, LanguageCase.ACCUSATIVE, LanguageCase.DATIVE, + LanguageCase.ABLATIVE, // Ablative & Instrumental merger LanguageCase.LOCATIVE); }