1 package org.unicode.cldr.tool;
2 
3 import java.io.File;
4 import java.util.EnumSet;
5 import java.util.LinkedHashMap;
6 import java.util.LinkedHashSet;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
10 import java.util.TreeSet;
11 
12 import org.unicode.cldr.util.CLDRPaths;
13 import org.unicode.cldr.util.SupplementalDataInfo;
14 
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.collect.Lists;
17 import com.ibm.icu.impl.locale.XCldrStub.ImmutableMap;
18 import com.ibm.icu.util.VersionInfo;
19 
20 /**
21  * Enums that should exactly match what is in cldr-archive; eg, v2_0_1 means that there is a folder "cldr-2.0.1"
22  * @author markdavis
23  *
24  */
25 // TODO compute the VersionInfo for each at creation time, and stash as field.
26 public enum CldrVersion {
27     unknown,
28     v1_1_1, v1_2, v1_3, v1_4_1, v1_5_1, v1_6_1, v1_7_2, v1_8_1, v1_9_1, v2_0_1,
29     v21_0, v22_1, v23_1, v24_0, v25_0, v26_0, v27_0, v28_0, v29_0, v30_0, v31_0, v32_0, v33_0, v33_1, v34_0,
30     v35_0, v35_1, v36_0, v36_1, v37_0,
31     trunk;
32 
33     private final String baseDirectory;
34     private final String dotName;
35     private final VersionInfo versionInfo;
36 
37     /**
38      * Get the closest available version (successively dropping lower-significance values)
39      * We do this because the archive might contain a dot-dot version
40      * but have a folder called by the round(er) version number.
41      */
from(VersionInfo versionInfo)42     public static CldrVersion from(VersionInfo versionInfo) {
43         if (versionInfo == null) {
44             return unknown;
45         }
46         while (true) {
47             CldrVersion result = versionInfoToCldrVersion.get(versionInfo);
48             if (result != null) {
49                 return result;
50             }
51             versionInfo = versionInfo.getMilli() != 0 ? VersionInfo.getInstance(versionInfo.getMajor(), versionInfo.getMinor())
52                     : versionInfo.getMinor() != 0 ? VersionInfo.getInstance(versionInfo.getMajor())
53                         : unknown.versionInfo; // will always terminate with unknown.
54         }
55     }
56 
from(String versionString)57     public static CldrVersion from(String versionString) {
58         return valueOf(versionString.charAt(0) < 'A' ? "v" + versionString.replace('.', '_') : versionString);
59     }
60 
getVersionInfo()61     public VersionInfo getVersionInfo() {
62         return versionInfo;
63     }
64     @Override
toString()65     public String toString() {
66         return dotName;
67     }
getBaseDirectory()68     public String getBaseDirectory() {
69         return baseDirectory;
70     }
71 
isOlderThan(CldrVersion other)72     public boolean isOlderThan(CldrVersion other) {
73         return compareTo(other) < 0;
74     }
75 
CldrVersion()76     private CldrVersion() {
77         String oldName = name();
78         if (oldName.charAt(0) == 'v') {
79             dotName = oldName.substring(1).replace('_', '.');
80             versionInfo = VersionInfo.getInstance(dotName);
81             baseDirectory = CLDRPaths.ARCHIVE_DIRECTORY + "cldr-" + toString() + "/";
82         } else {
83             dotName = oldName;
84             baseDirectory = CLDRPaths.BASE_DIRECTORY;
85             SupplementalDataInfo sdi = SupplementalDataInfo.getInstance();
86             versionInfo = "trunk".equals(oldName) ? sdi.getCldrVersion() : VersionInfo.getInstance(0);
87         }
88     }
89 
90     public static final CldrVersion LAST_RELEASE_VERSION = values()[values().length-2];
91     public static final List<CldrVersion> CLDR_VERSIONS_ASCENDING;
92     public static final List<CldrVersion> CLDR_VERSIONS_DESCENDING;
93     private static final Map<VersionInfo, CldrVersion> versionInfoToCldrVersion;
94     static {
95         EnumSet<CldrVersion> temp = EnumSet.allOf(CldrVersion.class);
96         CLDR_VERSIONS_ASCENDING = ImmutableList.copyOf(temp);
97         CLDR_VERSIONS_DESCENDING = ImmutableList.copyOf(Lists.reverse(CLDR_VERSIONS_ASCENDING));
98         Map<VersionInfo, CldrVersion> temp2 = new LinkedHashMap<>();
99         for (CldrVersion item : CLDR_VERSIONS_ASCENDING) {
100             VersionInfo version2 = item.versionInfo;
temp2.put(version2, item)101             temp2.put(version2, item);
102             if (version2.getMilli() != 0) {
103                 version2 = VersionInfo.getInstance(version2.getMajor(), version2.getMinor());
104                 if (!temp2.containsKey(version2)) {
temp2.put(version2, item)105                     temp2.put(version2, item);
106                 }
107             }
108             if (version2.getMinor() != 0) {
109                 version2 = VersionInfo.getInstance(version2.getMajor());
110                 if (!temp2.containsKey(version2)) {
temp2.put(version2, item)111                     temp2.put(version2, item);
112                 }
113             }
114         }
115         versionInfoToCldrVersion = ImmutableMap.copyOf(temp2);
116     }
117 
getPathsForFactory()118     public List<File> getPathsForFactory() {
119         return ImmutableList.copyOf(versionInfo != null && versionInfo.getMajor() < 27
120             ? new File[] { new File(getBaseDirectory() + "common/main/") }
121         : new File[] {
122             new File(getBaseDirectory() + "common/main/"),
123             new File(getBaseDirectory() + "common/annotations/") });
124     }
125 
126     /**
127      * For testing
128      */
checkVersions()129     public static void checkVersions() {
130 //        System.out.println(Arrays.asList(CldrVersion.values()));
131 
132         Set<VersionInfo> allFileVersions = new TreeSet<>();
133         Set<VersionInfo> allTc = new TreeSet<>();
134         Set<VersionInfo> missingEnums = new TreeSet<>();
135         Set<CldrVersion> extraEnums = EnumSet.copyOf(CLDR_VERSIONS_ASCENDING);
136         extraEnums.remove(CldrVersion.trunk);
137         extraEnums.remove(CldrVersion.unknown);
138 
139         for (String subdir : new File(CLDRPaths.ARCHIVE_DIRECTORY).list()) {
140             if (subdir.startsWith("cldr-")) {
141                 String versionString = subdir.substring("cldr-".length());
142                 VersionInfo versionInfo = VersionInfo.getInstance(versionString);
143                 allFileVersions.add(versionInfo);
144                 try {
145                     CldrVersion found = CldrVersion.from(versionString);
146                     extraEnums.remove(found);
147                 } catch (Exception e) {
148                     missingEnums.add(versionInfo);
149                 }
150             }
151         }
152         Set<String> errorMessages = new LinkedHashSet<>();
153 
154         // get versions from ToolConstants
155         for (String tc : ToolConstants.CLDR_VERSIONS) {
156             VersionInfo versionInfo = VersionInfo.getInstance(tc);
157             allTc.add(versionInfo);
158         }
159         // same?
160         if (!allTc.equals(allFileVersions)) {
161             LinkedHashSet<VersionInfo> tcMFile = new LinkedHashSet<>(allTc);
162             tcMFile.removeAll(allFileVersions);
163             if (!tcMFile.isEmpty()) {
164                 errorMessages.add("Extra ToolConstants.CLDR_VERSIONS compared to " + CLDRPaths.ARCHIVE_DIRECTORY + ": " + tcMFile);
165             }
166             LinkedHashSet<VersionInfo> fileMTc = new LinkedHashSet<>(allFileVersions);
167             fileMTc.removeAll(allTc);
168             if (!fileMTc.isEmpty()) {
169                 errorMessages.add("Extra folders in " + CLDRPaths.ARCHIVE_DIRECTORY + " compared to ToolConstants.CLDR_VERSIONS: " + fileMTc);
170             }
171         }
172 
173         // Are there extra enums complete?
174         if (!extraEnums.isEmpty()) {
175             errorMessages.add("Extra enums compared to " + CLDRPaths.ARCHIVE_DIRECTORY + ": " + extraEnums);
176         }
177         // Is the archive complete?
178         if (!missingEnums.isEmpty()) {
179             StringBuilder temp = new StringBuilder();
180             allFileVersions.forEach(v -> temp.append(", v" + v.getVersionString(2, 4).replace('.', '_')));
181             errorMessages.add("Missing enums " + missingEnums + ", should be:\ntrunk" + temp + ", unknown");
182         }
183         if (!errorMessages.isEmpty()) {
184             throw new IllegalArgumentException(errorMessages.toString());
185         }
186     }
187 }