package com.limegroup.gnutella.i18n;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* @author Admin
*/
public class CountPercent {
private static final int ACTION_STATISTICS = 0;
private static final int ACTION_HTML = 1;
private static final int ACTION_CHECK = 2;
private static final int ACTION_UPDATE = 3;
private static final int ACTION_RELEASE = 4;
private static final int ACTION_NSIS = 5;
private static final double RELEASE_PERCENTAGE = .65;
/**
* Launched from the console with command-line parameters. Usage: java
* CountPercent [html|check|update [<code>]|release]
* @param args a possibly empty array of command-line parameters.
* @throws IOException
*/
public static void main(String[] args) throws java.io.IOException {
final int action;
String code = null;
if (args != null && args.length > 0) {
if (args[0].equals("html")) {
action = ACTION_HTML;
} else if (args[0].equals("check")) {
action = ACTION_CHECK;
} else if (args[0].equals("update")) {
action = ACTION_UPDATE;
if (args.length > 1)
code = args[1];
} else if (args[0].equals("release")) {
action = ACTION_RELEASE;
} else if (args[0].equals("nsis")) {
action = ACTION_NSIS;
} else {
System.err
.println("Usage: java CountPercent [html|check|update [<code>]|release|nsis]");
return;
}
} else
action = ACTION_STATISTICS;
new CountPercent(action, code);
}
private final DateFormat df;
private final NumberFormat rc;
private final NumberFormat pc;
private final Map/* <String code, LanguageInfo li> */langs;
private final Set/* <String key> */basicKeys, advancedKeys;
private final int basicTotal;
/**
* @param action
* @param code
* @throws IOException
*/
CountPercent(int action, String code) throws java.io.IOException {
df = DateFormat.getDateInstance(DateFormat.LONG, Locale.US);
rc = NumberFormat.getNumberInstance(Locale.US);
rc.setMinimumIntegerDigits(4);
rc.setMaximumIntegerDigits(4);
rc.setGroupingUsed(false);
pc = NumberFormat.getPercentInstance(Locale.US);
pc.setMinimumFractionDigits(2);
pc.setMaximumFractionDigits(2);
pc.setMaximumIntegerDigits(3);
File root = new File(".");
LanguageLoader loader = new LanguageLoader(root);
Properties defaultProps = loader.getDefaultProperties();
advancedKeys = loader.getAdvancedKeys();
defaultProps.keySet().removeAll(advancedKeys);
basicKeys = defaultProps.keySet();
basicTotal = basicKeys.size();
langs = loader.loadLanguages();
switch (action) {
case ACTION_CHECK:
checkBadKeys();
break;
case ACTION_STATISTICS:
loader.extendVariantLanguages();
loader.retainKeys(basicKeys);
pc.setMinimumIntegerDigits(3);
printStatistics();
break;
case ACTION_HTML:
loader.extendVariantLanguages();
loader.retainKeys(basicKeys);
HTMLOutput html = new HTMLOutput(df, pc, langs, basicTotal);
html.printHTML(System.out);
break;
case ACTION_RELEASE:
// release does an update, ensuring bad keys are gone
// & native2ascii is done.
case ACTION_NSIS:
// nsis does an update too.
case ACTION_UPDATE:
loader.extendVariantLanguages();
Set validKeys = new HashSet();
validKeys.addAll(basicKeys);
validKeys.addAll(advancedKeys);
loader.retainKeys(validKeys);
List lines = loader.getEnglishLines();
LanguageUpdater updater = new LanguageUpdater(root, langs, lines);
if (action == ACTION_RELEASE || action == ACTION_NSIS)
updater.setSilent(true);
if (code == null)
updater.updateAllLanguages();
else {
LanguageInfo info = (LanguageInfo) langs.get(code);
updater.updateLanguage(info);
}
if (action == ACTION_RELEASE) {
loader.retainKeys(basicKeys);
release(root);
} else if (action == ACTION_NSIS) {
loader.retainKeys(basicKeys);
nsis();
}
break;
}
}
/**
* Check and list extra or badly names names found in resources. Use the
* default (English) basic and extended resource keys.
*/
private void checkBadKeys() {
System.out.println("List of extra or badly named resource keys:");
System.out.println("-------------------------------------------");
for (Iterator i = langs.entrySet().iterator(); i.hasNext();) {
final Map.Entry entry = (Map.Entry) i.next();
final String code = (String) entry.getKey();
final LanguageInfo li = (LanguageInfo) entry.getValue();
final Properties props = li.getProperties();
props.keySet().removeAll(basicKeys);
props.keySet().removeAll(advancedKeys);
if (props.size() != 0) {
System.out.println("(" + code + ") " + li.getName() + ": "
+ li.getFileName());
props.list(System.out);
System.out
.println("-------------------------------------------");
}
}
}
/**
* Prints statistics about the number of translated resources.
*/
private void printStatistics() {
System.out.println("Total Number of Resources: " + basicTotal);
System.out.println("---------------------------------");
System.out.println();
for (Iterator i = langs.entrySet().iterator(); i.hasNext();) {
final Map.Entry entry = (Map.Entry) i.next();
final String code = (String) entry.getKey();
final LanguageInfo li = (LanguageInfo) entry.getValue();
final Properties props = li.getProperties();
final int count = props.size();
final double percentage = (double) count / (double) basicTotal;
System.out.print("(" + code + ") " + pc.format(percentage)
+ ", count: " + rc.format(count) + " [" + li.getName()
+ ": ");
try {
final byte[] langName = li.toString().getBytes("UTF-8");
System.out.write(langName, 0, langName.length);
} catch (java.io.UnsupportedEncodingException uee) {
// shouldn't occur
}
System.out.println("]");
}
}
/**
* Releases the properties.
*/
private void release(File root) {
// First gather statistics on which languages have a suitable %
// translated.
List validLangs = new LinkedList();
for (Iterator i = langs.values().iterator(); i.hasNext();) {
LanguageInfo li = (LanguageInfo) i.next();
int count = li.getProperties().size();
double percentage = (double) count / (double) basicTotal;
if (percentage >= RELEASE_PERCENTAGE)
validLangs.add(li);
}
// Now that we've got a list of valid languages, go through
// and copy'm to a release dir.
File release = new File(root, "release");
deleteAll(release);
copy(root, release, new ReleaseFilter(validLangs));
}
/**
* Lists all the languages that are of release-quality & have an NSIS name.
*/
private void nsis() {
System.out.println("English");
for (Iterator i = langs.values().iterator(); i.hasNext();) {
LanguageInfo li = (LanguageInfo) i.next();
int count = li.getProperties().size();
double percentage = (double) count / (double) basicTotal;
if (percentage >= RELEASE_PERCENTAGE) {
String name = li.getNSISName();
if (!name.equals(""))
System.out.println(name);
}
}
}
/**
* Recursively copies all files in root to dir that match Filter.
*/
private void copy(File root, File dir, FileFilter filter) {
File[] files = root.listFiles(filter);
for (int i = 0; i < files.length; i++) {
File f = files[i];
if (f.isDirectory())
copy(f, new File(dir, f.getName()), filter);
else
copy(f, dir);
}
}
/**
* Recursively deletes all files in a directory.
*/
private void deleteAll(File f) {
if (f.isDirectory()) {
File[] files = f.listFiles();
for (int i = 0; i < files.length; i++)
deleteAll(files[i]);
}
f.delete();
}
/**
* Copies file to dir, ignoring any lines that are comments.
*/
private void copy(File src, File dst) {
dst.mkdirs();
dst = new File(dst, src.getName());
BufferedReader reader = null;
BufferedWriter writer = null;
try {
reader = new BufferedReader(new InputStreamReader(
new FileInputStream(src), "ISO-8859-1"));
writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(dst), "ISO-8859-1"));
String read;
while ((read = reader.readLine()) != null) {
Line line = new Line(read);
if (line.isComment())
continue;
writer.write(read);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
}
if (writer != null) {
try {
writer.flush();
} catch (IOException e) {
}
try {
writer.close();
} catch (IOException e) {
}
}
}
}
/**
* Filter for releasing files.
*/
private static class ReleaseFilter implements FileFilter {
/**
* Comment for <code>validLangs</code>
*/
final List validLangs;
/**
* @param valid
*/
ReleaseFilter(List valid) {
validLangs = valid;
}
/**
* @see java.io.FileFilter#accept(java.io.File)
*/
public boolean accept(File f) {
if (f.isDirectory())
return true;
String name = f.getName();
if (!name.endsWith(".properties"))
return false;
int idxU;
if ((idxU = name.indexOf('_')) == -1)
return true; // base resource.
String code = name.substring(idxU + 1, name.indexOf("."));
if (code.equals("en")) // always valid.
return true;
// check to see if the code is in the list of valid codes.
for (Iterator i = validLangs.iterator(); i.hasNext();) {
LanguageInfo li = (LanguageInfo) i.next();
// if its the base of a variant or the variant itself,
// accept it. (need bases so the variant works.)
if (code.equals(li.getBaseCode()) || code.equals(li.getCode()))
return true;
}
return false;
}
}
}