001    package calhoun.util;
002    
003    import java.io.BufferedReader;
004    import java.io.File;
005    import java.io.FileInputStream;
006    import java.io.IOException;
007    import java.io.InputStreamReader;
008    import java.io.PrintWriter;
009    import java.io.Reader;
010    import java.io.StringWriter;
011    import java.util.ArrayList;
012    
013    import bmsi.util.Diff;
014    import bmsi.util.DiffPrint;
015    
016    /**
017     * Computes the 'diff' difference between two files. By default, whitespace in the files is ignored.
018     */
019    public class FileDiff
020    {
021            private String[] firstLines;
022            private String[] secondLines;
023    
024            private boolean closeReaders;
025            private Reader firstLinesReader;
026            private Reader secondLinesReader;
027            private boolean ignoreWhitespace = true;
028            private String commentLineIndicator;
029            private Diff.change change = null;
030    
031            public static boolean filesMatch(String first, String second) throws IOException {
032                    return !new FileDiff(first, second).execute();
033            }
034    
035            /**     Constructor takes 2 file names - opens the files using UTF-8 encoding.
036            */
037            public FileDiff(String first, String second) throws IOException
038            {
039                    this(new InputStreamReader( new FileInputStream(first), "UTF-8" ), new InputStreamReader( new FileInputStream(second),"UTF-8"), true );
040            }
041    
042            /**     Constructor takes 2 Files - opens the files using UTF-8 encoding.
043            */
044            public FileDiff(File first, File second) throws IOException
045            {
046                    this(new InputStreamReader( new FileInputStream(first), "UTF-8" ), new InputStreamReader( new FileInputStream(second),"UTF-8"), true );
047            }
048    
049            public FileDiff(Reader first, Reader second)
050            {
051                    this( first,second, false );
052            }
053    
054            public FileDiff(Reader first, Reader second, boolean closeReaders )
055            {
056                    this.firstLinesReader = first;
057                    this.secondLinesReader = second;
058                    this.closeReaders = closeReaders;
059            }
060    
061            /**
062             * Sets whether to ignore whitespace. By default, whitespace is ignored.
063             * @see #getIgnoreWhitespace
064             */
065            public void setIgnoreWhitespace(boolean b)
066            {
067                    ignoreWhitespace = b;
068            }
069    
070            /**
071             * @see #setIgnoreWhitespace
072             */
073            public boolean getIgnoreWhitespace()
074            {
075                    return ignoreWhitespace;
076            }
077    
078            /**
079             * Sets the comment line indicator string.  If set, lines beginning with this string are not used in the diff comparison.
080             * @see #getCommentLineIndicator
081             */
082            public void setCommentLineIndicator(String commentLineIndicator)
083            {
084                    this.commentLineIndicator = commentLineIndicator;
085            }
086    
087            /**
088             * Gets the comment line indicator string.
089             * @see #setCommentLineIndicator
090             */
091            public String getCommentLineIndicator()
092            {
093                    return commentLineIndicator;
094            }
095    
096            /**
097             * @return whether the two files were different.
098             * @see #toString
099             */
100            public boolean execute() throws IOException
101            {
102                    firstLines = readLines(firstLinesReader);
103                    secondLines = readLines(secondLinesReader);
104                    if ( closeReaders )
105                    {
106                            firstLinesReader.close();
107                            secondLinesReader.close();
108                    }
109                    Diff diff = new Diff(firstLines, secondLines);
110                    change = diff.diff_2(false);
111                    return change != null;
112            }
113    
114            /**
115             * @return a diff-style listing of the differences between the 2 files. If the files were identical,
116             * returns the empty string ('').
117             */
118            @Override
119            public String toString()
120            {
121                    if ( change != null )
122                    {
123                            DiffPrint.NormalPrint np = new DiffPrint.NormalPrint(firstLines, secondLines);
124                            StringWriter str = new StringWriter();
125                            PrintWriter writer = new PrintWriter(str);
126                            np.setWriter(writer);
127                            np.print_script(change);
128                            writer.close();
129                            return str.toString();
130                    }
131                    else
132                    {
133                            return "";
134                    }
135            }
136    
137            private String[] readLines(Reader r) throws IOException
138            {
139                    BufferedReader reader = new BufferedReader(r);
140                    ArrayList lines = new ArrayList();
141                    String line;
142                    while ( ( line = reader.readLine() ) != null )
143                    {
144                            if ( ignoreWhitespace )
145                                    line = line.trim();
146    
147                            if ( (!ignoreWhitespace || !"".equals(line)) &&
148                                      (commentLineIndicator == null || !line.startsWith(commentLineIndicator)) )
149                            {
150                                    lines.add(line);
151                            }
152                    }
153                    String[] result = new String[lines.size()];
154                    return (String[])lines.toArray(result);
155            }
156    }