checkstyle passes (again, with newest checkstyle checks)

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@52 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/build-tools/doctool/src/com/google/doctool/Booklet.java b/build-tools/doctool/src/com/google/doctool/Booklet.java
index d8a3b05..e07f30e 100644
--- a/build-tools/doctool/src/com/google/doctool/Booklet.java
+++ b/build-tools/doctool/src/com/google/doctool/Booklet.java
@@ -152,32 +152,48 @@
     return sBooklet;
   }
 
+  private String outputPath;
+
+  private HashSet packagesToGenerate;
+
+  private RootDoc initialRootDoc;
+
+  private String rootDocId;
+
+  private boolean showCode;
+
+  private HashSet standardTagKinds = new HashSet();
+
+  private Stack tagStack = new Stack();
+
+  private PrintWriter pw;
+
   public Booklet() {
     // Set up standard tags (to ignore during tag processing)
     //
-    fStandardTagKinds.add("@see");
-    fStandardTagKinds.add("@serial");
-    fStandardTagKinds.add("@throws");
-    fStandardTagKinds.add("@param");
-    fStandardTagKinds.add("@id");
+    standardTagKinds.add("@see");
+    standardTagKinds.add("@serial");
+    standardTagKinds.add("@throws");
+    standardTagKinds.add("@param");
+    standardTagKinds.add("@id");
   }
 
   private boolean analyzeOptions(String[][] options, DocErrorReporter reporter) {
     for (int i = 0, n = options.length; i < n; ++i) {
       if (options[i][0].equals(OPT_BKOUT)) {
-        fOutputPath = options[i][1];
+        outputPath = options[i][1];
       } else if (options[i][0].equals(OPT_BKDOCPKG)) {
         String[] packages = options[i][1].split(";");
-        fPackagesToGenerate = new HashSet();
+        packagesToGenerate = new HashSet();
         for (int packageIndex = 0; packageIndex < packages.length; ++packageIndex) {
-          fPackagesToGenerate.add(packages[packageIndex]);
+          packagesToGenerate.add(packages[packageIndex]);
         }
       } else if (options[i][0].equals(OPT_BKCODE)) {
-        fShowCode = true;
+        showCode = true;
       }
     }
 
-    if (fOutputPath == null) {
+    if (outputPath == null) {
       reporter.printError("You must specify an output directory with "
           + OPT_BKOUT);
       return false;
@@ -188,12 +204,12 @@
 
   private void begin(String tag) {
     pw.print("<" + tag + ">");
-    fTagStack.push(tag);
+    tagStack.push(tag);
   }
 
   private void begin(String tag, String attr, String value) {
     pw.print("<" + tag + " " + attr + "='" + value + "'>");
-    fTagStack.push(tag);
+    tagStack.push(tag);
   }
 
   private void beginCDATA() {
@@ -322,8 +338,8 @@
       myId = getId(pkgDoc);
       myTitle = pkgDoc.name();
     } else if (doc instanceof RootDoc) {
-      myId = fRootDocId;
-      myTitle = fRootDoc.name();
+      myId = rootDocId;
+      myTitle = initialRootDoc.name();
     } else {
       throw new IllegalStateException(
           "Expected only a member, type, or package");
@@ -406,7 +422,7 @@
   }
 
   private void end() {
-    pw.print("</" + fTagStack.pop() + ">");
+    pw.print("</" + tagStack.pop() + ">");
   }
 
   private void endCDATA() {
@@ -455,6 +471,19 @@
     return null;
   }
 
+  private ExtraClassResolver getExtraClassResolver(Tag tag) {
+
+    if (tag.holder() instanceof PackageDoc) {
+      return new ExtraClassResolver() {
+        public ClassDoc findClass(String className) {
+          return initialRootDoc.classNamed(className);
+        }
+      };
+    }
+
+    return null;
+  }
+
   private String getId(ClassDoc classDoc) {
     return classDoc.qualifiedName();
   }
@@ -502,7 +531,7 @@
         return classDoc.containingPackage();
       }
     } else if (doc instanceof PackageDoc) {
-      return fRootDoc;
+      return initialRootDoc;
     } else if (doc instanceof RootDoc) {
       return null;
     } else {
@@ -694,7 +723,7 @@
 
     // Maybe show code
     //
-    if (fShowCode) {
+    if (showCode) {
       SourcePosition pos = memberDoc.position();
       if (pos != null) {
         beginln("code");
@@ -775,31 +804,31 @@
 
   private void process(RootDoc rootDoc) {
     try {
-      fRootDoc = rootDoc;
-      File outputFile = new File(fOutputPath);
+      initialRootDoc = rootDoc;
+      File outputFile = new File(outputPath);
       outputFile.getParentFile().mkdirs();
       FileWriter fw = new FileWriter(outputFile);
       pw = new PrintWriter(fw, true);
 
       beginln("booklet");
 
-      fRootDocId = "";
+      rootDocId = "";
       String title = "";
       Tag[] idTags = rootDoc.tags("@id");
       if (idTags.length > 0) {
-        fRootDocId = idTags[0].text();
+        rootDocId = idTags[0].text();
       } else {
-        fRootDoc.printWarning("Expecting @id in an overview html doc; see -overview");
+        initialRootDoc.printWarning("Expecting @id in an overview html doc; see -overview");
       }
 
       Tag[] titleTags = rootDoc.tags("@title");
       if (titleTags.length > 0) {
         title = titleTags[0].text();
       } else {
-        fRootDoc.printWarning("Expecting @title in an overview html doc; see -overview");
+        initialRootDoc.printWarning("Expecting @title in an overview html doc; see -overview");
       }
 
-      emitIdentity(fRootDocId, title);
+      emitIdentity(rootDocId, title);
       emitLocation(rootDoc);
       emitDescription(null, rootDoc, rootDoc.firstSentenceTags(),
           rootDoc.inlineTags());
@@ -808,7 +837,7 @@
       // Create a list of the packages to iterate over.
       //
       HashSet packageNames = new HashSet();
-      ClassDoc[] cda = fRootDoc.classes();
+      ClassDoc[] cda = initialRootDoc.classes();
       for (int i = 0; i < cda.length; i++) {
         ClassDoc cd = cda[i];
         // Only top-level classes matter.
@@ -826,9 +855,9 @@
         // Only process this package if either no "docpkg" is set, or it is
         // included.
         //
-        if (fPackagesToGenerate == null
-            || fPackagesToGenerate.contains(packageName)) {
-          PackageDoc pd = fRootDoc.packageNamed(packageName);
+        if (packagesToGenerate == null
+            || packagesToGenerate.contains(packageName)) {
+          PackageDoc pd = initialRootDoc.packageNamed(packageName);
           process(pd);
         }
       }
@@ -836,7 +865,7 @@
       endln();
     } catch (Exception e) {
       e.printStackTrace();
-      fRootDoc.printError("Caught exception: " + e.toString());
+      initialRootDoc.printError("Caught exception: " + e.toString());
     }
   }
 
@@ -909,7 +938,7 @@
       text(label != null ? label.trim() : "");
       end();
     } else {
-      fRootDoc.printWarning(seeTag.position(),
+      initialRootDoc.printWarning(seeTag.position(),
           "Unverifiable cross-reference to '" + seeTag.text() + "'");
       // The link probably won't work, but emit it anyway.
       begin("link");
@@ -950,7 +979,7 @@
         begin("pre", "class", "code");
         text(contents);
         endln();
-      } else if (!fStandardTagKinds.contains(tag.name())) {
+      } else if (!standardTagKinds.contains(tag.name())) {
         // Custom tag; pass it along other tag.
         //
         String tagName = tag.name().substring(1);
@@ -961,29 +990,7 @@
     }
   }
 
-  private ExtraClassResolver getExtraClassResolver(Tag tag) {
-
-    if (tag.holder() instanceof PackageDoc) {
-      return new ExtraClassResolver() {
-        public ClassDoc findClass(String className) {
-          return fRootDoc.classNamed(className);
-        }
-      };
-    }
-
-    return null;
-  }
-
   private void text(String s) {
     pw.print(s);
   }
-
-  private String fOutputPath;
-  private HashSet fPackagesToGenerate;
-  private RootDoc fRootDoc;
-  private String fRootDocId;
-  private boolean fShowCode;
-  private HashSet fStandardTagKinds = new HashSet();
-  private Stack fTagStack = new Stack();
-  private PrintWriter pw;
 }
diff --git a/build-tools/doctool/src/com/google/doctool/DocTool.java b/build-tools/doctool/src/com/google/doctool/DocTool.java
index be36083..94bf9bf 100644
--- a/build-tools/doctool/src/com/google/doctool/DocTool.java
+++ b/build-tools/doctool/src/com/google/doctool/DocTool.java
@@ -60,8 +60,10 @@
 
   private class ImageCopier extends DefaultHandler {
 
+    private final File htmlDir;
+
     private ImageCopier(File htmlDir) {
-      fHtmlDir = htmlDir;
+      this.htmlDir = htmlDir;
     }
 
     public void startElement(String uri, String localName, String qName,
@@ -70,14 +72,14 @@
         String imgSrc = attributes.getValue("src");
         if (imgSrc != null) {
           boolean found = false;
-          for (int i = 0, n = fImagePath.length; i < n; ++i) {
-            File dir = fImagePath[i];
+          for (int i = 0, n = imagePath.length; i < n; ++i) {
+            File dir = imagePath[i];
             File inFile = new File(dir, imgSrc);
             if (inFile.exists()) {
               // Copy it over.
               //
               found = true;
-              File outFile = new File(fHtmlDir, imgSrc);
+              File outFile = new File(htmlDir, imgSrc);
 
               if (outFile.exists()) {
                 if (outFile.lastModified() > inFile.lastModified()) {
@@ -87,24 +89,21 @@
               } else {
                 File outFileDir = outFile.getParentFile();
                 if (!outFileDir.exists() && !outFileDir.mkdirs()) {
-                  fErr.println("Unable to create image output dir "
-                      + outFileDir);
+                  err.println("Unable to create image output dir " + outFileDir);
                   break;
                 }
               }
               if (!copyFile(inFile, outFile)) {
-                fErr.println("Unable to copy image file " + outFile);
+                err.println("Unable to copy image file " + outFile);
               }
             }
           }
           if (!found) {
-            fErr.println("Unable to find image " + imgSrc);
+            err.println("Unable to find image " + imgSrc);
           }
         }
       }
     }
-
-    private final File fHtmlDir;
   }
 
   private static final Pattern IN_XML_FILENAME = Pattern.compile(
@@ -252,23 +251,49 @@
     return false;
   }
 
+  private final File[] classPath;
+
+  private final String[] packages;
+
+  private final PrintStream err;
+
+  private final String base;
+
+  private final String fileType;
+
+  private final boolean generateHtml;
+
+  private final String[] htmlFileBases;
+
+  private final File[] imagePath;
+
+  private final PrintStream out;
+
+  private final File outDir;
+
+  private final File overviewFile;
+
+  private final File[] sourcePath;
+
+  private final String title;
+
   DocTool(PrintStream out, PrintStream err, File outDir, boolean generateHtml,
       String title, String[] htmlFileBases, String fileType, String fileBase,
       File overviewFile, File[] sourcePath, File[] classPath,
       String[] packages, File[] imagePath) {
-    fOut = out;
-    fErr = err;
-    fOutDir = outDir;
-    fGenerateHtml = generateHtml;
-    fFileBase = fileBase;
-    fFileType = fileType;
-    fOverviewFile = overviewFile;
-    fSourcePath = sourcePath;
-    fClassPath = classPath;
-    fPackages = packages;
-    fImagePath = imagePath;
-    fTitle = title;
-    fHtmlFileBases = (String[]) htmlFileBases.clone();
+    this.out = out;
+    this.err = err;
+    this.outDir = outDir;
+    this.generateHtml = generateHtml;
+    this.base = fileBase;
+    this.fileType = fileType;
+    this.overviewFile = overviewFile;
+    this.sourcePath = sourcePath;
+    this.classPath = classPath;
+    this.packages = packages;
+    this.imagePath = imagePath;
+    this.title = title;
+    this.htmlFileBases = (String[]) htmlFileBases.clone();
   }
 
   public boolean copyFile(File in, File out) {
@@ -296,7 +321,7 @@
       try {
         is.close();
       } catch (IOException e) {
-        e.printStackTrace(fErr);
+        e.printStackTrace(err);
       }
     }
   }
@@ -306,7 +331,7 @@
       try {
         os.close();
       } catch (IOException e) {
-        e.printStackTrace(fErr);
+        e.printStackTrace(err);
       }
     }
   }
@@ -338,17 +363,17 @@
           fileReader.close();
         }
       } catch (IOException e) {
-        e.printStackTrace(fErr);
+        e.printStackTrace(err);
       }
     }
-    caught.printStackTrace(fErr);
+    caught.printStackTrace(err);
     return false;
   }
 
   private Set findSourcePackages() {
     Set results = new HashSet();
-    for (int i = 0, n = fSourcePath.length; i < n; ++i) {
-      File srcDir = fSourcePath[i];
+    for (int i = 0, n = sourcePath.length; i < n; ++i) {
+      File srcDir = sourcePath[i];
       findSourcePackages(results, srcDir, "");
     }
     return results;
@@ -399,7 +424,7 @@
         if (file.lastModified() > topicFile.lastModified()) {
           String xsltFileName = matcher.group(2) + "-" + "topics.xslt";
           String xslt = getFileFromClassPath(xsltFileName); // yucky slow
-          fOut.println(file + " -> " + topicFile);
+          out.println(file + " -> " + topicFile);
           transform(xslt, file, topicFile, null);
         }
       }
@@ -409,16 +434,16 @@
   private boolean genHtml() {
     // Make sure the html directory exists.
     //
-    File htmlDir = new File(fOutDir, "html");
+    File htmlDir = new File(outDir, "html");
     if (!htmlDir.exists() && !htmlDir.mkdirs()) {
-      fErr.println("Cannot create html output directory "
+      err.println("Cannot create html output directory "
           + htmlDir.getAbsolutePath());
       return false;
     }
 
     // Merge all *.topics.xml into one topics.xml file.
     //
-    File mergedTopicsFile = new File(fOutDir, "topics.xml");
+    File mergedTopicsFile = new File(outDir, "topics.xml");
     if (!mergeTopics(mergedTopicsFile)) {
       return false;
     }
@@ -436,7 +461,7 @@
       String xsltHtmls = getFileFromClassPath("topics-htmls.xslt");
 
       Map params = new HashMap();
-      params.put("title", fTitle);
+      params.put("title", title);
 
       transform(xsltHtmls, mergedTopicsFile, mergedHtmlsFile, params);
 
@@ -460,10 +485,10 @@
         cssWriter.write(css);
         cssWriter.close();
       } catch (IOException e) {
-        e.printStackTrace(fErr);
+        e.printStackTrace(err);
       }
     } else {
-      fOut.println("Skipping html creation since nothing seems to have changed since "
+      out.println("Skipping html creation since nothing seems to have changed since "
           + mergedHtmlsFile.getAbsolutePath());
     }
 
@@ -476,7 +501,7 @@
       in = getClass().getClassLoader().getResourceAsStream(filename);
       try {
         if (in == null) {
-          fErr.println("Cannot find file: " + filename);
+          err.println("Cannot find file: " + filename);
           System.exit(-1); // yuck
         }
         StringWriter sw = new StringWriter();
@@ -506,14 +531,14 @@
       // merge into the big topics doc.
       //
       boolean foundAny = false;
-      for (int i = 0, n = fHtmlFileBases.length; i < n; ++i) {
-        String filebase = fHtmlFileBases[i];
-        File fileToMerge = new File(fOutDir, filebase + ".topics.xml");
+      for (int i = 0, n = htmlFileBases.length; i < n; ++i) {
+        String filebase = htmlFileBases[i];
+        File fileToMerge = new File(outDir, filebase + ".topics.xml");
         if (fileToMerge.exists()) {
           foundAny = true;
           args.add(fileToMerge.getAbsolutePath());
         } else {
-          fErr.println("Unable to find " + fileToMerge.getName());
+          err.println("Unable to find " + fileToMerge.getName());
         }
       }
 
@@ -522,11 +547,11 @@
         traceCommand("SplitterJoiner", argArray);
         SplitterJoiner.main(argArray);
       } else {
-        fErr.println("No topics found");
+        err.println("No topics found");
         return false;
       }
     } catch (IOException e) {
-      e.printStackTrace(fErr);
+      e.printStackTrace(err);
       return false;
     }
     return true;
@@ -536,11 +561,11 @@
    * Runs the help process.
    */
   private boolean process() {
-    if (fFileType != null) {
+    if (fileType != null) {
       // Produce XML from JavaDoc.
       //
-      String fileName = fFileBase + "." + fFileType + ".xml";
-      if (!runBooklet(new File(fOutDir, fileName))) {
+      String fileName = base + "." + fileType + ".xml";
+      if (!runBooklet(new File(outDir, fileName))) {
         return false;
       }
     }
@@ -550,7 +575,7 @@
     //
     transformExistingIntoTopicXml();
 
-    if (fGenerateHtml) {
+    if (generateHtml) {
       // Merge into HTML.
       if (!genHtml()) {
         return false;
@@ -562,10 +587,10 @@
 
   private boolean runBooklet(File bkoutFile) {
     // Write out the list of packages that can be found on the source path.
-    fOut.println("Creating " + bkoutFile.getAbsolutePath());
+    out.println("Creating " + bkoutFile.getAbsolutePath());
     Set srcPackages = findSourcePackages();
     if (srcPackages.isEmpty()) {
-      fErr.println("No input files found");
+      err.println("No input files found");
       return false;
     }
 
@@ -581,27 +606,27 @@
 
     // Class path
     args.add("-classpath");
-    args.add(flattenPath(fClassPath));
+    args.add(flattenPath(classPath));
 
     // Source path
     args.add("-sourcepath");
-    args.add(flattenPath(fSourcePath));
+    args.add(flattenPath(sourcePath));
 
     // Overview file
-    if (fOverviewFile != null) {
+    if (overviewFile != null) {
       args.add("-overview");
-      args.add(fOverviewFile.getAbsolutePath());
+      args.add(overviewFile.getAbsolutePath());
     }
 
     // Output file
     args.add("-bkout");
     args.add(bkoutFile.getAbsolutePath());
 
-    if (fPackages != null) {
+    if (packages != null) {
       // Specify the packages to actually emit doc for
       StringBuffer bkdocpkg = new StringBuffer();
-      for (int i = 0; i < fPackages.length; i++) {
-        String pkg = fPackages[i];
+      for (int i = 0; i < packages.length; i++) {
+        String pkg = packages[i];
         bkdocpkg.append(pkg);
         bkdocpkg.append(";");
       }
@@ -630,20 +655,20 @@
       traceCommand("SplitterJoiner", argArray);
       SplitterJoiner.main(argArray);
     } catch (IOException e) {
-      e.printStackTrace(fErr);
+      e.printStackTrace(err);
       return false;
     }
     return true;
   }
 
   private void traceCommand(String cmd, String[] args) {
-    fOut.print(cmd);
+    out.print(cmd);
     for (int i = 0, n = args.length; i < n; ++i) {
       String arg = args[i];
-      fOut.print(" ");
-      fOut.print(arg);
+      out.print(" ");
+      out.print(arg);
     }
-    fOut.println();
+    out.println();
   }
 
   private void transform(String xslt, File inFile, File outFile, Map params) {
@@ -683,7 +708,7 @@
   }
 
   private void transformExistingIntoTopicXml() {
-    File[] children = fOutDir.listFiles();
+    File[] children = outDir.listFiles();
     if (children != null) {
       for (int i = 0, n = children.length; i < n; ++i) {
         File file = children[i];
@@ -701,18 +726,4 @@
       return null;
     }
   }
-
-  private final File[] fClassPath;
-  private final String[] fPackages;
-  private final PrintStream fErr;
-  private final String fFileBase;
-  private final String fFileType;
-  private final boolean fGenerateHtml;
-  private final String[] fHtmlFileBases;
-  private final File[] fImagePath;
-  private final PrintStream fOut;
-  private final File fOutDir;
-  private final File fOverviewFile;
-  private final File[] fSourcePath;
-  private final String fTitle;
 }
diff --git a/build-tools/doctool/src/com/google/doctool/DocToolFactory.java b/build-tools/doctool/src/com/google/doctool/DocToolFactory.java
index f0027f9..b9acc5f 100644
--- a/build-tools/doctool/src/com/google/doctool/DocToolFactory.java
+++ b/build-tools/doctool/src/com/google/doctool/DocToolFactory.java
@@ -25,6 +25,28 @@
  */
 public class DocToolFactory {
 
+  private final List classPathEntries = new ArrayList();
+
+  private String fileBase;
+
+  private String fileType;
+
+  private boolean generateHtml;
+
+  private final List htmlFileBases = new ArrayList();
+
+  private final List imagePathEntries = new ArrayList();
+
+  private File outDir;
+
+  private File overviewFile;
+
+  private final List packageNameEntries = new ArrayList();
+
+  private final List srcPathEntries = new ArrayList();
+
+  private String title;
+
   public DocToolFactory() {
   }
 
@@ -138,16 +160,4 @@
   public void setTitle(String title) {
     this.title = title;
   }
-
-  private final List classPathEntries = new ArrayList();
-  private String fileBase;
-  private String fileType;
-  private boolean generateHtml;
-  private final List htmlFileBases = new ArrayList();
-  private final List imagePathEntries = new ArrayList();
-  private File outDir;
-  private File overviewFile;
-  private final List packageNameEntries = new ArrayList();
-  private final List srcPathEntries = new ArrayList();
-  private String title;
 }
diff --git a/build-tools/doctool/src/com/google/doctool/ResourceIncluder.java b/build-tools/doctool/src/com/google/doctool/ResourceIncluder.java
index 91757d7..97833c2 100644
--- a/build-tools/doctool/src/com/google/doctool/ResourceIncluder.java
+++ b/build-tools/doctool/src/com/google/doctool/ResourceIncluder.java
@@ -27,6 +27,18 @@
  */
 public class ResourceIncluder {
 
+  /**
+   * Copied from {@link com.google.gwt.util.tools.Utility#close(InputStream)}.
+   */
+  public static void close(InputStream is) {
+    try {
+      if (is != null) {
+        is.close();
+      }
+    } catch (IOException e) {
+    }
+  }
+
   public static String getResourceFromClasspathScrubbedForHTML(Tag tag) {
     String partialPath = tag.text();
     try {
@@ -43,18 +55,6 @@
   }
 
   /**
-   * Copied from {@link com.google.gwt.util.tools.Utility#close(InputStream)}.
-   */
-  public static void close(InputStream is) {
-    try {
-      if (is != null) {
-        is.close();
-      }
-    } catch (IOException e) {
-    }
-  }
-
-  /**
    * Copied from
    * {@link com.google.gwt.util.tools.Utility#getFileFromClassPath(String)}.
    */
diff --git a/build-tools/doctool/src/com/google/doctool/SplitterJoiner.java b/build-tools/doctool/src/com/google/doctool/SplitterJoiner.java
index abe678d..5cd917c 100644
--- a/build-tools/doctool/src/com/google/doctool/SplitterJoiner.java
+++ b/build-tools/doctool/src/com/google/doctool/SplitterJoiner.java
@@ -42,6 +42,148 @@
  */
 public class SplitterJoiner {
 
+  public static void main(String[] args) throws IOException {
+    if (args.length < 2) {
+      help();
+      return;
+    } else if (args[0].equals("split")) {
+      String[] files = new String[args.length - 1];
+      System.arraycopy(args, 1, files, 0, args.length - 1);
+      split(files);
+    } else if (args[0].equals("join")) {
+      if (args.length < 4) {
+        help();
+        return;
+      }
+      String[] files = new String[args.length - 3];
+      System.arraycopy(args, 3, files, 0, args.length - 3);
+      merge(args[1], args[2], files);
+    } else {
+      if (!args[0].equals("-h") && !args[0].equals("-?")) {
+        System.err.println("Error: don't know '" + args[0] + "'");
+      }
+      help();
+      return;
+    }
+  }
+
+  private static void emitFile(PrintWriter out, File outputFile, File inputFile)
+      throws IOException, ParserConfigurationException, SAXException,
+      TransformerException {
+    if (!inputFile.exists()) {
+      System.err.println("Error: Cannot find input file " + inputFile.getPath());
+      return;
+    }
+
+    if (inputFile.getCanonicalFile().equals(outputFile)) {
+      // skip
+      return;
+    }
+
+    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    DocumentBuilder builder = factory.newDocumentBuilder();
+    Document doc = builder.parse(inputFile);
+    writeTopLevelChildren(doc, out);
+  }
+
+  private static void help() {
+    System.out.println("Usage: SplitterJoiner split infile+");
+    System.out.println("Usage: SplitterJoiner join tag outfile (infile|dir)+");
+    System.out.println("\tsplit         indicates that inputs file should be split into multiple output files");
+    System.out.println("\tjoin          indicates xml files (or directories) should be merged into one big xml file (on stdout)");
+    System.out.println("\ttag           when joining, the outermost xml tag name");
+    System.out.println("\toutfile       when joining, the file to write the joined output into");
+    System.out.println("\tinfile        if splitting, an input file to split");
+    System.out.println("\t              if joining, a file whose contents should be merged in");
+    System.out.println("\tdir           when joining, a directory whose xml files' contents should be merged in");
+  }
+
+  private static boolean isNewerThan(File file, long lastModified) {
+    if (file.isFile()) {
+      return file.lastModified() > lastModified;
+    }
+
+    File[] children = file.listFiles();
+    if (children != null) {
+      for (int i = 0, n = children.length; i < n; ++i) {
+        File child = children[i];
+        if (isNewerThan(child, lastModified)) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  private static void merge(String tag, String outputPath, String files[]) {
+    File outputFile = null;
+    try {
+      outputFile = new File(outputPath).getCanonicalFile();
+    } catch (IOException e) {
+      e.printStackTrace();
+      return;
+    }
+
+    // Maybe we don't need to do anything.
+    //
+    boolean skipMerge = true;
+    if (!outputFile.exists()) {
+      skipMerge = false;
+    } else {
+      long outputFileLastModified = outputFile.lastModified();
+      for (int i = 0, n = files.length; i < n; ++i) {
+        if (isNewerThan(new File(files[i]), outputFileLastModified)) {
+          skipMerge = false;
+          break;
+        }
+      }
+    }
+
+    if (skipMerge) {
+      // Nothing to do.
+      //
+      return;
+    }
+
+    try {
+      PrintWriter out = new PrintWriter(new FileWriter(outputFile), true);
+
+      out.println("<?xml version='1.0'?>");
+      out.println("<" + tag + ">");
+
+      for (int i = 0; i < files.length; i++) {
+        File file = new File(files[i]);
+        if (file.isFile()) {
+          emitFile(out, outputFile, file);
+        } else {
+          File[] children = file.listFiles();
+          if (children != null) {
+            for (int j = 0; j < children.length; ++j) {
+              if (children[j].isFile()
+                  && children[j].getPath().endsWith(".xml")) {
+                emitFile(out, outputFile, children[j]);
+              }
+            }
+          }
+        }
+      }
+      out.println("</" + tag + ">");
+      out.close();
+    } catch (IOException e) {
+      outputFile.deleteOnExit();
+      e.printStackTrace();
+    } catch (ParserConfigurationException e) {
+      outputFile.deleteOnExit();
+      e.printStackTrace();
+    } catch (SAXException e) {
+      outputFile.deleteOnExit();
+      e.printStackTrace();
+    } catch (TransformerException e) {
+      e.printStackTrace();
+    }
+  }
+
   private static void split(String[] files) throws IOException {
     BufferedReader reader = null;
     String prefix = null;
@@ -141,146 +283,4 @@
     }
   }
 
-  private static void emitFile(PrintWriter out, File outputFile, File inputFile)
-      throws IOException, ParserConfigurationException, SAXException,
-      TransformerException {
-    if (!inputFile.exists()) {
-      System.err.println("Error: Cannot find input file " + inputFile.getPath());
-      return;
-    }
-
-    if (inputFile.getCanonicalFile().equals(outputFile)) {
-      // skip
-      return;
-    }
-
-    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-    DocumentBuilder builder = factory.newDocumentBuilder();
-    Document doc = builder.parse(inputFile);
-    writeTopLevelChildren(doc, out);
-  }
-
-  private static void merge(String tag, String outputPath, String files[]) {
-    File outputFile = null;
-    try {
-      outputFile = new File(outputPath).getCanonicalFile();
-    } catch (IOException e) {
-      e.printStackTrace();
-      return;
-    }
-
-    // Maybe we don't need to do anything.
-    //
-    boolean skipMerge = true;
-    if (!outputFile.exists()) {
-      skipMerge = false;
-    } else {
-      long outputFileLastModified = outputFile.lastModified();
-      for (int i = 0, n = files.length; i < n; ++i) {
-        if (isNewerThan(new File(files[i]), outputFileLastModified)) {
-          skipMerge = false;
-          break;
-        }
-      }
-    }
-
-    if (skipMerge) {
-      // Nothing to do.
-      //
-      return;
-    }
-
-    try {
-      PrintWriter out = new PrintWriter(new FileWriter(outputFile), true);
-
-      out.println("<?xml version='1.0'?>");
-      out.println("<" + tag + ">");
-
-      for (int i = 0; i < files.length; i++) {
-        File file = new File(files[i]);
-        if (file.isFile()) {
-          emitFile(out, outputFile, file);
-        } else {
-          File[] children = file.listFiles();
-          if (children != null) {
-            for (int j = 0; j < children.length; ++j) {
-              if (children[j].isFile()
-                  && children[j].getPath().endsWith(".xml")) {
-                emitFile(out, outputFile, children[j]);
-              }
-            }
-          }
-        }
-      }
-      out.println("</" + tag + ">");
-      out.close();
-    } catch (IOException e) {
-      outputFile.deleteOnExit();
-      e.printStackTrace();
-    } catch (ParserConfigurationException e) {
-      outputFile.deleteOnExit();
-      e.printStackTrace();
-    } catch (SAXException e) {
-      outputFile.deleteOnExit();
-      e.printStackTrace();
-    } catch (TransformerException e) {
-      e.printStackTrace();
-    }
-  }
-
-  private static boolean isNewerThan(File file, long lastModified) {
-    if (file.isFile()) {
-      return file.lastModified() > lastModified;
-    }
-
-    File[] children = file.listFiles();
-    if (children != null) {
-      for (int i = 0, n = children.length; i < n; ++i) {
-        File child = children[i];
-        if (isNewerThan(child, lastModified)) {
-          return true;
-        }
-      }
-    }
-
-    return false;
-  }
-
-  private static void help() {
-    System.out.println("Usage: SplitterJoiner split infile+");
-    System.out.println("Usage: SplitterJoiner join tag outfile (infile|dir)+");
-    System.out.println("\tsplit         indicates that inputs file should be split into multiple output files");
-    System.out.println("\tjoin          indicates xml files (or directories) should be merged into one big xml file (on stdout)");
-    System.out.println("\ttag           when joining, the outermost xml tag name");
-    System.out.println("\toutfile       when joining, the file to write the joined output into");
-    System.out.println("\tinfile        if splitting, an input file to split");
-    System.out.println("\t              if joining, a file whose contents should be merged in");
-    System.out.println("\tdir           when joining, a directory whose xml files' contents should be merged in");
-  }
-
-  public static void main(String[] args) throws IOException {
-    if (args.length < 2) {
-      help();
-      return;
-    } else if (args[0].equals("split")) {
-      String[] files = new String[args.length - 1];
-      System.arraycopy(args, 1, files, 0, args.length - 1);
-      split(files);
-    } else if (args[0].equals("join")) {
-      if (args.length < 4) {
-        help();
-        return;
-      }
-      String[] files = new String[args.length - 3];
-      System.arraycopy(args, 3, files, 0, args.length - 3);
-      merge(args[1], args[2], files);
-    } else {
-      if (!args[0].equals("-h") && !args[0].equals("-?")) {
-        System.err.println("Error: don't know '" + args[0] + "'");
-      }
-      help();
-      return;
-    }
-  }
-
 }