001: /*
002: * Copyright (C) 2001, 2002 Robert MacGrogan
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: *
019: * $Archive: SourceJammer$
020: * $FileName: diff.java$
021: * $FileID: 4298$
022: *
023: * Last change:
024: * $AuthorName: Rob MacGrogan$
025: * $Date: 5/6/03 8:31 PM$
026: * $Comment: Allow algorithm class name to be passed in to constructor.$
027: *
028: * $KeyWordsOff: $
029: */
030:
031: package JLibDiff;
032:
033: import java.util.*;
034: import java.io.*;
035:
036: import org.sourcejammer.util.AppConfig;
037: import org.sourcejammer.util.ConfigurationException;
038:
039: /**
040: * The <code>diff</code> class compares two files. it compares also two
041: * BufferedReaders or two strings.
042: * after the comparison the vector will represents a list of hunk
043: * corresponding with blocks of difference.
044: * <p>
045: * to generate a file of difference, one can instanciate as follows the class
046: * diff:
047: * <p><blockquote><pre>
048: * diff d = new diff(file1,file2);
049: * </pre></blockquote><p>
050: * which is equivalent to:
051: * <p><blockquote><pre>
052: * diff d = new diff();
053: * d.diffFile(file1,file2);
054: * </pre></blockquote><p>
055: * To compare two BufferedReaders or two String we have to instanciate
056: * as follows:
057: * <p><blockquote><pre>
058: * diff d = new diff();
059: * d.diffBuffer(BufferedReader1,BufferedReader2);
060: * </pre></blockquote><p>
061: * or:
062: * <p><blockquote><pre>
063: * diff d = new diff();
064: * d.diffString(String1,String2);
065: * </pre></blockquote><p>
066: * The class <code>diff</code> includes methods for examining, printing
067: * or saveing blocks of difference: (Hunks).
068: * Here are some more examples of how <code>diff</code> can be used:
069: * <p><blockquote><pre>
070: * diff d=new diff(args[0],args[1]);
071: * d.print();
072: * d.save("diff.txt");
073: * </pre></blockquote><p>
074: * Example using BufferedReader and ED_format:
075: * <p><blockquote><pre>
076: * BufferedReader in=new BufferedReader(new FileReader(args[0]));
077: * BufferedReader inn=new BufferedReader(new FileReader(args[1]));
078: * diff d = new diff();
079: * d.diffBuffer(in,inn);
080: * d.print_ED();
081: * d.save_ED("diff.txt");
082: * </pre></blockquote><p>
083: * To go throw the list of Hunks we can choose between an Enumeration
084: * or a loop by spesifyng index in the vector to get at each time
085: * the corresponding Hunk.
086: *
087: * <p><blockquote><pre>
088: * Vector v=d.getHunk();
089: * for(Enumeration e=v.element();e.hasMoreElements(); )
090: * {
091: * System.out.print(((Hunk)e.nextElement()).convert());
092: * }
093: * </pre></blockquote><p>
094: *
095: * or:
096: * <p><blockquote><pre>
097: * diff d = new diff(file1,file2);
098: * for(int i=0; i<d.numberOfHunk(); i++){
099: * Object k=d.hunkAt(i);
100: * if(k instanceof Hunk)
101: * System.out.print(k.convert());
102: * }
103: * </pre></blockquote><p>
104: * @see diff.diff#getHunk()
105: * @see diff.diff#hunkAt()
106: * @see diff.diff#numberOfHunk()
107: * @see diff.diff#print()
108: * @see diff.diff#print_ED()
109: * @see diff.diff#print_RCS()
110: * @see diff.diff#save()
111: * @see diff.diff#save_ED()
112: * @see diff.diff#save_RCS()
113: */
114:
115: public class diff implements define, HunkVisitable {
116:
117: Vector v = new Vector();
118: String msEOL = "";
119:
120: private String msEndOfLine = "\n";
121:
122: private String diffAlgorithmClass = null;
123:
124: /**
125: * Allocates a new <code>diff</code> containing no Hunks.
126: */
127: public diff() {
128: }
129:
130: public diff(diff d) {
131: this .v = d.v;
132: }
133:
134: public diff(Vector v) {
135: this .v = v;
136: }
137:
138: /**
139: * Allocates a new <code>diff</code> which contains Hunks corresponding
140: * to the difference between the two files passed in arguments.
141: *
142: * @param s1 first file to compare.
143: * @param s2 second file to compare.
144: */
145: public diff(String s1, String s2) throws IOException {
146: diffFile(s1, s2);
147: }
148:
149: /**
150: * Allocates a new <code>diff</code> which contains Hunks corresponding
151: * to the difference between the two files passed in arguments.
152: *
153: * @param s1 first file to compare.
154: * @param s2 second file to compare.
155: */
156: public diff(String s1, String s2, String algorithmClass)
157: throws IOException {
158: setDiffAlgorithmClass(algorithmClass);
159: diffFile(s1, s2);
160: }
161:
162: public void supressEndOfLine() {
163: msEndOfLine = "";
164: }
165:
166: /**
167: * Returns a vector containing Hunks.
168: */
169: public Vector getHunk() {
170: return v;
171: }
172:
173: public Vector getUnderlyingVector() {
174: return (Vector) v.clone();
175: }
176:
177: /**
178: * Returns the number of hunks in the vector.
179: */
180: public int numberOfHunk() {
181: return v.size();
182: }
183:
184: /**
185: * Return the hunk at the specified index.
186: *
187: * @param i index of the hunk that will be returned.
188: */
189: public Hunk hunkAt(int i) {
190: return (Hunk) v.elementAt(i);
191: }
192:
193: /**
194: * Accept a visitor in order to visit the collection of hunks.
195: *
196: * @param visitor the HunkVisitor.
197: */
198: public void accept(HunkVisitor visitor) {
199: for (Enumeration e = v.elements(); e.hasMoreElements();) {
200: Hunk h = (Hunk) e.nextElement();
201: h.accept(visitor);
202: }
203: }
204:
205: /**
206: * Compares two files and updates the vector of Hunks.
207: *
208: * @param s1 first file to compare.
209: * @param s2 second file to compare.
210: */
211: public void diffFile(String s1, String s2) throws IOException {
212:
213: BufferedReader in = new BufferedReader(new FileReader(s1));
214: BufferedReader inn = new BufferedReader(new FileReader(s2));
215: diffBuffer(in, inn);
216: in.close();
217: inn.close();
218: }
219:
220: private Object[] getLines(int firstLine, int numLines,
221: Object[] parent) {
222: Object[] lines = null;
223: numLines = numLines * -1;
224: if (numLines > 0) {
225: lines = new Object[numLines];
226: System.arraycopy(parent, firstLine - numLines, lines, 0,
227: numLines);
228: }
229: return lines;
230: }
231:
232: /**
233: * Compares two BufferedReaders and updates the vector of Hunks.
234: *
235: * @param in first BufferedReader to compare.
236: * @param inn second BufferedReader to compare.
237: */
238: public void diffBuffer(BufferedReader in, BufferedReader inn)
239: throws IOException {
240:
241: int i, j, lower, upper, d = 1, k, row, col;
242:
243: String s;
244:
245: ArrayList al = new ArrayList();
246: while ((s = in.readLine()) != null) {
247: al.add(s);
248: }
249: String[] A = new String[al.size()];
250: al.toArray(A);
251:
252: al = new ArrayList();
253: while ((s = inn.readLine()) != null) {
254: al.add(s);
255: }
256: String[] B = new String[al.size()];
257: al.toArray(B);
258:
259: makeDiff(A, B);
260:
261: }
262:
263: protected DiffAlgorithm getDiffAlgorithmClass()
264: throws IllegalAccessException, InstantiationException {
265: String algorithmClass = null;
266: if (diffAlgorithmClass == null) {
267: algorithmClass = AppConfig.getInstance()
268: .getDiffAlgorithmClass();
269: } else {
270: algorithmClass = diffAlgorithmClass;
271: }
272: Class cl = null;
273: try {
274: cl = Class.forName(algorithmClass);
275: } catch (ClassNotFoundException ex) {
276: throw new ConfigurationException(
277: "Can't build diff. Diff algorithm class "
278: + algorithmClass
279: + " cannot be found in the classpath.");
280: }
281:
282: Object o = cl.newInstance();
283: DiffAlgorithm algorithm = (DiffAlgorithm) o;
284: algorithm.setEol(msEOL);
285: return algorithm;
286: }
287:
288: protected void makeDiff(String[] A, String[] B) {
289:
290: //First get the algorithm object.
291: DiffAlgorithm algorithm = null;
292: try {
293: algorithm = getDiffAlgorithmClass();
294: } catch (IllegalAccessException ex) {
295: throw new ConfigurationException(
296: "Unable to instantiate diff algorithm class.");
297: } catch (InstantiationException ex) {
298: throw new ConfigurationException(
299: "Unable to instantiate diff algorithm class.");
300: }
301:
302: v = algorithm.makeDiff(A, B);
303: }
304:
305: /**
306: * Print Hunks with normal format.
307: */
308: // use only in diff3 (to be deleted)
309: public void print() {
310: for (Enumeration e = v.elements(); e.hasMoreElements();)
311: System.out.print(((Hunk) e.nextElement()).convert());
312: }
313:
314: /**
315: * Sets the diffAlgorithmClass.
316: * @param diffAlgorithmClass The diffAlgorithmClass to set
317: */
318: public void setDiffAlgorithmClass(String diffAlgorithmClass) {
319: this.diffAlgorithmClass = diffAlgorithmClass;
320: }
321:
322: }
|