branch: elpa/datetime
commit 38a85cb35253a15f10f7451fe4a03990044a31b8
Author: Paul Pogonyshev <[email protected]>
Commit: Paul Pogonyshev <[email protected]>
Fix another bug in 'HarvestData' tool; no effect currently, but would be
uncovered by future changes.
---
Eldev | 3 +-
dev/HarvestData.java | 140 +++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 115 insertions(+), 28 deletions(-)
diff --git a/Eldev b/Eldev
index ef79863fca..c4e38c2cde 100644
--- a/Eldev
+++ b/Eldev
@@ -55,7 +55,8 @@
:destination '(t nil)
:forward-output 'stderr
(unless (= exit-code 0)
- (signal 'eldev-error `("`HarvestData' tool exited with error code %d:
%s" ,exit-code ,(buffer-string))))
+ (signal 'eldev-error `(:hint "stderr output, if any, is shown above"
+ "`HarvestData' tool exited with error code
%d:\n%s" ,exit-code ,(if (eobp) "[no stdout output]" (buffer-string)))))
(eldev-trace "Building an extmap out of it...")
(apply #'extmap-from-alist target (eldev-read-wholly (buffer-string)
"`HarvestData' output") :overwrite t extmap-flags)))
diff --git a/dev/HarvestData.java b/dev/HarvestData.java
index eabd023a40..cb242de90f 100644
--- a/dev/HarvestData.java
+++ b/dev/HarvestData.java
@@ -1,3 +1,4 @@
+import java.lang.reflect.*;
import java.time.*;
import java.time.chrono.*;
import java.time.format.*;
@@ -20,6 +21,8 @@ public class HarvestData
public static void main (String[] args) throws Exception
{
+ SelfTests.run ();
+
if (Arrays.asList (args).contains ("--locales"))
printLocaleData ();
@@ -235,49 +238,67 @@ public class HarvestData
return toLispPlist (data, false);
}
+
+ private static Map <String, String> LOCALE_FALLBACK_KEYS = Map.of
(":month-standalone-abbr", ":month-context-abbr",
+
":month-standalone-names", ":month-context-names",
+
":weekday-standalone-abbr", ":weekday-context-abbr",
+
":weekday-standalone-names", ":weekday-context-names");
+ private static Map <String, String> LOCALE_DEFAULT_VALUES = Map.of
(":decimal-separator", "?.",
+
":eras", ENGLISH_ERAS,
+
":am-pm", ENGLISH_AM_PM,
+
":date-time-pattern-rule", "(t . \" \")");
+
protected static void removeUnnecessaryLocaleData (Map <Locale, Map
<String, String>> data, Locale locale)
{
Map <String, String> locale_data = data.get (locale);
Locale parent = new Locale (locale.getLanguage ());
- Map <String, String> parent_data;
+ Map <String, String> parent_data = null;
- if (Objects.equals (locale, parent))
- parent_data = new HashMap <> ();
- else {
+ if (!Objects.equals (locale, parent)) {
removeUnnecessaryLocaleData (data, parent);
parent_data = data.get (parent);
locale_data.put (":parent", parent.toLanguageTag ());
}
- removeForFallback1 (locale_data, parent_data, ":decimal-separator",
"?.");
- removeForFallback1 (locale_data, parent_data, ":eras",
ENGLISH_ERAS);
- removeForFallback1 (locale_data, parent_data, ":am-pm",
ENGLISH_AM_PM);
- removeForFallback1 (locale_data, parent_data, ":day-periods",
null);
- removeForFallback1 (locale_data, parent_data,
":date-time-pattern-rule", "(t . \" \")");
-
- removeForFallback2 (locale_data, parent_data,
":month-standalone-abbr", ":month-context-abbr");
- removeForFallback2 (locale_data, parent_data,
":month-standalone-names", ":month-context-names");
- removeForFallback2 (locale_data, parent_data,
":weekday-standalone-abbr", ":weekday-context-abbr");
- removeForFallback2 (locale_data, parent_data,
":weekday-standalone-names", ":weekday-context-names");
-
- for (Iterator <Map.Entry <String, String>> it = locale_data.entrySet
().iterator (); it.hasNext ();) {
- Map.Entry <String, String> entry = it.next ();
- if (Objects.equals (entry.getValue (), parent_data.get
(entry.getKey ())))
- it.remove ();
+ // See the various tests for this method. Removals below need to
satisfy them all.
+
+ for (var entry : LOCALE_FALLBACK_KEYS.entrySet ()) {
+ var key = entry.getKey ();
+ var fallback_to = entry.getValue ();
+
+ if (locale_data.containsKey (key) && Objects.equals
(locale_data.get (key), locale_data.get (fallback_to)))
+ locale_data.remove (key);
}
- }
- protected static void removeForFallback1 (Map <String, String>
locale_data, Map <String, String> parent_data, String key, String default_value)
- {
- if (Objects.equals (locale_data.get (key), parent_data.getOrDefault
(key, default_value)))
- locale_data.remove (key);
+ for (var it = locale_data.entrySet ().iterator (); it.hasNext ();) {
+ var entry = it.next ();
+ var key = entry.getKey ();
+
+ if (!key.equals (":parent") && !LOCALE_FALLBACK_KEYS.containsKey
(key)) {
+ if (Objects.equals (entry.getValue (), getEffectiveValue
(parent_data, entry.getKey ())))
+ it.remove ();
+ }
+ }
+
+ if (parent_data != null) {
+ for (var entry : LOCALE_FALLBACK_KEYS.entrySet ()) {
+ var key = entry.getKey ();
+ var fallback_to = entry.getValue ();
+
+ if (locale_data.containsKey (key) && locale_data.get
(fallback_to) == null && Objects.equals (locale_data.get (key), parent_data.get
(key)))
+ locale_data.remove (key);
+ }
+ }
}
- protected static void removeForFallback2 (Map <String, String>
locale_data, Map <String, String> parent_data, String main_key, String
fallback_key)
+ protected static String getEffectiveValue (Map <String, String>
locale_data, String key)
{
- if (Objects.equals (locale_data.get (main_key), locale_data.get
(fallback_key)))
- locale_data.remove (main_key);
+ String value = (locale_data != null ? locale_data.get (key) : null);
+ if (value != null)
+ return value;
+ else
+ return LOCALE_DEFAULT_VALUES.get (key);
}
@@ -637,4 +658,69 @@ public class HarvestData
return String.format (dst ? "%d.0" : "%d", seconds);
}
}
+
+
+ // Normally tests should be separate, but since this is a run-once tool
and we don't
+ // have a proper Java setup for testing in this project, it's fine to do
it like this.
+ protected static class SelfTests
+ {
+ public void testRemoveUnnecessaryLocaleData ()
+ {
+ var xx = Locale.forLanguageTag ("xx");
+ var xx_yy = Locale.forLanguageTag ("xx-YY");
+ var data1 = Map.of (xx, modifiableMap (":month-context-abbr",
"1", ":month-standalone-abbr", "1"),
+ xx_yy, modifiableMap (":month-context-abbr",
"1", ":month-standalone-abbr", "1"));
+
+ removeUnnecessaryLocaleData (data1, xx_yy);
+ assertEquals (data1, Map.of (xx, modifiableMap
(":month-context-abbr", "1"),
+ xx_yy, modifiableMap (":parent",
"xx")));
+
+ var data2 = Map.of (xx, modifiableMap (":month-context-abbr",
"1", ":month-standalone-abbr", "2"),
+ xx_yy, modifiableMap (":month-context-abbr",
"1", ":month-standalone-abbr", "2"));
+
+ removeUnnecessaryLocaleData (data2, xx_yy);
+ assertEquals (data2, Map.of (xx, modifiableMap
(":month-context-abbr", "1", ":month-standalone-abbr", "2"),
+ xx_yy, modifiableMap (":parent",
"xx")));
+
+ var data3 = Map.of (xx, modifiableMap (":month-context-abbr",
"1", ":month-standalone-abbr", "2"),
+ xx_yy, modifiableMap (":month-context-abbr",
"1", ":month-standalone-abbr", "3"));
+
+ removeUnnecessaryLocaleData (data3, xx_yy);
+ assertEquals (data3, Map.of (xx, modifiableMap
(":month-context-abbr", "1", ":month-standalone-abbr", "2"),
+ xx_yy, modifiableMap (":parent",
"xx", ":month-standalone-abbr", "3")));
+
+ var data4 = Map.of (xx, modifiableMap
(":month-standalone-abbr", "2"),
+ xx_yy, modifiableMap (":month-context-abbr",
"1", ":month-standalone-abbr", "2"));
+
+ removeUnnecessaryLocaleData (data4, xx_yy);
+ assertEquals (data4, Map.of (xx, modifiableMap
(":month-standalone-abbr", "2"),
+ xx_yy, modifiableMap (":parent",
"xx", ":month-context-abbr", "1", ":month-standalone-abbr", "2")));
+ }
+
+
+ protected Map <String, String> modifiableMap (String...
key_value_pairs)
+ {
+ var map = new LinkedHashMap <String, String> ();
+ for (int k = 0; k < key_value_pairs.length; k += 2)
+ map.put (key_value_pairs[k], key_value_pairs[k + 1]);
+
+ return map;
+ }
+
+ protected void assertEquals (Object actual, Object expected)
+ {
+ if (!Objects.equals (actual, expected))
+ throw new Error (String.format ("self-test has failed:\n
expected: %s\n but was: %s", expected, actual));
+ }
+
+
+ public static void run () throws Exception
+ {
+ var me = new SelfTests ();
+ for (var method : me.getClass ().getDeclaredMethods ()) {
+ if (method.getName ().startsWith ("test") &&
method.getParameterCount () == 0 && !Modifier.isStatic (method.getModifiers ()))
+ method.invoke (me);
+ }
+ }
+ }
}