xref: /aosp_15_r20/external/cldr/tools/cldr-code/src/main/java/org/unicode/cldr/tool/CldrVersion.java (revision 912701f9769bb47905792267661f0baf2b85bed5)
1 package org.unicode.cldr.tool;
2 
3 import com.google.common.collect.ImmutableList;
4 import com.google.common.collect.Lists;
5 import com.ibm.icu.impl.locale.XCldrStub.ImmutableMap;
6 import com.ibm.icu.util.VersionInfo;
7 import java.io.File;
8 import java.util.EnumSet;
9 import java.util.LinkedHashMap;
10 import java.util.LinkedHashSet;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14 import java.util.TreeSet;
15 import org.unicode.cldr.util.CLDRFile;
16 import org.unicode.cldr.util.CLDRPaths;
17 
18 /**
19  * Enums that should exactly match what is in cldr-archive; eg, v2_0_1 means that there is a folder
20  * "cldr-2.0.1"
21  *
22  * @author markdavis
23  * @see CheckoutArchive for a tool to automatically populate the cldr-archive
24  */
25 // TODO merge with all other copies of the CLDR version and replace with supplemental metadata,
26 // CLDR-9149
27 public enum CldrVersion {
28     unknown,
29     v1_1,
30     v1_1_1,
31     v1_2,
32     v1_3,
33     v1_4,
34     v1_4_1,
35     v1_5_0_1,
36     v1_5_1,
37     v1_6_1,
38     v1_7_2,
39     v1_8_1,
40     v1_9_1,
41     v2_0_1,
42     v21_0,
43     v22_1,
44     v23_1,
45     v24_0,
46     v25_0,
47     v26_0,
48     v27_0,
49     v28_0,
50     v29_0,
51     v30_0,
52     v31_0,
53     v32_0,
54     v33_0,
55     v33_1,
56     v34_0,
57     v35_0,
58     v35_1,
59     v36_0,
60     v36_1,
61     v37_0,
62     v38_0,
63     v38_1,
64     v39_0,
65     v40_0,
66     v41_0,
67     v42_0,
68     v43_0,
69     v44_0,
70     v44_1,
71     /**
72      * @see CLDRFile#GEN_VERSION
73      */
74     baseline;
75 
76     private final String baseDirectory;
77     private final String dotName;
78     private final VersionInfo versionInfo;
79 
80     /**
81      * Get the closest available version (successively dropping lower-significance values) We do
82      * this because the archive might contain a dot-dot version but have a folder called by the
83      * round(er) version number.
84      */
from(VersionInfo versionInfo)85     public static CldrVersion from(VersionInfo versionInfo) {
86         if (versionInfo == null) {
87             return unknown;
88         }
89         while (true) {
90             CldrVersion result = versionInfoToCldrVersion.get(versionInfo);
91             if (result != null) {
92                 return result;
93             }
94             versionInfo =
95                     versionInfo.getMilli() != 0
96                             ? VersionInfo.getInstance(
97                                     versionInfo.getMajor(), versionInfo.getMinor())
98                             : versionInfo.getMinor() != 0
99                                     ? VersionInfo.getInstance(versionInfo.getMajor())
100                                     : unknown.versionInfo; // will always terminate with unknown.
101         }
102     }
103 
from(String versionString)104     public static CldrVersion from(String versionString) {
105         // treat 'current' as baseline
106         if (versionString.equals(CLDRFile.GEN_VERSION)
107                 || versionString.equals(CLDRFile.GEN_VERSION + ".0")) {
108             return CldrVersion.baseline;
109         }
110         return valueOf(
111                 versionString.charAt(0) < 'A'
112                         ? "v" + versionString.replace('.', '_')
113                         : versionString);
114     }
115 
getVersionInfo()116     public VersionInfo getVersionInfo() {
117         return versionInfo;
118     }
119 
120     @Override
toString()121     public String toString() {
122         return dotName;
123     }
124 
getBaseDirectory()125     public String getBaseDirectory() {
126         return baseDirectory;
127     }
128 
isOlderThan(CldrVersion other)129     public boolean isOlderThan(CldrVersion other) {
130         return compareTo(other) < 0;
131     }
132 
CldrVersion()133     private CldrVersion() {
134         String oldName = name();
135         if (oldName.charAt(0) == 'v') {
136             dotName = oldName.substring(1).replace('_', '.');
137             versionInfo = VersionInfo.getInstance(dotName);
138             baseDirectory = CLDRPaths.ARCHIVE_DIRECTORY + "cldr-" + toString() + "/";
139         } else {
140             dotName = oldName;
141             baseDirectory = CLDRPaths.BASE_DIRECTORY;
142             final VersionInfo cldrVersion = VersionInfo.getInstance(CLDRFile.GEN_VERSION);
143             versionInfo = "baseline".equals(oldName) ? cldrVersion : VersionInfo.getInstance(0);
144         }
145     }
146 
147     public static final CldrVersion LAST_RELEASE_VERSION = values()[values().length - 2];
148     public static final List<CldrVersion> CLDR_VERSIONS_ASCENDING;
149     public static final List<CldrVersion> CLDR_VERSIONS_DESCENDING;
150     private static final Map<VersionInfo, CldrVersion> versionInfoToCldrVersion;
151 
152     static {
153         EnumSet<CldrVersion> temp = EnumSet.allOf(CldrVersion.class);
154         CLDR_VERSIONS_ASCENDING = ImmutableList.copyOf(temp);
155         CLDR_VERSIONS_DESCENDING = ImmutableList.copyOf(Lists.reverse(CLDR_VERSIONS_ASCENDING));
156         Map<VersionInfo, CldrVersion> temp2 = new LinkedHashMap<>();
157         for (CldrVersion item : CLDR_VERSIONS_ASCENDING) {
158             VersionInfo version2 = item.versionInfo;
temp2.put(version2, item)159             temp2.put(version2, item);
160             if (version2.getMilli() != 0) {
161                 version2 = VersionInfo.getInstance(version2.getMajor(), version2.getMinor());
162                 if (!temp2.containsKey(version2)) {
temp2.put(version2, item)163                     temp2.put(version2, item);
164                 }
165             }
166             if (version2.getMinor() != 0) {
167                 version2 = VersionInfo.getInstance(version2.getMajor());
168                 if (!temp2.containsKey(version2)) {
temp2.put(version2, item)169                     temp2.put(version2, item);
170                 }
171             }
172         }
173         versionInfoToCldrVersion = ImmutableMap.copyOf(temp2);
174     }
175 
getPathsForFactory()176     public List<File> getPathsForFactory() {
177         return ImmutableList.copyOf(
178                 versionInfo != null && versionInfo.getMajor() < 27
179                         ? new File[] {new File(getBaseDirectory() + "common/main/")}
180                         : new File[] {
181                             new File(getBaseDirectory() + "common/main/"),
182                             new File(getBaseDirectory() + "common/annotations/")
183                         });
184     }
185 
186     /** For testing */
checkVersions()187     public static void checkVersions() {
188         //        System.out.println(Arrays.asList(CldrVersion.values()));
189 
190         Set<VersionInfo> allFileVersions = new TreeSet<>();
191         Set<VersionInfo> allTc = new TreeSet<>();
192         Set<VersionInfo> missingEnums = new TreeSet<>();
193         Set<CldrVersion> extraEnums = EnumSet.copyOf(CLDR_VERSIONS_ASCENDING);
194         extraEnums.remove(CldrVersion.baseline);
195         extraEnums.remove(CldrVersion.unknown);
196 
197         for (String subdir : new File(CLDRPaths.ARCHIVE_DIRECTORY).list()) {
198             if (subdir.startsWith("cldr-")) {
199                 String versionString = subdir.substring("cldr-".length());
200                 VersionInfo versionInfo = VersionInfo.getInstance(versionString);
201                 allFileVersions.add(versionInfo);
202                 try {
203                     CldrVersion found = CldrVersion.from(versionString);
204                     extraEnums.remove(found);
205                 } catch (Exception e) {
206                     missingEnums.add(versionInfo);
207                 }
208             }
209         }
210         Set<String> errorMessages = new LinkedHashSet<>();
211 
212         // get versions from ToolConstants
213         for (String tc : ToolConstants.CLDR_VERSIONS) {
214             VersionInfo versionInfo = VersionInfo.getInstance(tc);
215             allTc.add(versionInfo);
216         }
217         // same?
218         if (!allTc.equals(allFileVersions)) {
219             LinkedHashSet<VersionInfo> tcMFile = new LinkedHashSet<>(allTc);
220             tcMFile.removeAll(allFileVersions);
221             if (!tcMFile.isEmpty()) {
222                 errorMessages.add(
223                         "Extra ToolConstants.CLDR_VERSIONS compared to "
224                                 + CLDRPaths.ARCHIVE_DIRECTORY
225                                 + ": "
226                                 + tcMFile);
227             }
228             LinkedHashSet<VersionInfo> fileMTc = new LinkedHashSet<>(allFileVersions);
229             fileMTc.removeAll(allTc);
230             if (!fileMTc.isEmpty()) {
231                 errorMessages.add(
232                         "Extra folders in "
233                                 + CLDRPaths.ARCHIVE_DIRECTORY
234                                 + " compared to ToolConstants.CLDR_VERSIONS: "
235                                 + fileMTc);
236             }
237         }
238 
239         // Are there extra enums complete?
240         if (!extraEnums.isEmpty()) {
241             errorMessages.add(
242                     "Extra enums compared to " + CLDRPaths.ARCHIVE_DIRECTORY + ": " + extraEnums);
243         }
244         // Is the archive complete?
245         if (!missingEnums.isEmpty()) {
246             StringBuilder temp = new StringBuilder();
247             allFileVersions.forEach(
248                     v -> temp.append(", v" + v.getVersionString(2, 4).replace('.', '_')));
249             errorMessages.add(
250                     "Missing enums " + missingEnums + ", should be:\ntrunk" + temp + ", unknown");
251         }
252         if (!errorMessages.isEmpty()) {
253             throw new IllegalArgumentException(errorMessages.toString());
254         }
255     }
256 }
257