1 import java.util.Vector; 2 import java.util.List; 3 import java.util.Iterator; 4 import java.util.Arrays; 5 import java.io.File; 6 import java.io.FileWriter; 7 import java.io.BufferedWriter; 8 import java.io.PrintWriter; 9 import java.io.IOException; 10 // JDOM classes used for document representation 11 import org.jdom.Document; 12 import org.jdom.Element; 13 import org.jdom.Attribute; 14 import org.jdom.JDOMException; 15 import org.jdom.input.SAXBuilder; 16 17 /** 18 * Converts the matrix.xml file to a matrix.texi file, suitable for 19 * being included from gettext's nls.texi. 20 * 21 * @author Bruno Haible 22 */ 23 public class Matrix { 24 25 public static class PoFile { 26 String domain; 27 String team; 28 int percentage; PoFile(String domain, String team, int percentage)29 public PoFile (String domain, String team, int percentage) { 30 this.domain = domain; 31 this.team = team; 32 this.percentage = percentage; 33 } 34 } 35 36 public static class Data { 37 List /* of String */ domains = new Vector(); 38 List /* of String */ teams = new Vector(); 39 List /* of PoFile */ po_files = new Vector(); 40 } 41 42 public static final int FALSE = 0; 43 public static final int TRUE = 1; 44 public static final int EXTERNAL = 2; 45 spaces(PrintWriter stream, int n)46 public static void spaces (PrintWriter stream, int n) { 47 for (int i = n; i > 0; i--) 48 stream.print(' '); 49 } 50 main(String[] args)51 public static void main (String[] args) { 52 Data data = new Data(); 53 54 SAXBuilder builder = new SAXBuilder(/*true*/); // "true" turns on validation 55 Document doc; 56 try { 57 doc = builder.build(new File("matrix.xml")); 58 } catch (IOException e) { 59 e.printStackTrace(); 60 doc = null; 61 System.exit(1); 62 } catch (JDOMException e) { 63 e.printStackTrace(); 64 doc = null; 65 System.exit(1); 66 } 67 Element po_inventory = doc.getRootElement(); 68 { 69 Element domains = po_inventory.getChild("domains"); 70 Iterator i = domains.getChildren("domain").iterator(); 71 while (i.hasNext()) { 72 Element domain = (Element)i.next(); 73 data.domains.add(domain.getAttribute("name").getValue()); 74 } 75 } 76 { 77 Element teams = po_inventory.getChild("teams"); 78 Iterator i = teams.getChildren("team").iterator(); 79 while (i.hasNext()) { 80 Element team = (Element)i.next(); 81 data.teams.add(team.getAttribute("name").getValue()); 82 } 83 } 84 { 85 Element po_files = po_inventory.getChild("PoFiles"); 86 Iterator i = po_files.getChildren("po").iterator(); 87 while (i.hasNext()) { 88 Element po = (Element)i.next(); 89 String value = po.getText(); 90 data.po_files.add( 91 new PoFile( 92 po.getAttribute("domain").getValue(), 93 po.getAttribute("team").getValue(), 94 value.equals("") ? -1 : Integer.parseInt(value))); 95 } 96 } 97 98 // Special treatment of clisp. The percentages are incorrect. 99 if (!data.teams.contains("en")) 100 data.teams.add("en"); 101 data.po_files.add(new PoFile("clisp","en",100)); 102 data.po_files.add(new PoFile("clisp","de",83)); 103 data.po_files.add(new PoFile("clisp","fr",58)); 104 data.po_files.add(new PoFile("clisp","es",54)); 105 data.po_files.add(new PoFile("clisp","nl",57)); 106 data.po_files.add(new PoFile("clisp","ru",74)); 107 108 // Obsolete domains. 109 data.domains.remove("gettext"); 110 for (Iterator i = data.po_files.iterator(); i.hasNext(); ) { 111 PoFile po = (PoFile)i.next(); 112 if (po.domain.equals("gettext")) 113 i.remove(); 114 } 115 116 try { 117 FileWriter f = new FileWriter("matrix.texi"); 118 BufferedWriter bf = new BufferedWriter(f); 119 PrintWriter stream = new PrintWriter(bf); 120 121 String[] domains = (String[])data.domains.toArray(new String[0]); 122 Arrays.sort(domains); 123 String[] teams = (String[])data.teams.toArray(new String[0]); 124 Arrays.sort(teams); 125 int ndomains = domains.length; 126 int nteams = teams.length; 127 128 int[][] matrix = new int[ndomains][]; 129 for (int d = 0; d < ndomains; d++) 130 matrix[d] = new int[nteams]; 131 int[] total_per_domain = new int[ndomains]; 132 int[] total_per_team = new int[nteams]; 133 int total = 0; 134 { 135 Iterator i = data.po_files.iterator(); 136 while (i.hasNext()) { 137 PoFile po = (PoFile)i.next(); 138 if (po.percentage >= 50) { 139 int d = Arrays.binarySearch(domains,po.domain); 140 if (d < 0) 141 throw new Error("didn't find domain \""+po.domain+"\""); 142 int t = Arrays.binarySearch(teams,po.team); 143 if (t < 0) 144 throw new Error("didn't find team \""+po.team+"\""); 145 matrix[d][t] = TRUE; 146 total_per_domain[d]++; 147 total_per_team[t]++; 148 total++; 149 } else if (po.percentage < 0) { 150 int d = Arrays.binarySearch(domains,po.domain); 151 if (d < 0) 152 throw new Error("didn't find domain \""+po.domain+"\""); 153 int t = Arrays.binarySearch(teams,po.team); 154 if (t < 0) { 155 System.err.println(po.domain+": didn't find team \""+po.team+"\""); 156 continue; 157 } 158 matrix[d][t] = EXTERNAL; 159 } 160 } 161 } 162 163 int[] columnwidth = new int[nteams]; 164 for (int t = 0; t < nteams; t++) 165 columnwidth[t] = 166 Math.max(teams[t].length(), 167 Integer.toString(total_per_team[t]).length()); 168 169 // Split into separate tables, to keep 80 column width. 170 int maxwidth = 80 - 21 - 5 - Integer.toString(total).length(); 171 172 // First determine how many groups are needed. 173 int ngroups = 0; 174 { 175 int width = 0, last_team = 0; 176 for (int t = 0; t < nteams; t++) { 177 int newwidth = width + columnwidth[t] + 1; 178 if (newwidth > maxwidth) { 179 last_team = t; 180 ngroups++; 181 width = 0; 182 } 183 width += columnwidth[t] + 1; 184 } 185 if (last_team < nteams) 186 ngroups++; 187 } 188 189 // Then initialize the size of each group. 190 int[][] groups = new int[ngroups][]; 191 { 192 int width = 0, last_team = 0, index = 0; 193 for (int t = 0; t < nteams; t++) { 194 int newwidth = width + columnwidth[t] + 1; 195 if (newwidth > maxwidth) { 196 groups[index++] = new int[] { last_team, t }; 197 last_team = t; 198 width = 0; 199 } 200 width += columnwidth[t] + 1; 201 } 202 if (last_team < nteams) 203 groups[index] = new int[] { last_team, nteams }; 204 } 205 206 stream.println("@example"); 207 for (int group = 0; group < ngroups; group++) { 208 if (group > 0) 209 stream.println(); 210 211 stream.println("@group"); 212 213 if (group == 0) 214 stream.print("Ready PO files "); 215 else 216 stream.print(" "); 217 for (int t = groups[group][0]; t < groups[group][1]; t++) { 218 int i = columnwidth[t]-teams[t].length(); 219 spaces(stream,1+i/2); 220 stream.print(teams[t].replace("@","@@")); 221 spaces(stream,(i+1)/2); 222 } 223 stream.println(); 224 225 stream.print(" +"); 226 for (int t = groups[group][0]; t < groups[group][1]; t++) 227 for (int i = columnwidth[t] + 1; i > 0; i--) 228 stream.print('-'); 229 stream.println("-+"); 230 231 for (int d = 0; d < ndomains; d++) { 232 String domain = domains[d]; 233 if (domain.length() > 18) 234 domain = domain.substring(0, 18-3) + "..."; 235 stream.print(domain); 236 spaces(stream,18 - domain.length() + 1); 237 stream.print('|'); 238 for (int t = groups[group][0]; t < groups[group][1]; t++) { 239 stream.print(' '); 240 if (matrix[d][t] == TRUE) { 241 int i = columnwidth[t]-2; 242 spaces(stream,i/2); 243 stream.print("[]"); 244 spaces(stream,(i+1)/2); 245 } else if (matrix[d][t] == EXTERNAL) { 246 int i = columnwidth[t]-2; 247 spaces(stream,i/2); 248 stream.print("()"); 249 spaces(stream,(i+1)/2); 250 } else { 251 spaces(stream,columnwidth[t]); 252 } 253 } 254 stream.print(' '); 255 stream.print('|'); 256 if (group == ngroups-1) { 257 stream.print(' '); 258 String s = Integer.toString(total_per_domain[d]); 259 spaces(stream,2-s.length()); 260 stream.print(s); 261 } 262 stream.println(); 263 } 264 265 stream.print(" +"); 266 for (int t = groups[group][0]; t < groups[group][1]; t++) 267 for (int i = columnwidth[t] + 1; i > 0; i--) 268 stream.print('-'); 269 stream.println("-+"); 270 271 if (group == ngroups-1) { 272 String s = Integer.toString(nteams); 273 spaces(stream,4-s.length()); 274 stream.print(s); 275 stream.print(" teams "); 276 } else { 277 stream.print(" "); 278 } 279 for (int t = groups[group][0]; t < groups[group][1]; t++) { 280 int i = columnwidth[t]-teams[t].length(); 281 spaces(stream,1+i/2); 282 stream.print(teams[t].replace("@","@@")); 283 spaces(stream,(i+1)/2); 284 } 285 stream.println(); 286 287 if (group == ngroups-1) { 288 String s = Integer.toString(ndomains); 289 spaces(stream,4-s.length()); 290 stream.print(s); 291 stream.print(" domains "); 292 } else { 293 stream.print(" "); 294 } 295 for (int t = groups[group][0]; t < groups[group][1]; t++) { 296 stream.print(' '); 297 String s = Integer.toString(total_per_team[t]); 298 int i = columnwidth[t]-s.length(); 299 int j = (s.length() < 2 ? 1 : 0); 300 spaces(stream,(i+j)/2); 301 stream.print(s); 302 spaces(stream,(i+1-j)/2); 303 } 304 if (group == ngroups-1) { 305 stream.print(' '); 306 stream.print(' '); 307 String s = Integer.toString(total); 308 spaces(stream,3-s.length()); 309 stream.print(s); 310 } 311 stream.println(); 312 313 stream.println("@end group"); 314 } 315 stream.println("@end example"); 316 317 stream.close(); 318 bf.close(); 319 f.close(); 320 } catch (IOException e) { 321 e.printStackTrace(); 322 System.exit(1); 323 } 324 } 325 326 } 327