View Javadoc
1   package org.djunits.locale;
2   
3   import static org.junit.Assert.assertEquals;
4   import static org.junit.Assert.assertTrue;
5   
6   import java.io.File;
7   import java.io.IOException;
8   import java.lang.reflect.InvocationTargetException;
9   import java.lang.reflect.Method;
10  import java.net.URISyntaxException;
11  import java.nio.charset.StandardCharsets;
12  import java.nio.file.Files;
13  import java.nio.file.Path;
14  import java.nio.file.Paths;
15  import java.util.ArrayList;
16  import java.util.HashMap;
17  import java.util.HashSet;
18  import java.util.List;
19  import java.util.Locale;
20  import java.util.Map;
21  import java.util.Set;
22  import java.util.TreeSet;
23  
24  import org.djunits.unit.DurationUnit;
25  import org.junit.Test;
26  
27  /**
28   * Verify that all localizations contain all keys.
29   * <p>
30   * @author <a href="https://www.tudelft.nl/p.knoppers">Peter Knoppers</a>
31   */
32  public class VerifyLocalizations
33  {
34  
35      /**
36       * Replace unicode escapes by the corresponding character. Based on
37       * https://stackoverflow.com/questions/37502058/replace-unicode-escapes-with-the-corresponding-character
38       * @param in String; the input string to process
39       * @return String the processed input string
40       */
41      static String fixUnicodeEscapes(final String in)
42      {
43          StringBuilder result = new StringBuilder();
44          for (int i = 0; i < in.length(); i++)
45          {
46              if (in.length() >= i + 6 && in.substring(i, i + 2).equals("\\u"))
47              {
48                  result.append(Character.toChars(Integer.parseInt(in.substring(i + 2, i + 6), 16)));
49                  i += 5;
50              }
51              else
52              {
53                  result.append(in.charAt(i));
54              }
55          }
56          return result.toString();
57      }
58  
59      /**
60       * Verify that all localizations have the same set of keys as the localeunit.properties file and check that a string using
61       * each of the acceptable unit names is correctly parsed.
62       * @throws IOException when a file could not be read
63       * @throws ClassNotFoundException ...
64       * @throws SecurityException ...
65       * @throws NoSuchMethodException ...
66       * @throws InvocationTargetException ...
67       * @throws IllegalArgumentException ...
68       * @throws IllegalAccessException ...
69       * @throws URISyntaxException ...
70       */
71      @Test
72      public void verifyLocalizations() throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException,
73              IllegalAccessException, IllegalArgumentException, InvocationTargetException, URISyntaxException
74      {
75          String pathToResources = new File(getClass().getResource("/resources/locale").toURI().getPath()).getAbsolutePath();
76          String referenceFileName = "unit_en.properties";
77          // system.out.println(pathToResources + "/" + referenceFileName);
78          // Parse the localeunit.properties file and store all the keys
79          List<String> reference =
80                  Files.readAllLines(Paths.get(pathToResources + "/" + referenceFileName), StandardCharsets.ISO_8859_1);
81          // Replace unicode escapes by the corresponding character
82          for (int index = 0; index < reference.size(); index++)
83          {
84              reference.set(index, fixUnicodeEscapes(reference.get(index)));
85          }
86          Map<String, Integer> keys = new HashMap<>();
87          Map<String, String> values = new HashMap<>();
88          for (int lineNo = 0; lineNo < reference.size(); lineNo++)
89          {
90              String line = reference.get(lineNo);
91              if (line.startsWith("#"))
92              {
93                  continue;
94              }
95              String[] parts = line.split("\\=");
96              assertTrue(referenceFileName + "(" + (lineNo + 1) + ") should contain a equals sign", parts.length > 1);
97              String key = parts[0].trim();
98              keys.put(parts[0].trim(), (lineNo + 1));
99              if (parts.length > 1)
100             {
101                 values.put(key, parts[1]);
102             }
103         }
104         // system.out.println("Collected " + keys.size() + " keys from reference file " + referenceFileName);
105         // system.out.println("Verifying that the valueOf method of each unit correctly parses all writing styles into a Scalar");
106         for (String key : new TreeSet<>(keys.keySet()))
107         {
108             int positionOfPoint = key.indexOf('.');
109             if (positionOfPoint < 0)
110             {
111                 continue;
112             }
113             String className = key.substring(0, positionOfPoint);
114             double testValue = 123.456;
115             String abbreviationsString = values.get(key);
116             String[] abbreviations = abbreviationsString.split("\\|");
117             for (int index = 0; index < abbreviations.length; index++)
118             {
119                 if (index == 1)
120                 {
121                     continue;
122                 }
123                 String input = testValue + " " + abbreviations[index].trim();
124                 // System.out.print(String.format("%-30s: %-20s", key, input));
125                 Class<?> c = Class.forName("org.djunits.value.vdouble.scalar." + className);
126                 Method valueOf = c.getMethod("valueOf", String.class);
127                 Object result = valueOf.invoke(null, input);
128                 // system.out.println(" got parsed into " + result);
129             }
130         }
131         List<Path> paths = new ArrayList<>();
132         Files.list(new File(pathToResources).toPath()).forEach(path -> paths.add(path));
133         for (Path path : paths)
134         {
135             // System.out.println(path);
136             if (path.getFileName().toString().startsWith("unit_")
137                     && path.getFileName().toString().endsWith(".properties"))
138             {
139                 // system.out.println("Verifying locale file " + path.getFileName().toString());
140                 Set<String> missingKeys = new TreeSet<>(keys.keySet());
141                 Set<String> foundKeys = new HashSet<>();
142                 int lineNo = 0;
143                 int errors = 0;
144                 for (String line : Files.readAllLines(path, StandardCharsets.ISO_8859_1))
145                 {
146                     lineNo++;
147                     line = fixUnicodeEscapes(line);
148                     if (line.startsWith("#"))
149                     {
150                         continue;
151                     }
152                     String[] parts = line.split("\\=");
153                     if (parts.length < 2)
154                     {
155                         System.err.println(path.getFileName() + "(" + (lineNo) + ") does not contain an equals sign");
156                         errors++;
157                         continue;
158                     }
159                     String key = parts[0].trim();
160                     if (!keys.containsKey(key))
161                     {
162                         System.err.println(path.getFileName() + "(" + lineNo + "): key " + key + " is not a valid key");
163                         errors++;
164                     }
165                     if (foundKeys.contains(key))
166                     {
167                         System.err.println(path.getFileName() + "(" + lineNo + "): duplicate key " + key);
168                         errors++;
169                     }
170                     missingKeys.remove(key);
171                     foundKeys.add(key);
172                 }
173                 for (String key : missingKeys)
174                 {
175                     System.err.println("file " + path.getFileName() + " misses key " + key);
176                     errors++;
177                 }
178                 assertEquals("No errors in file " + path.getFileName(), 0, errors);
179             }
180         }
181     }
182 
183     
184     /**
185      * Check that all UnitSystems have valid a nameKey and a valid abbreviationKey and test those keys in all available
186      * localizations.
187      * @throws URISyntaxException on error
188      */
189     @Test
190     public final void checkUnitSystemsLocale() throws URISyntaxException
191     {
192         Locale.setDefault(Locale.US);
193         assertEquals("Duration", DurationUnit.BASE.getLocalizedName());
194         assertEquals("h", DurationUnit.HOUR.getLocalizedDisplayAbbreviation());
195         assertEquals("hour", DurationUnit.HOUR.getLocalizedTextualAbbreviation());
196         Set<String> localizedAbbreviationsEN = DurationUnit.HOUR.getLocalizedAbbreviations();
197         assertTrue(localizedAbbreviationsEN.contains("h"));
198         Locale.setDefault(new Locale("nl", "NL"));
199         assertEquals("Tijdsduur", DurationUnit.BASE.getLocalizedName());
200         assertEquals("u", DurationUnit.HOUR.getLocalizedDisplayAbbreviation());
201         assertEquals("uur", DurationUnit.HOUR.getLocalizedTextualAbbreviation());
202         Set<String> localizedAbbreviationsNL = DurationUnit.HOUR.getLocalizedAbbreviations();
203         assertTrue(localizedAbbreviationsNL.contains("u"));
204     }
205 
206 }