Package com.topologi.diffx

Source Code of com.topologi.diffx.Main

/*
* This file is part of the DiffX library.
*
* For licensing information please see the file license.txt included in the release.
* A copy of this licence can also be found at
*   http://www.opensource.org/licenses/artistic-license-2.0.php
*/
package com.topologi.diffx;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.topologi.diffx.algorithm.DiffXAlgorithm;
import com.topologi.diffx.algorithm.DiffXFitWesyma;
import com.topologi.diffx.algorithm.DiffXFitopsy;
import com.topologi.diffx.algorithm.DiffXFitsy;
import com.topologi.diffx.algorithm.DiffXKumarRangan;
import com.topologi.diffx.algorithm.GuanoAlgorithm;
import com.topologi.diffx.config.DiffXConfig;
import com.topologi.diffx.config.TextGranularity;
import com.topologi.diffx.config.WhiteSpaceProcessing;
import com.topologi.diffx.format.BasicXMLFormatter;
import com.topologi.diffx.format.ConvenientXMLFormatter;
import com.topologi.diffx.format.DiffXFormatter;
import com.topologi.diffx.format.SafeXMLFormatter;
import com.topologi.diffx.format.SmartXMLFormatter;
import com.topologi.diffx.format.StrictXMLFormatter;
import com.topologi.diffx.format.XMLDiffXFormatter;
import com.topologi.diffx.load.DOMRecorder;
import com.topologi.diffx.load.Recorder;
import com.topologi.diffx.load.SAXRecorder;
import com.topologi.diffx.load.TextRecorder;
import com.topologi.diffx.sequence.EventSequence;
import com.topologi.diffx.sequence.SequenceSlicer;
import com.topologi.diffx.util.CommandLine;

/**
* Utility class to centralise the access to this API from the command line.
*
* @author Christophe Lauret
* @version 10 May 2010
*/
public final class Main {

  /**
   * Prevents creation of instances.
   */
  private Main() {
  }

  // equivalent methods -------------------------------------------------------------------

  /**
   * Returns <code>true</code> if the two specified files are XML equivalent by looking at the
   * sequence SAX events reported an XML reader.
   *
   * @param xml1 The first XML stream to compare.
   * @param xml2 The first XML stream to compare.
   *
   * @return <code>true</code> If the XML are considered equivalent;
   *         <code>false</code> otherwise.
   *
   * @throws DiffXException Should a Diff-X exception occur.
   * @throws IOException    Should an I/O exception occur.
   */
  public static boolean equivalent(File xml1, File xml2)
      throws DiffXException, IOException {
    Recorder recorder = new SAXRecorder();
    EventSequence seq0 = recorder.process(xml1);
    EventSequence seq1 = recorder.process(xml2);
    return seq0.equals(seq1);
  }

  /**
   * Returns <code>true</code> if the two specified input streams are equivalent by looking at the
   * sequence SAX events reported an XML reader.
   *
   * @param xml1 The first XML stream to compare.
   * @param xml2 The first XML stream to compare.
   *
   * @return <code>true</code> If the XML are considered equivalent;
   *         <code>false</code> otherwise.
   *
   * @throws DiffXException Should a Diff-X exception occur.
   * @throws IOException    Should an I/O exception occur.
   */
  public static boolean equivalent(InputStream xml1, InputStream xml2)
      throws DiffXException, IOException {
    SAXRecorder recorder = new SAXRecorder();
    EventSequence seq0 = recorder.process(new InputSource(xml1));
    EventSequence seq1 = recorder.process(new InputSource(xml2));
    return seq0.equals(seq1);
  }

  /**
   * Returns <code>true</code> if the two specified readers are equivalent by looking at the
   * sequence SAX events reported an XML reader.
   *
   * @param xml1 The first XML stream to compare.
   * @param xml2 The first XML stream to compare.
   *
   * @return <code>true</code> If the XML are considered equivalent;
   *         <code>false</code> otherwise.
   *
   * @throws DiffXException If a DiffX exception is reported by the recorders.
   * @throws IOException    Should an I/O exception occur.
   */
  public static boolean equivalent(Reader xml1, Reader xml2)
      throws DiffXException, IOException {
    SAXRecorder recorder = new SAXRecorder();
    EventSequence seq0 = recorder.process(new InputSource(xml1));
    EventSequence seq1 = recorder.process(new InputSource(xml2));
    return seq0.equals(seq1);
  }

  // diff methods -------------------------------------------------------------------------

  /**
   * Compares the two specified XML nodes and prints the diff onto the given writer.
   *
   * @param xml1   The first XML node to compare.
   * @param xml2   The second XML node to compare.
   * @param out    Where the output goes.
   * @param config The DiffX configuration to use.
   *
   * @throws DiffXException Should a Diff-X exception occur.
   * @throws IOException    Should an I/O exception occur.
   */
  public static void diff(Node xml1, Node xml2, Writer out, DiffXConfig config)
      throws DiffXException, IOException {
    // records the events from the XML
    DOMRecorder loader = new DOMRecorder();
    if (config != null) {
      loader.setConfig(config);
    }
    EventSequence seq1 = loader.process(xml1);
    EventSequence seq2 = loader.process(xml2);
    // start slicing
    diff(seq1, seq2, out, config);
  }

  /**
   * Compares the two specified <code>NodeList</code>s and prints the diff onto the given writer.
   *
   * <p>Only the first node in the node list is sequenced.
   *
   * @param xml1   The first XML node list to compare.
   * @param xml2   The second XML node list to compare.
   * @param out    Where the output goes.
   * @param config The DiffX configuration to use.
   *
   * @throws DiffXException Should a Diff-X exception occur.
   * @throws IOException    Should an I/O exception occur.
   */
  public static void diff(NodeList xml1, NodeList xml2, Writer out, DiffXConfig config)
      throws DiffXException, IOException {
    // records the events from the XML
    DOMRecorder loader = new DOMRecorder();
    if (config != null) {
      loader.setConfig(config);
    }
    EventSequence seq1 = loader.process(xml1);
    EventSequence seq2 = loader.process(xml2);
    // start slicing
    diff(seq1, seq2, out, config);
  }

  /**
   * Compares the two specified xml files and prints the diff onto the given writer.
   *
   * @param xml1   The first XML reader to compare.
   * @param xml2   The first XML reader to compare.
   * @param out    Where the output goes.
   * @param config The DiffX configuration to use.
   *
   * @throws DiffXException Should a Diff-X exception occur.
   * @throws IOException    Should an I/O exception occur.
   */
  public static void diff(Reader xml1, Reader xml2, Writer out, DiffXConfig config)
      throws DiffXException, IOException {
    // records the events from the XML
    SAXRecorder recorder = new SAXRecorder();
    if (config != null) {
      recorder.setConfig(config);
    }
    EventSequence seq1 = recorder.process(new InputSource(xml1));
    EventSequence seq2 = recorder.process(new InputSource(xml2));
    // start slicing
    diff(seq1, seq2, out, config);
  }

  /**
   * Compares the two specified xml files and prints the diff onto the given writer.
   *
   * @param xml1 The first XML reader to compare.
   * @param xml2 The first XML reader to compare.
   * @param out  Where the output goes
   *
   * @throws DiffXException Should a Diff-X exception occur.
   * @throws IOException    Should an I/O exception occur.
   */
  public static void diff(Reader xml1, Reader xml2, Writer out)
      throws DiffXException, IOException {
    // records the events from the XML
    SAXRecorder recorder = new SAXRecorder();
    EventSequence seq1 = recorder.process(new InputSource(xml1));
    EventSequence seq2 = recorder.process(new InputSource(xml2));
    // start slicing
    diff(seq1, seq2, out, new DiffXConfig());
  }

  /**
   * Compares the two specified xml files and prints the diff onto the given writer.
   *
   * @param xml1 The first XML input stream to compare.
   * @param xml2 The first XML input stream to compare.
   * @param out  Where the output goes
   *
   * @throws DiffXException Should a Diff-X exception occur.
   * @throws IOException    Should an I/O exception occur.
   */
  public static void diff(InputStream xml1, InputStream xml2, OutputStream out)
      throws DiffXException, IOException {
    // records the events from the XML
    SAXRecorder recorder = new SAXRecorder();
    EventSequence seq1 = recorder.process(new InputSource(xml1));
    EventSequence seq2 = recorder.process(new InputSource(xml2));
    diff(seq1, seq2, new OutputStreamWriter(out), new DiffXConfig());
  }

  /**
   * Compares the two specified xml files and prints the diff onto the given writer.
   *
   * @param seq1   The first XML reader to compare.
   * @param seq2   The first XML reader to compare.
   * @param out    Where the output goes.
   * @param config The DiffX configuration to use.
   *
   * @throws DiffXException Should a Diff-X exception occur.
   * @throws IOException    Should an I/O exception occur.
   */
  private static void diff(EventSequence seq1, EventSequence seq2, Writer out, DiffXConfig config)
      throws DiffXException, IOException {
    SafeXMLFormatter formatter = new SafeXMLFormatter(out);
    formatter.declarePrefixMapping(seq1.getPrefixMapping());
    formatter.declarePrefixMapping(seq2.getPrefixMapping());

    if (config != null) {
      formatter.setConfig(config);
    }
    SequenceSlicer slicer = new SequenceSlicer(seq1, seq2);
    slicer.slice();
    slicer.formatStart(formatter);
    DiffXAlgorithm df = new GuanoAlgorithm(seq1, seq2);
    df.process(formatter);
    slicer.formatEnd(formatter);
  }

  // command line -------------------------------------------------------------------------

  /**
   * Main entry point from the command line.
   *
   * @param args The command-line arguments
   *
   * @throws Exception If anything wrong happens.
   */
  public static void main(String[] args) throws Exception {
    // TODO: better command-line interface
    if (args.length < 2) {
      usage();
    }
    try {
      boolean profile = CommandLine.hasSwitch("-profile", args);
      boolean slice = !CommandLine.hasSwitch("-noslice", args);
      boolean quiet = CommandLine.hasSwitch("-quiet", args);

      // get the files
      File xml1 = new File(args[args.length - 2]);
      File xml2 = new File(args[args.length - 1]);

      // loading
      long t0 = System.currentTimeMillis();
      Recorder recorder = getRecorder(args);
      EventSequence seq1 = recorder.process(xml1);
      EventSequence seq2 = recorder.process(xml2);
      long t1 = System.currentTimeMillis();
      if (profile) {
        System.err.println("Loaded files in "+(t1 - t0)+"ms");
      }

      // get the config
      DiffXConfig config = new DiffXConfig();
      config.setGranularity(getTextGranularity(args));
      config.setWhiteSpaceProcessing(getWhiteSpaceProcessing(args));
      if (!quiet) {
        System.err.println("Whitespace processing: "+getTextGranularity(args)+" "+getWhiteSpaceProcessing(args));
      }

      // get and setup the formatter
      Writer out = new OutputStreamWriter(getOutput(args), "utf-8");
      DiffXFormatter formatter = getFormatter(args, out);
      if (formatter instanceof XMLDiffXFormatter) {
        ((XMLDiffXFormatter)formatter).declarePrefixMapping(seq1.getPrefixMapping());
        ((XMLDiffXFormatter)formatter).declarePrefixMapping(seq2.getPrefixMapping());
      }
      formatter.setConfig(config);

      // pre-slicing
      SequenceSlicer slicer = new SequenceSlicer(seq1, seq2);
      if (slice) {
        slicer.slice();
        slicer.formatStart(formatter);
      }

      // start algorithm
      if (!quiet) {
        System.err.println("Matrix: "+seq1.size()+"x"+seq2.size());
      }
      DiffXAlgorithm df = getAlgorithm(args, seq1, seq2);
      df.process(formatter);

      // post-slicing
      if (slice) {
        slicer.formatEnd(formatter);
      }

      long t2 = System.currentTimeMillis();
      if (profile) {
        System.err.println("Executed algorithm files in "+(t2 - t1)+"ms");
      }

    } catch (Throwable ex) {
      ex.printStackTrace();
    }
  }

  /**
   * Displays the usage on the System.err console
   */
  public static void usage() {
    System.err.println("Compare the SAX events returned by two XML files.");
    System.err.println("usage:");
    System.err.println("  Main [options] xml_file1 xml_file2");
    System.err.println("where:");
    System.err.println("  xml_file1 = Path to the new XML file");
    System.err.println("  xml_file2 = Path to the old XML file");
    System.err.println("options:");
    System.err.println("  -profile    Display profiling info");
    System.err.println("  -noslice    Do not use slicing");
    System.err.println("  -o [output] The output file");
    System.err.println("  -L [loader] Choose a specific loader");
    System.err.println("               sax* | dom | text");
    System.err.println("  -A [algo]   Choose a specific algorithm");
    System.err.println("               fitsy* | guano | fitopsy | kumar | wesyma");
    System.err.println("  -F [format] Choose a specific formatter");
    System.err.println("               smart* | basic | convenient | strict | short");
    System.err.println("  -W [wsp]    Define whitespace processing");
    System.err.println("               preserve* | compare | ignore");
    System.err.println("  -G [granul] Define text diffing granularity");
    System.err.println("               word* | text | character");
    System.err.println(" * indicates option used by default.");
    System.exit(1);
  }

  /**
   * @param args The command line arguments.
   * @return The recorder to use.
   */
  private static Recorder getRecorder(String[] args) {
    String loaderArg = CommandLine.getParameter("-L", args);
    if (loaderArg == null || "sax".equals(loaderArg))
      return new SAXRecorder();
    else if ("dom".equals(loaderArg))
      return new DOMRecorder();
    else if ("text".equals(loaderArg))
      return new TextRecorder();
    else {
      usage();
    }
    return null;
  }

  /**
   * @param args The command line arguments.
   * @return The output to use.
   *
   * @throws FileNotFoundException If the file does not exist.
   */
  private static OutputStream getOutput(String[] args) throws FileNotFoundException {
    String outArg = CommandLine.getParameter("-o", args);
    if (outArg == null)
      return System.out;
    else
      return new BufferedOutputStream(new FileOutputStream(outArg));
  }

  /**
   * @param args The command line arguments.
   * @param seq1 The first sequence.
   * @param seq2 The second sequence.
   * @return The algorithm to use.
   */
  private static DiffXAlgorithm getAlgorithm(String[] args, EventSequence seq1, EventSequence seq2) {
    String loaderArg = CommandLine.getParameter("-A", args);
    if (loaderArg == null || "fitsy".equals(loaderArg))
      return new DiffXFitsy(seq1, seq2);
    else if ("guano".equals(loaderArg))
      return new GuanoAlgorithm(seq1, seq2);
    else if ("fitopsy".equals(loaderArg))
      return new DiffXFitopsy(seq1, seq2);
    else if ("kumar".equals(loaderArg))
      return new DiffXKumarRangan(seq1, seq2);
    else if ("wesyma".equals(loaderArg))
      return new DiffXFitWesyma(seq1, seq2);
    else {
      usage();
    }
    return null;
  }

  /**
   * @param args The command line arguments.
   * @param out  The writer to use.
   * @return The formatter to use.
   * @throws IOException Should and I/O error occur
   */
  private static DiffXFormatter getFormatter(String[] args, Writer out) throws IOException {
    String formatArg = CommandLine.getParameter("-F", args);
    if (formatArg == null || "smart".equals(formatArg))
      return new SmartXMLFormatter(out);
    else if ("convenient".equals(formatArg))
      return new ConvenientXMLFormatter(out);
    else if ("basic".equals(formatArg))
      return new BasicXMLFormatter(out);
    else if ("strict".equals(formatArg))
      return new StrictXMLFormatter(out);
    else if ("short".equals(formatArg))
      return new StrictXMLFormatter(out);
    else {
      usage();
    }
    return null;
  }

  /**
   * @param args The command line arguments.
   * @return The formatter to use.
   * @throws IOException Should and I/O error occur
   */
  private static WhiteSpaceProcessing getWhiteSpaceProcessing(String[] args) throws IOException {
    String formatArg = CommandLine.getParameter("-W", args);
    if (formatArg == null || "preserve".equals(formatArg))
      return WhiteSpaceProcessing.PRESERVE;
    else if ("compare".equals(formatArg))
      return WhiteSpaceProcessing.COMPARE;
    else if ("ignore".equals(formatArg))
      return WhiteSpaceProcessing.IGNORE;
    else {
      usage();
    }
    return null;
  }

  /**
   * @param args The command line arguments.
   * @return The formatter to use.
   * @throws IOException Should and I/O error occur
   */
  private static TextGranularity getTextGranularity(String[] args) throws IOException {
    String formatArg = CommandLine.getParameter("-G", args);
    if (formatArg == null || "word".equals(formatArg))
      return TextGranularity.WORD;
    else if ("text".equals(formatArg))
      return TextGranularity.TEXT;
    else if ("character".equals(formatArg))
      return TextGranularity.CHARACTER;
    else {
      usage();
    }
    return null;
  }
}
TOP

Related Classes of com.topologi.diffx.Main

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.