ListDiffPrinter.java

  1. /*
  2.  *  Copyright (c) 2001-2024, Jean Tessier
  3.  *  All rights reserved.
  4.  *  
  5.  *  Redistribution and use in source and binary forms, with or without
  6.  *  modification, are permitted provided that the following conditions
  7.  *  are met:
  8.  *  
  9.  *      * Redistributions of source code must retain the above copyright
  10.  *        notice, this list of conditions and the following disclaimer.
  11.  *  
  12.  *      * Redistributions in binary form must reproduce the above copyright
  13.  *        notice, this list of conditions and the following disclaimer in the
  14.  *        documentation and/or other materials provided with the distribution.
  15.  *  
  16.  *      * Neither the name of Jean Tessier nor the names of his contributors
  17.  *        may be used to endorse or promote products derived from this software
  18.  *        without specific prior written permission.
  19.  *  
  20.  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21.  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22.  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23.  *  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
  24.  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25.  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26.  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27.  *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28.  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29.  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30.  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31.  */

  32. package com.jeantessier.diff;

  33. import com.jeantessier.text.PrinterBuffer;
  34. import org.apache.oro.text.perl.Perl5Util;

  35. import java.util.Collection;
  36. import java.util.Collections;
  37. import java.util.TreeSet;

  38. public class ListDiffPrinter {
  39.     public static final boolean DEFAULT_COMPRESS = false;
  40.     public static final String DEFAULT_ENCODING = "utf-8";
  41.     public static final String DEFAULT_DTD_PREFIX  = "https://jeantessier.github.io/dependency-finder/dtd";
  42.     public static final String DEFAULT_INDENT_TEXT = PrinterBuffer.DEFAULT_INDENT_TEXT;

  43.     private static final Perl5Util perl = new Perl5Util();
  44.    
  45.     private final boolean compress;
  46.     private final PrinterBuffer buffer;

  47.     private String name = "";
  48.     private String oldVersion = "";
  49.     private String newVersion = "";
  50.     private final Collection<String> removed = new TreeSet<>();
  51.     private final Collection<String> added = new TreeSet<>();

  52.     public ListDiffPrinter() {
  53.         this(DEFAULT_COMPRESS, DEFAULT_INDENT_TEXT, DEFAULT_ENCODING, DEFAULT_DTD_PREFIX);
  54.     }

  55.     public ListDiffPrinter(boolean compress) {
  56.         this(compress, DEFAULT_INDENT_TEXT, DEFAULT_ENCODING, DEFAULT_DTD_PREFIX);
  57.     }

  58.     public ListDiffPrinter(boolean compress, String indentText, String encoding, String dtdPrefix) {
  59.         this.buffer = new PrinterBuffer(indentText);
  60.         this.compress = compress;

  61.         appendHeader(encoding, dtdPrefix);
  62.     }

  63.     private void appendHeader(String encoding, String dtdPrefix) {
  64.         append("<?xml version=\"1.0\" encoding=\"").append(encoding).append("\" ?>").eol();
  65.         eol();
  66.         append("<!DOCTYPE list-diff SYSTEM \"").append(dtdPrefix).append("/list-diff.dtd\">").eol();
  67.         eol();
  68.     }

  69.     public String getName() {
  70.         return name;
  71.     }

  72.     public void setName(String name) {
  73.         this.name = name;
  74.     }

  75.     public String getOldVersion() {
  76.         return oldVersion;
  77.     }

  78.     public void setOldVersion(String oldVersion) {
  79.         this.oldVersion = oldVersion;
  80.     }

  81.     public String getNewVersion() {
  82.         return newVersion;
  83.     }

  84.     public void setNewVersion(String newVersion) {
  85.         this.newVersion = newVersion;
  86.     }
  87.    
  88.     public Collection<String> getRemoved() {
  89.         return Collections.unmodifiableCollection(removed);
  90.     }

  91.     public void remove(String line) {
  92.         this.removed.add(line);
  93.     }
  94.    
  95.     public Collection<String> getAdded() {
  96.         return Collections.unmodifiableCollection(added);
  97.     }

  98.     public void add(String line) {
  99.         this.added.add(line);
  100.     }

  101.     protected ListDiffPrinter append(boolean b) {
  102.         buffer.append(b);
  103.         return this;
  104.     }

  105.     protected ListDiffPrinter append(char c) {
  106.         buffer.append(c);
  107.         return this;
  108.     }

  109.     protected ListDiffPrinter append(char[] str, int offset, int len) {
  110.         buffer.append(str, offset, len);
  111.         return this;
  112.     }

  113.     protected ListDiffPrinter append(char[] str) {
  114.         buffer.append(str);
  115.         return this;
  116.     }

  117.     protected ListDiffPrinter append(double d) {
  118.         buffer.append(d);
  119.         return this;
  120.     }

  121.     protected ListDiffPrinter append(float f) {
  122.         buffer.append(f);
  123.         return this;
  124.     }

  125.     protected ListDiffPrinter append(int i) {
  126.         buffer.append(i);
  127.         return this;
  128.     }

  129.     protected ListDiffPrinter append(long l) {
  130.         buffer.append(l);
  131.         return this;
  132.     }

  133.     protected ListDiffPrinter append(Object obj) {
  134.         buffer.append(obj);
  135.         return this;
  136.     }

  137.     protected ListDiffPrinter append(String str) {
  138.         buffer.append(str);
  139.         return this;
  140.     }

  141.     protected ListDiffPrinter indent() {
  142.         buffer.indent();
  143.         return this;
  144.     }

  145.     protected ListDiffPrinter eol() {
  146.         buffer.eol();
  147.         return this;
  148.     }

  149.     protected void raiseIndent() {
  150.         buffer.raiseIndent();
  151.     }

  152.     protected void lowerIndent() {
  153.         buffer.lowerIndent();
  154.     }

  155.     public String toString() {
  156.         indent().append("<list-diff>").eol();
  157.         raiseIndent();
  158.        
  159.         indent().append("<name>").append(getName()).append("</name>").eol();
  160.         indent().append("<old>").append(getOldVersion()).append("</old>").eol();
  161.         indent().append("<new>").append(getNewVersion()).append("</new>").eol();
  162.        
  163.         indent().append("<removed>").eol();
  164.         raiseIndent();
  165.         printLines(compress ? compress(getRemoved()) : getRemoved());
  166.         lowerIndent();
  167.         indent().append("</removed>").eol();
  168.        
  169.         indent().append("<added>").eol();
  170.         raiseIndent();
  171.         printLines(compress ? compress(getAdded()) : getAdded());
  172.         lowerIndent();
  173.         indent().append("</added>").eol();
  174.        
  175.         lowerIndent();
  176.         indent().append("</list-diff>").eol();
  177.        
  178.         return buffer.toString();
  179.     }

  180.     private void printLines(Collection<String> lines) {
  181.         lines.forEach(line -> {
  182.             int pos = line.lastIndexOf(" [");
  183.             if (pos != -1) {
  184.                 indent().append("<line>").append(line.substring(0, pos)).append("</line>").eol();
  185.             } else {
  186.                 indent().append("<line>").append(line).append("</line>").eol();
  187.             }
  188.         });
  189.     }

  190.     private Collection<String> compress(Collection<String> lines) {
  191.         Collection<String> result = new TreeSet<>();

  192.         lines.forEach(line -> {
  193.             boolean add = true;
  194.             if (line.endsWith(" [C]")) {
  195.                 String packageName = extractPackageName(line);

  196.                 add = !lines.contains(packageName + " [P]");
  197.             } else if (line.endsWith(" [F]")) {
  198.                 String className = extractClassName(line);
  199.                 String packageName = extractPackageName(className);

  200.                 add = !lines.contains(packageName + " [P]") && !lines.contains(className + " [C]");
  201.             }

  202.             if (add) {
  203.                 result.add(line);
  204.             }
  205.         });

  206.         return result;
  207.     }

  208.     private String extractPackageName(String className) {
  209.         String result = "";

  210.         int pos = className.lastIndexOf('.');
  211.         if (pos != -1) {
  212.             result = className.substring(0, pos);
  213.         }
  214.        
  215.         return result;
  216.     }

  217.     private String extractClassName(String featureName) {
  218.         String result = "";

  219.         synchronized (perl) {
  220.             if (perl.match("/^(.*)\\.[^\\.]*\\(.*\\)(: \\S.*)?/", featureName)) {
  221.                 result = perl.group(1);
  222.             } else if (perl.match("/^(.*)\\.[\\^.]*/", featureName)) {
  223.                 result = perl.group(1);
  224.             }
  225.         }
  226.        
  227.         return result;
  228.     }
  229. }