/**
   * Write the XML representation of the API to a file.
   *
   * @param root the RootDoc object passed by Javadoc
   * @return true if no problems encountered
   */
  public static boolean writeXML(RootDoc root) {
    String tempFileName = outputFileName;
    if (outputDirectory != null) {
      tempFileName = outputDirectory;
      if (!tempFileName.endsWith(JDiff.DIR_SEP)) tempFileName += JDiff.DIR_SEP;
      tempFileName += outputFileName;
    }

    try {
      FileOutputStream fos = new FileOutputStream(tempFileName);
      outputFile = new PrintWriter(fos);
      System.out.println("JDiff: writing the API to file '" + tempFileName + "'...");
      if (root.specifiedPackages().length != 0 || root.specifiedClasses().length != 0) {
        RootDocToXML apiWriter = new RootDocToXML();
        apiWriter.emitXMLHeader();
        apiWriter.logOptions();
        apiWriter.processPackages(root);
        apiWriter.emitXMLFooter();
      }
      outputFile.close();
    } catch (IOException e) {
      System.out.println("IO Error while attempting to create " + tempFileName);
      System.out.println("Error: " + e.getMessage());
      System.exit(1);
    }
    // If validation is desired, write out the appropriate api.xsd file
    // in the same directory as the XML file.
    if (XMLToAPI.validateXML) {
      writeXSD();
    }
    return true;
  }
  /**
   * Process each package and the classes/interfaces within it.
   *
   * @param pd an array of PackageDoc objects
   */
  public void processPackages(RootDoc root) {
    PackageDoc[] specified_pd = root.specifiedPackages();
    Map pdl = new TreeMap();
    for (int i = 0; specified_pd != null && i < specified_pd.length; i++) {
      pdl.put(specified_pd[i].name(), specified_pd[i]);
    }

    // Classes may be specified separately, so merge their packages into the
    // list of specified packages.
    ClassDoc[] cd = root.specifiedClasses();
    // This is lists of the specific classes to document
    Map classesToUse = new HashMap();
    for (int i = 0; cd != null && i < cd.length; i++) {
      PackageDoc cpd = cd[i].containingPackage();
      if (cpd == null && !packagesOnly) {
        // If the RootDoc object has been created from a jar file
        // this duplicates classes, so we have to be able to disable it.
        // TODO this is still null?
        cpd = root.packageNamed("anonymous");
      }
      String pkgName = cpd.name();
      String className = cd[i].name();
      if (trace) System.out.println("Found package " + pkgName + " for class " + className);
      if (!pdl.containsKey(pkgName)) {
        if (trace) System.out.println("Adding new package " + pkgName);
        pdl.put(pkgName, cpd);
      }

      // Keep track of the specific classes to be used for this package
      List classes;
      if (classesToUse.containsKey(pkgName)) {
        classes = (ArrayList) classesToUse.get(pkgName);
      } else {
        classes = new ArrayList();
      }
      classes.add(cd[i]);
      classesToUse.put(pkgName, classes);
    }

    PackageDoc[] pd = (PackageDoc[]) pdl.values().toArray(new PackageDoc[0]);
    for (int i = 0; pd != null && i < pd.length; i++) {
      String pkgName = pd[i].name();

      // Check for an exclude tag in the package doc block, but not
      // in the package.htm[l] file.
      if (!shownElement(pd[i], null)) continue;

      if (trace) System.out.println("PROCESSING PACKAGE: " + pkgName);
      outputFile.println("<package name=\"" + pkgName + "\">");

      int tagCount = pd[i].tags().length;
      if (trace) System.out.println("#tags: " + tagCount);

      List classList;
      if (classesToUse.containsKey(pkgName)) {
        // Use only the specified classes in the package
        System.out.println("Using the specified classes");
        classList = (ArrayList) classesToUse.get(pkgName);
      } else {
        // Use all classes in the package
        classList = new LinkedList(Arrays.asList(pd[i].allClasses()));
      }
      Collections.sort(classList);
      ClassDoc[] classes = new ClassDoc[classList.size()];
      classes = (ClassDoc[]) classList.toArray(classes);
      processClasses(classes, pkgName);

      addPkgDocumentation(root, pd[i], 2);

      outputFile.println("</package>");
    }
  } // processPackages