KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > diff > builtin > visualizer > TextDiffVisualizer


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.diff.builtin.visualizer;
21
22 import java.awt.Component JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.io.Reader JavaDoc;
26 import java.io.BufferedReader JavaDoc;
27 import java.io.ByteArrayInputStream JavaDoc;
28 import java.io.Serializable JavaDoc;
29 import org.openide.windows.CloneableOpenSupport;
30
31 import org.openide.util.NbBundle;
32
33 import org.netbeans.api.diff.Difference;
34 import org.netbeans.spi.diff.DiffVisualizer;
35
36 import org.netbeans.modules.diff.builtin.DiffPresenter;
37
38 /**
39  * The textual visualizer of diffs.
40  *
41  * @author Martin Entlicher
42  */

43 public class TextDiffVisualizer extends DiffVisualizer implements Serializable JavaDoc {
44     
45     private boolean contextMode = true;
46     private int contextNumLines = 3;
47
48     static final long serialVersionUID =-2481513747957146261L;
49     /** Creates a new instance of TextDiffVisualizer */
50     public TextDiffVisualizer() {
51     }
52
53     /**
54      * Get the display name of this diff visualizer.
55      */

56     public String JavaDoc getDisplayName() {
57         return NbBundle.getMessage(TextDiffVisualizer.class, "TextDiffVisualizer.displayName");
58     }
59     
60     /**
61      * Get a short description of this diff visualizer.
62      */

63     public String JavaDoc getShortDescription() {
64         return NbBundle.getMessage(TextDiffVisualizer.class, "TextDiffVisualizer.shortDescription");
65     }
66     
67     /** Getter for property contextMode.
68      * @return Value of property contextMode.
69      */

70     public boolean isContextMode() {
71         return contextMode;
72     }
73     
74     /** Setter for property contextMode.
75      * @param contextMode New value of property contextMode.
76      */

77     public void setContextMode(boolean contextMode) {
78         this.contextMode = contextMode;
79     }
80     
81     /** Getter for property contextNumLines.
82      * @return Value of property contextNumLines.
83      */

84     public int getContextNumLines() {
85         return contextNumLines;
86     }
87     
88     /** Setter for property contextNumLines.
89      * @param contextNumLines New value of property contextNumLines.
90      */

91     public void setContextNumLines(int contextNumLines) {
92         this.contextNumLines = contextNumLines;
93     }
94     
95     /**
96      * Some diff visualizers may have built-in the diff calculation. In such a case
97      * the visualizer does not need any diff provider.
98      * @return true when it relies on differences supplied, false if not.
99      *
100     public boolean needsProvider() {
101         return true;
102     }
103      */

104     
105     /**
106      * Show the visual representation of the diff between two sources.
107      * @param diffs The list of differences (instances of {@link Difference}).
108      * may be <code>null</code> in case that it does not need diff provider.
109      * @param name1 the name of the first source
110      * @param title1 the title of the first source
111      * @param r1 the first source
112      * @param name2 the name of the second source
113      * @param title2 the title of the second source
114      * @param r2 the second resource compared with the first one.
115      * @param MIMEType the mime type of these sources
116      * @return The TopComponent representing the diff visual representation
117      * or null, when the representation is outside the IDE.
118      * @throws IOException when the reading from input streams fails.
119      */

120     public Component JavaDoc createView(Difference[] diffs, String JavaDoc name1, String JavaDoc title1, Reader JavaDoc r1,
121                                 String JavaDoc name2, String JavaDoc title2, Reader JavaDoc r2, String JavaDoc MIMEType) throws IOException JavaDoc {
122         /*
123         TextDiffEditorSupport.DiffsListWithOpenSupport diff =
124             new TextDiffEditorSupport.DiffsListWithOpenSupport(diffs, name1 + " <> " + name2, title1+" <> "+title2);
125         diff.setContextMode(contextMode, contextNumLines);
126         diff.setReaders(r1, r2);
127         return ((TextDiffEditorSupport) diff.getOpenSupport()).createCloneableTopComponentForMe();
128         //return null;
129          */

130         TextDiffInfo diff = new TextDiffInfo(name1, name2, title1, title2, r1, r2, diffs);
131         diff.setContextMode(contextMode, contextNumLines);
132         return ((TextDiffEditorSupport) diff.getOpenSupport()).createCloneableTopComponentForMe();
133     }
134     
135     static InputStream JavaDoc differenceToLineDiffText(Difference[] diffs) {
136         StringBuffer JavaDoc content = new StringBuffer JavaDoc();
137         int n1, n2, n3, n4;
138         for (int i = 0; i < diffs.length; i++) {
139             Difference diff = diffs[i];
140             switch (diff.getType()) {
141                 case Difference.ADD:
142                     n3 = diff.getSecondStart();
143                     n4 = diff.getSecondEnd();
144                     if (n3 == n4) {
145                         content.append(diff.getFirstStart()+"a"+n3+"\n");
146                     } else {
147                         content.append(diff.getFirstStart()+"a"+n3+","+n4+"\n");
148                     }
149                     appendText(content, "> ", diff.getSecondText());
150                     break;
151                 case Difference.DELETE:
152                     n1 = diff.getFirstStart();
153                     n2 = diff.getFirstEnd();
154                     if (n1 == n2) {
155                         content.append(n1+"d"+diff.getSecondStart()+"\n");
156                     } else {
157                         content.append(n1+","+n2+"d"+diff.getSecondStart()+"\n");
158                     }
159                     appendText(content, "< ", diff.getFirstText());
160                     break;
161                 case Difference.CHANGE:
162                     n1 = diff.getFirstStart();
163                     n2 = diff.getFirstEnd();
164                     n3 = diff.getSecondStart();
165                     n4 = diff.getSecondEnd();
166                     if (n1 == n2 && n3 == n4) {
167                         content.append(n1+"c"+n3+"\n");
168                     } else if (n1 == n2) {
169                         content.append(n1+"c"+n3+","+n4+"\n");
170                     } else if (n3 == n4) {
171                         content.append(n1+","+n2+"c"+n3+"\n");
172                     } else {
173                         content.append(n1+","+n2+"c"+n3+","+n4+"\n");
174                     }
175                     appendText(content, "< ", diff.getFirstText());
176                     content.append("---\n");
177                     appendText(content, "> ", diff.getSecondText());
178                     break;
179             }
180         }
181         return new ByteArrayInputStream JavaDoc(content.toString().getBytes());
182     }
183     
184     private static void appendText(StringBuffer JavaDoc buff, String JavaDoc prefix, String JavaDoc text) {
185         if (text == null) return ;
186         int startLine = 0;
187         do {
188             int endLine = text.indexOf('\n', startLine);
189             if (endLine < 0) endLine = text.length();
190             buff.append(prefix + text.substring(startLine, endLine) + "\n");
191             startLine = endLine + 1;
192         } while (startLine < text.length());
193     }
194     
195     private static final String JavaDoc CONTEXT_MARK1B = "*** ";
196     private static final String JavaDoc CONTEXT_MARK1E = " ****\n";
197     private static final String JavaDoc CONTEXT_MARK2B = "--- ";
198     private static final String JavaDoc CONTEXT_MARK2E = " ----\n";
199     private static final String JavaDoc CONTEXT_MARK_DELIMETER = ",";
200     private static final String JavaDoc DIFFERENCE_DELIMETER = "***************\n";
201     private static final String JavaDoc LINE_PREP = " ";
202     private static final String JavaDoc LINE_PREP_ADD = "+ ";
203     private static final String JavaDoc LINE_PREP_REMOVE = "- ";
204     private static final String JavaDoc LINE_PREP_CHANGE = "! ";
205
206     /**
207      * @return UTF-8 encoded stream with '\n' newlines.
208      */

209     public static InputStream JavaDoc differenceToContextDiffText(TextDiffInfo diffInfo) throws IOException JavaDoc {
210         StringBuffer JavaDoc content = new StringBuffer JavaDoc();
211         content.append(CONTEXT_MARK1B);
212         content.append(diffInfo.getName1());
213         content.append("\n");
214         content.append(CONTEXT_MARK2B);
215         content.append(diffInfo.getName2());
216         content.append("\n");
217         final int contextNumLines = diffInfo.getContextNumLines();
218         Difference[] diffs = diffInfo.getDifferences();
219         BufferedReader JavaDoc br1 = new BufferedReader JavaDoc(diffInfo.createFirstReader());
220         BufferedReader JavaDoc br2 = new BufferedReader JavaDoc(diffInfo.createSecondReader());
221         int line1 = 1; // Current line read from 1st file
222
int line2 = 1; // Current line read from 2nd file
223
for (int i = 0; i < diffs.length; i++) {
224
225             content.append(DIFFERENCE_DELIMETER);
226
227             int[] cr = getContextRange(diffs, i, contextNumLines);
228
229             int begin = diffs[i].getFirstStart() - contextNumLines;
230             if (diffs[i].getType() == Difference.ADD) begin++;
231             if (begin < 1) begin = 1;
232             StringBuffer JavaDoc context = new StringBuffer JavaDoc();
233             line1 = dumpContext(0, diffs, i, cr[0], context, contextNumLines, br1, line1);
234             int end1 = line1 <= cr[1] ?
235                     line1 + contextNumLines :
236                     cr[1];
237             if (line1 <= cr[1] && i == diffs.length -1) {
238                 // determine how many lines remains to EOF
239
int buffer = contextNumLines;
240                 int existingLines = 0;
241                 while (buffer-- > 0) {
242                     String JavaDoc l = br1.readLine();
243                     if (l == null) {
244                         break;
245                     }
246                     existingLines++;
247                 }
248                 if (existingLines<contextNumLines) {
249                     end1 = line1 + existingLines - 1;
250                 }
251             }
252             content.append(CONTEXT_MARK1B);
253             content.append(begin);
254             content.append(CONTEXT_MARK_DELIMETER);
255             content.append(end1);
256             content.append(CONTEXT_MARK1E);
257             content.append(context);
258
259             begin = diffs[i].getSecondStart() - contextNumLines;
260             if (diffs[i].getType() == Difference.DELETE) begin++;
261             if (begin < 1) begin = 1;
262             context = new StringBuffer JavaDoc();
263             line2 = dumpContext(1, diffs, i, cr[0], context, contextNumLines, br2, line2);
264             int end2 = line2 <= cr[2] ?
265                     line2 + contextNumLines :
266                     cr[2];
267             if (line2 <= cr[2] && i == diffs.length -1) {
268                 // determine how many lines remains to EOF
269
int buffer = contextNumLines;
270                 int existingLines = 0;
271                 while (buffer-- > 0) {
272                     String JavaDoc l = br2.readLine();
273                     if (l == null) {
274                         break;
275                     }
276                     existingLines++;
277                 }
278                 if (existingLines<contextNumLines) {
279                     end2 = line2 + existingLines - 1;
280                 }
281             }
282             content.append(CONTEXT_MARK2B);
283             content.append(begin);
284             content.append(CONTEXT_MARK_DELIMETER);
285             content.append(end2);
286             content.append(CONTEXT_MARK2E);
287             content.append(context);
288
289             i = cr[0];
290             //i = dumpContext(diffs,
291
//Difference diff = diffs[i];
292
//Difference nextDiff = ((i + 1) < diffs.length) ? diffs[i + 1] : null;
293
//if (isNew) {
294
// content.append(DIFFERENCE_DELIMETER);
295
//}
296
}
297         return new ByteArrayInputStream JavaDoc(content.toString().getBytes("utf8")); // NOI18N
298
}
299     
300     private static int[] getContextRange(Difference[] diffs, int i,
301                                        int contextNumLines) {
302         int line1 = diffs[i].getFirstStart();
303         int line2 = diffs[i].getSecondStart();
304         for ( ; i < diffs.length; i++) {
305             Difference diff = diffs[i];
306             if (line1 + 2*contextNumLines < diff.getFirstStart() &&
307                 line2 + 2*contextNumLines < diff.getSecondStart()) break;
308             line1 = diff.getFirstStart();
309             line2 = diff.getSecondStart();
310             int l1 = Math.max(0, diff.getFirstEnd() - diff.getFirstStart());
311             int l2 = Math.max(0, diff.getSecondEnd() - diff.getSecondStart());
312             line1 += l1;
313             line2 += l2;
314         }
315         return new int[] { i - 1, line1 + contextNumLines, line2 + contextNumLines };
316     }
317     
318     private static int dumpContext(int which, Difference[] diffs, int i, int j,
319         StringBuffer JavaDoc content, final int contextNumLines, BufferedReader JavaDoc br, int line)
320         throws IOException JavaDoc {
321
322         int startLine;
323         if (which == 0) {
324             startLine = diffs[i].getFirstStart() - contextNumLines;
325             if (diffs[i].getType() == Difference.ADD) startLine++;
326         } else {
327             startLine = diffs[i].getSecondStart() - contextNumLines;
328             if (diffs[i].getType() == Difference.DELETE) startLine++;
329         }
330         for ( ; line < startLine; line++) br.readLine();
331         int position = content.length();
332         boolean isChange = false;
333         for ( ; i <= j; i++) {
334             Difference diff = diffs[i];
335             if (which == 0) startLine = diff.getFirstStart();
336             else startLine = diff.getSecondStart();
337             for ( ; line < startLine; line++) {
338                 content.append(LINE_PREP);
339                 content.append(br.readLine());
340                 content.append("\n");
341             }
342             int length = 0;
343             String JavaDoc prep = null;
344             switch (diffs[i].getType()) {
345                 case Difference.ADD:
346                     if (which == 1) {
347                         prep = LINE_PREP_ADD;
348                         length = diff.getSecondEnd() - diff.getSecondStart() + 1;
349                     }
350                     break;
351                 case Difference.DELETE:
352                     if (which == 0) {
353                         prep = LINE_PREP_REMOVE;
354                         length = diff.getFirstEnd() - diff.getFirstStart() + 1;
355                     }
356                     break;
357                 case Difference.CHANGE:
358                     prep = LINE_PREP_CHANGE;
359                     if (which == 0) {
360                         length = diff.getFirstEnd() - diff.getFirstStart() + 1;
361                     } else {
362                         length = diff.getSecondEnd() - diff.getSecondStart() + 1;
363                     }
364                     break;
365             }
366             if (prep != null) {
367                 isChange = true;
368                 for (int k = 0; k < length; k++, line++) {
369                     content.append(prep);
370                     content.append(br.readLine());
371                     content.append("\n");
372                 }
373             }
374         }
375         if (!isChange) {
376             content.delete(position, content.length());
377         } else {
378             for (int k = 0; k < contextNumLines; k++, line++) {
379                 String JavaDoc lineStr = br.readLine();
380                 if (lineStr == null) break;
381                 content.append(LINE_PREP);
382                 content.append(lineStr);
383                 content.append("\n");
384             }
385         }
386         return line;
387     }
388     
389     public static class TextDiffInfo extends DiffPresenter.Info {
390         
391         private Reader JavaDoc r1;
392         private Reader JavaDoc r2;
393         private Difference[] diffs;
394         private CloneableOpenSupport openSupport;
395         private boolean contextMode;
396         private int contextNumLines;
397         
398         public TextDiffInfo(String JavaDoc name1, String JavaDoc name2, String JavaDoc title1, String JavaDoc title2,
399                             Reader JavaDoc r1, Reader JavaDoc r2, Difference[] diffs) {
400             super(name1, name2, title1, title2, null, false, false);
401             this.r1 = r1;
402             this.r2 = r2;
403             this.diffs = diffs;
404         }
405         
406         public String JavaDoc getName() {
407             String JavaDoc componentName = getName1();
408             String JavaDoc name2 = getName2();
409             if (name2 != null && name2.length() > 0) componentName += " <> "+name2;
410             return componentName;
411         }
412         
413         public String JavaDoc getTitle() {
414             return getTitle1() + " <> " + getTitle2();
415         }
416         
417         public Reader JavaDoc createFirstReader() {
418             return r1;
419         }
420         
421         public Reader JavaDoc createSecondReader() {
422             return r2;
423         }
424         
425         public Difference[] getDifferences() {
426             return diffs;
427         }
428         
429         public CloneableOpenSupport getOpenSupport() {
430             if (openSupport == null) {
431                 openSupport = new TextDiffEditorSupport(this);
432             }
433             return openSupport;
434         }
435         
436         /** Setter for property contextMode.
437          * @param contextMode New value of property contextMode.
438          */

439         public void setContextMode(boolean contextMode, int contextNumLines) {
440             this.contextMode = contextMode;
441             this.contextNumLines = contextNumLines;
442         }
443         
444         /** Getter for property contextMode.
445          * @return Value of property contextMode.
446          */

447         public boolean isContextMode() {
448             return contextMode;
449         }
450         
451         public int getContextNumLines() {
452             return contextNumLines;
453         }
454         
455     }
456 }
457
Popular Tags