/* LanguageTool, a natural language style checker * Copyright (C) 2005 Daniel Naber (http://www.danielnaber.de) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA */ package tools.ltdiff; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Scanner; /** * Generates an HTML report of added, deleted and modified rules between versions of LanguageTool. * See ltdiff.bash. * @author Markus Brenneis */ class VersionDiffGenerator { public static void main(String[] args) throws IOException { final VersionDiffGenerator generator = new VersionDiffGenerator(); generator.makeDiff(args[0]); } private void makeDiff(String lang) throws IOException { final List<Rule> oldRules = new ArrayList<Rule>(); // rules in old grammar.xml final List<Rule> newRules = new ArrayList<Rule>(); // rules in new grammar.xml final List<Rule> modifiedRules = new ArrayList<Rule>(); for (int i = 0; i < 2; i++) { final List<Rule> rules; if (i == 0) { rules = oldRules; } else { rules = newRules; } final Scanner scanner = new Scanner(new FileReader(i == 0 ? "tools/ltdiff/old" : "tools/ltdiff/new")); Rule r = new Rule(); // loop through all lines while (scanner.hasNextLine()) { String line = scanner.nextLine(); if (line.contains("id=\"") && line.contains("rule")) { if (!line.contains("name=\"")) { // merge with the following line if the name is there (e.g. sk) line += scanner.nextLine(); } if (r.numberOfExamples() > 0) { rules.add(r); r = new Rule(); } r.id = line; r.name = line; r.id = r.id.replaceAll(".*id=\"","").replaceAll("\".*",""); r.name = r.name.replaceAll(".*name=\"","").replaceAll("\".*",""); for (Rule rule : rules) { // ensure that the name is unique if (r.name.equals(rule.name)) { r.name += " "; } } } else if (line.contains("type=\"correct\"")) { while (!line.contains("</example>")) { // merge with the following line(s) if the example continues there line += scanner.nextLine(); } r.correct.add(line.replaceAll("marker","b").replaceAll(".*<example.*?>","").replaceAll("</example>.*","")); } else if (line.contains("type=\"incorrect\"")) { while (!line.contains("</example>")) { line += scanner.nextLine(); } r.incorrect.add(line.replaceAll("marker","b").replaceAll(".*<example.*?>","").replaceAll("</example>.*","")); } } // while(readLine) scanner.close(); } // sort rules by name Collections.sort(oldRules); Collections.sort(newRules); // create html file containing the tr elements final FileWriter fileWriter = new FileWriter("changes_" + lang + ".html"); final BufferedWriter out = new BufferedWriter(fileWriter); for (Rule newRule1 : newRules) { boolean found = false; for (int j = 0; j < oldRules.size() && !found; j++) { if (newRule1.id.equals(oldRules.get(j).id) || newRule1.name.equals(oldRules.get(j).name)) { found = true; if (newRule1.numberOfExamples() > oldRules.get(j).numberOfExamples()) { // if the new rules has more examples, it is considered to be improved final Rule r = newRule1; for (int k = 0; k < r.correct.size(); k++) { // remove examples which already exist in old rule for (int l = 0; l < oldRules.get(j).correct.size() && r.correct.size()>0; l++) { if (r.correct.get(k).equals(oldRules.get(j).correct.get(l))) { r.correct.remove(k); if (k > 0) k--; } // if examples equal } // for each old correct example } // for each new correct example for (int k = 0; k < r.incorrect.size(); k++) { // remove examples which already exist in old rule for (int l = 0; l < oldRules.get(j).incorrect.size() && r.incorrect.size()>0; l++) { if (r.incorrect.get(k).equals(oldRules.get(j).incorrect.get(l))) { r.incorrect.remove(k); if (k > 0) k--; } // if examples equal } // for each old incorrect example } // for each new incorrect example modifiedRules.add(r); } // if new rules has more examples } // if new rule is not new } // for each old rule if (!found) { out.write("<tr class=\"new\"><td>4NEWRULE</td><td>" + newRule1.name + newRule1.getExamples(false) + "</td></tr>\n"); } } // for each new rule for (Rule modifiedRule : modifiedRules) { out.write("<tr class=\"modified\"><td>6IMPROVEDRULE</td><td>" + modifiedRule.name + modifiedRule.getExamples(true) + "</td></tr>\n"); } for (Rule oldRule : oldRules) { boolean found = false; for (Rule newRule : newRules) { if (newRule.id.equals(oldRule.id) || newRule.name.equals(oldRule.name)) { found = true; } } if (!found && !oldRule.name.contains("<")) { out.write("<tr class=\"removed\"><td>5REMOVEDRULE</td><td>" + oldRule.name + "</td></tr>\n"); } } out.close(); } class Rule implements Comparable<Rule> { private final List<String> correct = new ArrayList<String>(); private final List<String> incorrect = new ArrayList<String>(); private String name = ""; private String id; int numberOfExamples() { return correct.size() + incorrect.size(); } String getExamples(boolean all) { String s = "<div>"; for (String anIncorrect : incorrect) { s += "<span>7FINDERR</span>" + anIncorrect + "<br/>"; } if (all) { for (String aCorrect : correct) { s += "<span>8FINDNOTERR</span>" + aCorrect + "<br/>"; } } s = s.substring(0, s.length() - 5) + "</div>"; return s; } @Override public int compareTo(Rule r) { return this.name.compareTo(r.name); } } }