KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 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.util.List JavaDoc;
14
15 import org.eclipse.compare.patch.PatchConfiguration;
16 import org.eclipse.core.runtime.Assert;
17
18 /**
19  * A Hunk describes a range of changed lines and some context lines.
20  */

21 public class Hunk {
22     
23     public static final int ADDED = 0x1;
24     public static final int DELETED = 0x2;
25     public static final int CHANGED = 0x4;
26     public static final int UNKNOWN = 0x8;
27     
28     private FileDiff fParent;
29     private int fOldStart, fOldLength;
30     private int fNewStart, fNewLength;
31     private String JavaDoc[] fLines;
32     private int hunkType;
33     
34     public Hunk(FileDiff parent, Hunk toCopy) {
35         fParent = parent;
36         if (fParent != null) {
37             fParent.add(this);
38         }
39         
40         fOldStart = toCopy.fOldStart;
41         fOldLength = toCopy.fOldLength;
42         fNewStart = toCopy.fNewStart;
43         fNewLength = toCopy.fOldLength;
44         fLines = toCopy.fLines;
45         hunkType = toCopy.hunkType;
46     }
47     
48     public Hunk(FileDiff parent, int[] oldRange, int[] newRange, List JavaDoc lines, boolean encounteredPlus, boolean encounteredMinus, boolean encounteredSpace) {
49         
50         fParent= parent;
51         if (fParent != null)
52             fParent.add(this);
53         
54         if (oldRange[0] > 0)
55             fOldStart= oldRange[0]-1; // line number start at 0!
56
else
57             fOldStart= 0;
58         fOldLength= oldRange[1];
59         if (newRange[0] > 0)
60             fNewStart= newRange[0]-1; // line number start at 0!
61
else
62             fNewStart= 0;
63         fNewLength= newRange[1];
64         
65         fLines= (String JavaDoc[]) lines.toArray(new String JavaDoc[lines.size()]);
66         
67         if (encounteredSpace && (encounteredPlus || encounteredMinus)){
68             hunkType = CHANGED;
69         } else if (encounteredPlus && !encounteredMinus && !encounteredSpace){
70             hunkType = ADDED;
71         } else if (!encounteredPlus && encounteredMinus && !encounteredSpace) {
72             hunkType = DELETED;
73         } else {
74             hunkType = UNKNOWN;
75         }
76     }
77
78     /*
79      * Returns the contents of this hunk.
80      * Each line starts with a control character. Their meaning is as follows:
81      * <ul>
82      * <li>
83      * '+': add the line
84      * <li>
85      * '-': delete the line
86      * <li>
87      * ' ': no change, context line
88      * </ul>
89      */

90     String JavaDoc getContent() {
91         StringBuffer JavaDoc sb= new StringBuffer JavaDoc();
92         for (int i= 0; i < fLines.length; i++) {
93             String JavaDoc line= fLines[i];
94             sb.append(line.substring(0, Patcher.length(line)));
95             sb.append('\n');
96         }
97         return sb.toString();
98     }
99     
100     /*
101      * Returns a descriptive String for this hunk.
102      * It is in the form old_start,old_length -> new_start,new_length.
103      */

104     String JavaDoc getDescription() {
105         StringBuffer JavaDoc sb= new StringBuffer JavaDoc();
106         sb.append(Integer.toString(fOldStart));
107         sb.append(',');
108         sb.append(Integer.toString(fOldLength));
109         sb.append(" -> "); //$NON-NLS-1$
110
sb.append(Integer.toString(fNewStart));
111         sb.append(',');
112         sb.append(Integer.toString(fNewLength));
113         return sb.toString();
114     }
115     
116     String JavaDoc getRejectedDescription() {
117         StringBuffer JavaDoc sb= new StringBuffer JavaDoc();
118         sb.append("@@ -"); //$NON-NLS-1$
119
sb.append(Integer.toString(fOldStart));
120         sb.append(',');
121         sb.append(Integer.toString(fOldLength));
122         sb.append(" +"); //$NON-NLS-1$
123
sb.append(Integer.toString(fNewStart));
124         sb.append(',');
125         sb.append(Integer.toString(fNewLength));
126         sb.append(" @@"); //$NON-NLS-1$
127
return sb.toString();
128     }
129     
130     int getHunkType(boolean reverse) {
131         if (reverse) {
132             if (hunkType == ADDED)
133                 return DELETED;
134             if (hunkType == DELETED)
135                 return ADDED;
136         }
137         return hunkType;
138     }
139
140     void setHunkType(int hunkType) {
141         this.hunkType = hunkType;
142     }
143
144     public String JavaDoc[] getLines() {
145         return fLines;
146     }
147
148     /**
149      * Set the parent of this hunk. This method
150      * should only be invoked from {@link FileDiff#add(Hunk)}
151      * @param diff the parent of this hunk
152      */

153     void setParent(FileDiff diff) {
154         if (fParent == diff)
155             return;
156         if (fParent != null)
157             fParent.remove(this);
158         fParent = diff;
159     }
160
161     public FileDiff getParent() {
162         return fParent;
163     }
164     
165     /*
166      * Tries to apply the given hunk on the specified lines.
167      * The parameter shift is added to the line numbers given
168      * in the hunk.
169      */

170     public boolean tryPatch(PatchConfiguration configuration, List JavaDoc lines, int shift) {
171         boolean reverse = configuration.isReversed();
172         int pos= getStart(reverse) + shift;
173         int deleteMatches= 0;
174         for (int i= 0; i < fLines.length; i++) {
175             String JavaDoc s= fLines[i];
176             Assert.isTrue(s.length() > 0);
177             String JavaDoc line= s.substring(1);
178             char controlChar= s.charAt(0);
179             if (controlChar == ' ') { // context lines
180
while (true) {
181                     if (pos < 0 || pos >= lines.size())
182                         return false;
183                     if (linesMatch(configuration, line, (String JavaDoc) lines.get(pos))) {
184                         pos++;
185                         break;
186                     }
187                     return false;
188                 }
189             } else if (isDeletedDelimeter(controlChar, reverse)) {
190                 // deleted lines
191
while (true) {
192                     if (pos < 0 || pos >= lines.size())
193                         return false;
194                     if (linesMatch(configuration, line, (String JavaDoc) lines.get(pos))) {
195                         deleteMatches++;
196                         pos++;
197                         break;
198                     }
199                     
200                     // We must remove all lines at once, return false if this
201
// fails. In other words, all lines considered for deletion
202
// must be found one by one.
203

204                     // if (deleteMatches <= 0)
205
return false;
206                     // pos++;
207
}
208             } else if (isAddedDelimeter(controlChar, reverse)) {
209                 // added lines
210
// we don't have to do anything for a 'try'
211
} else
212                 Assert.isTrue(false, "tryPatch: unknown control character: " + controlChar); //$NON-NLS-1$
213
}
214         return true;
215     }
216     
217     int getStart(boolean reverse) {
218         if (reverse) {
219             return fNewStart;
220         }
221         return fOldStart;
222     }
223     
224     private int getLength(boolean reverse) {
225         if (reverse) {
226             return fNewLength;
227         }
228         return fOldLength;
229     }
230     
231     private int getShift(boolean reverse) {
232         if (reverse) {
233             return fOldLength - fNewLength;
234         }
235         return fNewLength - fOldLength;
236     }
237     
238     int doPatch(PatchConfiguration configuration, List JavaDoc lines, int shift) {
239         boolean reverse = configuration.isReversed();
240         int pos = getStart(reverse) + shift;
241         for (int i= 0; i < fLines.length; i++) {
242             String JavaDoc s= fLines[i];
243             Assert.isTrue(s.length() > 0);
244             String JavaDoc line= s.substring(1);
245             char controlChar= s.charAt(0);
246             if (controlChar == ' ') { // context lines
247
while (true) {
248                     Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in context"); //$NON-NLS-1$
249
if (linesMatch(configuration, line, (String JavaDoc) lines.get(pos))) {
250                         pos++;
251                         break;
252                     }
253                     pos++;
254                 }
255             } else if (isDeletedDelimeter(controlChar, reverse)) {
256                 // deleted lines
257
while (true) {
258                     Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in deleted lines"); //$NON-NLS-1$
259
if (linesMatch(configuration, line, (String JavaDoc) lines.get(pos))) {
260                         break;
261                     }
262                     pos++;
263                 }
264                 lines.remove(pos);
265             } else if (isAddedDelimeter(controlChar, reverse)) {
266                 // added lines
267
if (getLength(reverse) == 0 && pos+1 < lines.size())
268                     lines.add(pos+1, line);
269                 else
270                     lines.add(pos, line);
271                 pos++;
272             } else
273                 Assert.isTrue(false, "doPatch: unknown control character: " + controlChar); //$NON-NLS-1$
274
}
275         return getShift(reverse);
276     }
277
278     private boolean isDeletedDelimeter(char controlChar, boolean reverse) {
279         return (!reverse && controlChar == '-') || (reverse && controlChar == '+');
280     }
281     
282     private boolean isAddedDelimeter(char controlChar, boolean reverse) {
283         return (reverse && controlChar == '-') || (!reverse && controlChar == '+');
284     }
285     
286     /*
287      * Compares two strings.
288      * If fIgnoreWhitespace is true whitespace is ignored.
289      */

290     private boolean linesMatch(PatchConfiguration configuration, String JavaDoc line1, String JavaDoc line2) {
291         if (configuration.isIgnoreWhitespace())
292             return stripWhiteSpace(line1).equals(stripWhiteSpace(line2));
293         if (isIgnoreLineDelimiter()) {
294             int l1= Patcher.length(line1);
295             int l2= Patcher.length(line2);
296             if (l1 != l2)
297                 return false;
298             return line1.regionMatches(0, line2, 0, l1);
299         }
300         return line1.equals(line2);
301     }
302     
303     private boolean isIgnoreLineDelimiter() {
304         return true;
305     }
306
307     /*
308      * Returns the given string with all whitespace characters removed.
309      * Whitespace is defined by <code>Character.isWhitespace(...)</code>.
310      */

311     private String JavaDoc stripWhiteSpace(String JavaDoc s) {
312         StringBuffer JavaDoc sb= new StringBuffer JavaDoc();
313         int l= s.length();
314         for (int i= 0; i < l; i++) {
315             char c= s.charAt(i);
316             if (!Character.isWhitespace(c))
317                 sb.append(c);
318         }
319         return sb.toString();
320     }
321     
322     public String JavaDoc getContents(boolean isAfterState, boolean reverse) {
323         StringBuffer JavaDoc result= new StringBuffer JavaDoc();
324         for (int i= 0; i<fLines.length; i++) {
325             String JavaDoc line= fLines[i];
326             String JavaDoc rest= line.substring(1);
327             char c = line.charAt(0);
328             if (c == ' ') {
329                 result.append(rest);
330             } else if (isDeletedDelimeter(c, reverse) && !isAfterState) {
331                 result.append(rest);
332             } else if (isAddedDelimeter(c, reverse) && isAfterState) {
333                 result.append(rest);
334             }
335         }
336         return result.toString();
337     }
338 }
339
Popular Tags