KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > compare > internal > patch > FileDiffResult


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.compare.internal.patch;
12
13 import java.io.*;
14 import java.util.*;
15
16 import org.eclipse.compare.internal.CompareUIPlugin;
17 import org.eclipse.compare.internal.Utilities;
18 import org.eclipse.compare.patch.*;
19 import org.eclipse.compare.structuremergeviewer.Differencer;
20 import org.eclipse.core.resources.*;
21 import org.eclipse.core.runtime.*;
22 import org.eclipse.osgi.util.NLS;
23
24 public class FileDiffResult implements IFilePatchResult {
25
26     private FileDiff fDiff;
27     private boolean fMatches= false;
28     private boolean fDiffProblem;
29     private String JavaDoc fErrorMessage;
30     private Map fHunkResults = new HashMap();
31     private List fBeforeLines, fAfterLines;
32     private final PatchConfiguration configuration;
33     private String JavaDoc charset;
34     private int fuzz;
35     
36     public FileDiffResult(FileDiff diff, PatchConfiguration configuration) {
37         super();
38         fDiff = diff;
39         this.configuration = configuration;
40     }
41     
42     public PatchConfiguration getConfiguration() {
43         return configuration;
44     }
45     
46     public boolean canApplyHunk(Hunk hunk) {
47         HunkResult result = getHunkResult(hunk);
48         return result.isOK() && !fDiffProblem;
49     }
50     
51     /**
52      * Refreshes the state of the diff to {no matches, no problems} and checks to see what hunks contained
53      * by this Diff can actually be applied.
54      *
55      * Checks to see:
56      * 1) if the target file specified in fNewPath exists and is patchable
57      * 2) which hunks contained by this diff can actually be applied to the file
58      * @param storage the contents being patched or <code>null</code> for an addition
59      * @param monitor a progress monitor or <code>null</code> if no progress monitoring is desired
60      */

61      public void refresh(IStorage storage, IProgressMonitor monitor) {
62         fMatches= false;
63         fDiffProblem= false;
64         boolean create= false;
65         charset = Utilities.getCharset(storage);
66         //If this diff is an addition, make sure that it doesn't already exist
67
boolean exists = targetExists(storage);
68         if (fDiff.getDiffType(getConfiguration().isReversed()) == Differencer.ADDITION) {
69             if ((!exists || isEmpty(storage)) && canCreateTarget(storage)) {
70                 fMatches= true;
71             } else {
72                 // file already exists
73
fDiffProblem= true;
74                 fErrorMessage= PatchMessages.PreviewPatchPage_FileExists_error;
75             }
76             create= true;
77         } else { //This diff is not an addition, try to find a match for it
78
//Ensure that the file described by the path exists and is modifiable
79
if (exists) {
80                 fMatches= true;
81             } else {
82                 // file doesn't exist
83
fDiffProblem= true;
84                 fErrorMessage= PatchMessages.PreviewPatchPage_FileDoesNotExist_error;
85             }
86         }
87
88         if (fDiffProblem) {
89             // We couldn't find the target file or the patch is trying to add a
90
// file that already exists but we need to initialize the hunk
91
// results for display
92
fBeforeLines = new ArrayList(getLines(storage, false));
93             fAfterLines = fMatches ? new ArrayList() : fBeforeLines;
94             Hunk[] hunks = fDiff.getHunks();
95             for (int i = 0; i < hunks.length; i++) {
96                 Hunk hunk = hunks[i];
97                 HunkResult result = getHunkResult(hunk);
98                 result.setMatches(false);
99             }
100         } else {
101             // If this diff has no problems discovered so far, try applying the patch
102
patch(getLines(storage, create), monitor);
103         }
104
105         if (containsProblems()) {
106             if (fMatches) {
107                 // Check to see if we have at least one hunk that matches
108
fMatches = false;
109                 Hunk[] hunks = fDiff.getHunks();
110                 for (int i = 0; i < hunks.length; i++) {
111                     Hunk hunk = hunks[i];
112                     HunkResult result = getHunkResult(hunk);
113                     if (result.isOK()) {
114                         fMatches = true;
115                         break;
116                     }
117                 }
118             }
119         }
120     }
121
122     protected boolean canCreateTarget(IStorage storage) {
123         return true;
124     }
125
126     protected boolean targetExists(IStorage storage) {
127         return storage != null;
128     }
129     
130     protected List getLines(IStorage storage, boolean create) {
131         List lines = Patcher.load(storage, create);
132         return lines;
133     }
134     
135     protected boolean isEmpty(IStorage storage) {
136         if (storage == null)
137             return true;
138         return Patcher.load(storage, false).isEmpty();
139     }
140
141     /*
142      * Tries to patch the given lines with the specified Diff.
143      * Any hunk that couldn't be applied is returned in the list failedHunks.
144      */

145     public void patch(List lines, IProgressMonitor monitor) {
146         fBeforeLines = new ArrayList();
147         fBeforeLines.addAll(lines);
148         if (getConfiguration().getFuzz() == -1) {
149             fuzz = calculateFuzz(fBeforeLines, monitor);
150         }
151         int shift= 0;
152         Hunk[] hunks = fDiff.getHunks();
153         for (int i = 0; i < hunks.length; i++) {
154             Hunk hunk = hunks[i];
155             HunkResult result = getHunkResult(hunk);
156             result.setShift(shift);
157             if (result.patch(lines)) {
158                 shift = result.getShift();
159             }
160         }
161         fAfterLines = lines;
162     }
163     
164     protected boolean getDiffProblem() {
165         return fDiffProblem;
166     }
167
168     /**
169      * Returns whether this Diff has any problems
170      * @return true if this Diff or any of its children Hunks have a problem, false if it doesn't
171      */

172     protected boolean containsProblems() {
173         if (fDiffProblem)
174             return true;
175         for (Iterator iterator = fHunkResults.values().iterator(); iterator.hasNext();) {
176             HunkResult result = (HunkResult) iterator.next();
177             if (!result.isOK())
178                 return true;
179         }
180         return false;
181     }
182     
183     public String JavaDoc getLabel() {
184         String JavaDoc label= getTargetPath().toString();
185         if (this.fDiffProblem)
186             return NLS.bind(PatchMessages.Diff_2Args, new String JavaDoc[] {label, fErrorMessage});
187         return label;
188     }
189     
190     public boolean hasMatches() {
191         return fMatches;
192     }
193
194     /**
195      * Return the lines of the target file with all matched hunks applied.
196      * @return the lines of the target file with all matched hunks applied
197      */

198     public List getLines() {
199         return fAfterLines;
200     }
201
202     /**
203      * Calculate the fuzz factor that will allow the most hunks to be matched.
204      * @param lines the lines of the target file
205      * @param monitor a progress monitor
206      * @return the fuzz factor or <code>-1</code> if no hunks could be matched
207      */

208     public int calculateFuzz(List lines, IProgressMonitor monitor) {
209         if (monitor == null)
210             monitor = new NullProgressMonitor();
211         fBeforeLines = new ArrayList();
212         fBeforeLines.addAll(lines);
213         // TODO: What about deletions?
214
if (fDiff.getDiffType(getConfiguration().isReversed()) == Differencer.ADDITION) {
215             // Additions don't need to adjust the fuzz factor
216
// TODO: What about the after lines?
217
return -1;
218         }
219         int shift= 0;
220         int fuzz1 = 0;
221         String JavaDoc name = getTargetPath() != null ? getTargetPath().lastSegment() : ""; //$NON-NLS-1$
222
Hunk[] hunks = fDiff.getHunks();
223         for (int j = 0; j < hunks.length; j++) {
224             Hunk h = hunks[j];
225             monitor.subTask(NLS.bind(PatchMessages.PreviewPatchPage_GuessFuzzProgress_format, new String JavaDoc[] {name, Integer.toString(j + 1)}));
226             HunkResult result = getHunkResult(h);
227             result.setShift(shift);
228             int f= result.calculateFuzz(lines, monitor);
229             if (f >= 0) {
230                 shift = result.getShift();
231             }
232             if (f>fuzz1)
233                 fuzz1= f;
234             monitor.worked(1);
235         }
236         fAfterLines = lines;
237         return fuzz1;
238     }
239     
240     public IPath getTargetPath() {
241         return fDiff.getStrippedPath(getConfiguration().getPrefixSegmentStripCount(), getConfiguration().isReversed());
242     }
243
244     private HunkResult getHunkResult(Hunk hunk) {
245         HunkResult result = (HunkResult)fHunkResults.get(hunk);
246         if (result == null) {
247             result = new HunkResult(this, hunk);
248             fHunkResults .put(hunk, result);
249         }
250         return result;
251     }
252
253     List getFailedHunks() {
254         List failedHunks = new ArrayList();
255         for (Iterator iterator = fHunkResults.values().iterator(); iterator.hasNext();) {
256             HunkResult result = (HunkResult) iterator.next();
257             if (!result.isOK())
258                 failedHunks.add(result.getHunk());
259         }
260         return failedHunks;
261     }
262     
263     private HunkResult[] getFailedHunkResults() {
264         List failedHunks = new ArrayList();
265         for (Iterator iterator = fHunkResults.values().iterator(); iterator.hasNext();) {
266             HunkResult result = (HunkResult) iterator.next();
267             if (!result.isOK())
268                 failedHunks.add(result);
269         }
270         return (HunkResult[]) failedHunks.toArray(new HunkResult[failedHunks.size()]);
271     }
272
273     public FileDiff getDiff() {
274         return fDiff;
275     }
276
277     List getBeforeLines() {
278         return fBeforeLines;
279     }
280
281     List getAfterLines() {
282         return fAfterLines;
283     }
284
285     public HunkResult[] getHunkResults() {
286         return (HunkResult[]) fHunkResults.values().toArray(new HunkResult[fHunkResults.size()]);
287     }
288
289     public InputStream getOriginalContents() {
290         String JavaDoc contents = Patcher.createString(isPreserveLineDelimeters(), getBeforeLines());
291         return asInputStream(contents, getCharset());
292     }
293
294     public InputStream getPatchedContents() {
295         String JavaDoc contents = Patcher.createString(isPreserveLineDelimeters(), getLines());
296         return asInputStream(contents, getCharset());
297     }
298
299     public String JavaDoc getCharset() {
300         return charset;
301     }
302
303     protected boolean isPreserveLineDelimeters() {
304         return false;
305     }
306
307     public IHunk[] getRejects() {
308         return getFailedHunkResults();
309     }
310
311     public boolean hasRejects() {
312         return getFailedHunkResults().length > 0;
313     }
314     
315     public static InputStream asInputStream(String JavaDoc contents, String JavaDoc charSet) {
316         byte[] bytes = null;
317         if (charSet != null) {
318             try {
319                 bytes = contents.getBytes(charSet);
320             } catch (UnsupportedEncodingException e) {
321                 CompareUIPlugin.log(e);
322             }
323         }
324         if (bytes == null) {
325             bytes = contents.getBytes();
326         }
327         return new ByteArrayInputStream(bytes);
328     }
329
330     public int getFuzz() {
331         int cf = configuration.getFuzz();
332         if (cf == -1) {
333             return fuzz;
334         }
335         return cf;
336     }
337     
338 }
339
Popular Tags