/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.netbeans.lib.cvsclient.commandLine.command;
import java.io.File;
import java.io.PrintStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ResourceBundle;
import org.netbeans.lib.cvsclient.command.Command;
import org.netbeans.lib.cvsclient.command.FileInfoContainer;
import org.netbeans.lib.cvsclient.command.GlobalOptions;
import org.netbeans.lib.cvsclient.command.annotate.AnnotateCommand;
import org.netbeans.lib.cvsclient.command.annotate.AnnotateInformation;
import org.netbeans.lib.cvsclient.command.annotate.AnnotateLine;
import org.netbeans.lib.cvsclient.commandLine.GetOpt;
import org.netbeans.lib.cvsclient.commandLine.ListenerProvider;
import org.netbeans.lib.cvsclient.event.CVSAdapter;
import org.netbeans.lib.cvsclient.event.CVSListener;
/**
* The locbundlecheck command
*
* @author Milos Kleint
*/
public class locbundlecheck extends CVSAdapter implements CommandProvider {
/**
* A constructor that is used to create the CommandProvider.
*/
public locbundlecheck() {
}
@Override
public String getName() {
return "locbundlecheck"; // NOI18N
}
@Override
public String[] getSynonyms() {
return new String[] { "lbch", "lbcheck" }; // NOI18N
}
@Override
public String getUsage() {
return ResourceBundle.getBundle(CommandProvider.class.getPackage().getName() + ".Bundle").getString("locbundlecheck.usage"); // NOI18N
}
@Override
public void printShortDescription(PrintStream out) {
String msg = ResourceBundle.getBundle(CommandProvider.class.getPackage().getName() + ".Bundle").getString(
"locbundlecheck.shortDescription"); // NOI18N
out.print(msg);
}
@Override
public void printLongDescription(PrintStream out) {
String msg = ResourceBundle.getBundle(CommandProvider.class.getPackage().getName() + ".Bundle").getString(
"locbundlecheck.longDescription"); // NOI18N
out.println(msg);
}
@Override
public Command createCommand(String[] args, int index, GlobalOptions gopt, String workDir) {
LocBundleAnnotateCommand command = new LocBundleAnnotateCommand();
final String getOptString = command.getOptString();
GetOpt go = new GetOpt(args, getOptString + "i:");
int ch = -1;
go.optIndexSet(index);
boolean usagePrint = false;
String arg;
String localization = null;
while ((ch = go.getopt()) != GetOpt.optEOF) {
if (ch == 'i') {
localization = go.optArgGet();
command.setLocalization(localization);
} else {
boolean ok = command.setCVSCommand((char) ch, go.optArgGet());
if (!ok) {
usagePrint = true;
}
}
}
if (usagePrint || localization == null) {
throw new IllegalArgumentException(getUsage());
}
int fileArgsIndex = go.optIndexGet();
// test if we have been passed any file arguments
if (fileArgsIndex < args.length) {
Collection fls = new ArrayList();
// send the arguments as absolute paths
if (workDir == null) {
workDir = System.getProperty("user.dir");
}
command.setWorkDir(workDir);
File workingDir = new File(workDir);
for (int i = fileArgsIndex; i < args.length; i++) {
File fl = new File(workingDir, args[i]);
// System.out.println("file=" + fl);
if (fl.exists() && fl.isDirectory()) {
addFilesInDir(fls, fl, localization);
} else if (fl.exists() && fl.getName().endsWith(".properties")) {
addFiles(fls, fl, localization);
} else {
throw new IllegalArgumentException();
}
}
if (fls.size() > 0) {
File[] fileArgs = new File[fls.size()];
fileArgs = (File[]) fls.toArray(fileArgs);
command.setFiles(fileArgs);
} else {
throw new IllegalArgumentException(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle")
.getString("locbundlecheck.no_file_spec"));
}
}
return command;
}
private static void addFiles(Collection fileList, File origFile, String localization) {
String origPath = origFile.getAbsolutePath();
String enarg = origPath.substring(0, origPath.length() - ".properties".length()) + "_" + localization + ".properties";
// System.out.println("enarg=" + enarg);
File addfl = new File(enarg);
fileList.add(origFile);
if (addfl.exists()) {
fileList.add(addfl);
} else {
// TODO
}
}
private static void addFilesInDir(Collection fileList, File origFile, String localization) {
File[] files = origFile.listFiles();
if (files != null && files.length > 0) {
for (int i = 0; i < files.length; i++) {
if (files[i].exists() && files[i].isDirectory()) {
addFilesInDir(fileList, files[i], localization);
} else if (files[i].exists() && "Bundle.properties".equals(files[i].getName())) {
addFiles(fileList, files[i], localization);
}
}
}
}
private PrintStream out;
private PrintStream err;
private int realEnd = 0;
private HashMap originalBundles;
private HashMap localizedBundles;
private String local;
private String workDir;
/**
* A constructor that is used to create the CVSAdapter.
*/
locbundlecheck(PrintStream stdout, PrintStream stderr, String localization, String workDir) {
out = stdout;
err = stderr;
originalBundles = new HashMap();
localizedBundles = new HashMap();
local = localization;
this.workDir = workDir;
}
@Override
public void fileInfoGenerated(org.netbeans.lib.cvsclient.event.FileInfoEvent e) {
// out.println("annotated " + e.getInfoContainer().getFile());
FileInfoContainer cont = e.getInfoContainer();
if (cont.getFile().getName().indexOf("_" + local) >= 0) {
localizedBundles.put(cont.getFile().getAbsolutePath(), cont);
} else {
originalBundles.put(cont.getFile().getAbsolutePath(), cont);
}
// out.println("orig size=" + originalBundles.keySet().size() + " loc size=" + localizedBundles.keySet().size());
if (realEnd == 2) {
// generate output.
// out.println("generating output....");
generateOutput();
}
}
@Override
public void commandTerminated(org.netbeans.lib.cvsclient.event.TerminationEvent e) {
if (realEnd == 0) {
// now the event is triggered because of the validresponses request
realEnd = 1;
return;
}
realEnd = 2;
// the second time it's the real end. waiting for the last info object to be received.
// out.println("finish=" + e.isError());
}
private void generateOutput() {
Iterator it = originalBundles.keySet().iterator();
while (it.hasNext()) {
String origPath = (String) it.next();
int dotIndex = origPath.lastIndexOf(".");
if (dotIndex < 0) {
throw new IllegalStateException(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle")
.getString("locbundlecheck.illegal_state"));
}
String locPath = origPath.substring(0, dotIndex) + "_" + local + origPath.substring(dotIndex);
// System.out.println("locpath=" + locPath);
AnnotateInformation origInfo = (AnnotateInformation) originalBundles.get(origPath);
AnnotateInformation locInfo = (AnnotateInformation) localizedBundles.get(locPath);
if (locInfo == null) {
out.println(MessageFormat.format(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle")
.getString("locbundlecheck.noLocalizedFile"), new Object[] { origPath }));
continue;
}
// remove from locl bundles to figure out what was removed in the original..
localizedBundles.remove(locPath);
HashMap origPropMap = createPropMap(origInfo);
HashMap locPropMap = createPropMap(locInfo);
String printFile = origPath;
if (origPath.startsWith(workDir)) {
printFile = origPath.substring(workDir.length());
if (printFile.startsWith("/") || printFile.startsWith("\\")) {
printFile = printFile.substring(1);
}
}
out.println(MessageFormat.format(
ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle").getString("locbundlecheck.File"),
new Object[] { printFile }));
Iterator propIt = origPropMap.keySet().iterator();
while (propIt.hasNext()) {
String prop = (String) propIt.next();
AnnotateLine origLine = (AnnotateLine) origPropMap.get(prop);
AnnotateLine locLine = (AnnotateLine) locPropMap.get(prop);
if (locLine == null) {
out.println(MessageFormat.format(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle")
.getString("locbundlecheck.propMissing"), new Object[] { prop }));
continue;
}
// System.out.println("prop=" + prop);
// System.out.println("orig date:" + origLine.getDate());
// System.out.println("loc date:" + locLine.getDate());
if (origLine.getDate().compareTo(locLine.getDate()) > 0) {
out.println(MessageFormat.format(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle")
.getString("locbundlecheck.prop_updated"), new Object[] { prop }));
}
}
}
if (localizedBundles.size() > 0) {
Iterator locIt = localizedBundles.keySet().iterator();
while (locIt.hasNext()) {
String prop = (String) locIt.next();
out.println(MessageFormat.format(ResourceBundle.getBundle("org/netbeans/lib/cvsclient/commandLine/command/Bundle")
.getString("locbundlecheck.prop_removed"), new Object[] { prop }));
}
}
}
private HashMap createPropMap(AnnotateInformation info) {
HashMap propMap = new HashMap();
AnnotateLine line = info.getFirstLine();
while (line != null) {
String content = line.getContent();
if (content.startsWith("#")) {
// ignore commented lines.
line = info.getNextLine();
continue;
}
int index = content.indexOf('=');
if (index > 0) {
String key = content.substring(0, index);
propMap.put(key, line);
} else {
// TODO.. for properties that span across multiple lines, one should take all lines into account
}
line = info.getNextLine();
}
return propMap;
}
private static class LocBundleAnnotateCommand extends AnnotateCommand implements ListenerProvider {
private String loc;
private String workDir;
@Override
public CVSListener createCVSListener(PrintStream stdout, PrintStream stderr) {
return new locbundlecheck(stdout, stderr, loc, workDir);
}
public void setLocalization(String loc) {
this.loc = loc;
}
public void setWorkDir(String dir) {
workDir = dir;
}
}
}