001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.texteditor.quickdiff.compare.rangedifferencer;
011:
012: import java.util.List;
013:
014: import org.eclipse.core.runtime.Assert;
015:
016: import org.eclipse.jface.text.IDocument;
017:
018: import org.eclipse.ui.internal.texteditor.quickdiff.DiffRegion;
019:
020: /**
021: * Description of a change between two or three ranges of comparable entities.
022: * <p>
023: * <code>RangeDifference</code> objects are the elements of a compare result returned from
024: * the <code>RangeDifferencer</code> <code>find* </code> methods.
025: * Clients use these objects as they are returned from the differencer.
026: * This class is not intended to be instantiated or subclassed.
027: * <p>
028: * Note: A range in the <code>RangeDifference</code> object is given as a start index
029: * and length in terms of comparable entities. However, these entity indices and counts
030: * are not necessarily character positions. For example, if an entity represents a line
031: * in a document, the start index would be a line number and the count would be in lines.
032: * </p>
033: *
034: * @see RangeDifferencer
035: * @since 3.0
036: */
037: public class RangeDifference {
038:
039: /** Two-way change constant indicating no change. */
040: public final static int NOCHANGE = 0;
041: /** Two-way change constant indicating two-way change (same as <code>RIGHT</code>) */
042: public final static int CHANGE = 2;
043:
044: /** Three-way change constant indicating a change in both right and left. */
045: public final static int CONFLICT = 1;
046: /** Three-way change constant indicating a change in right. */
047: public final static int RIGHT = 2;
048: /** Three-way change constant indicating a change in left. */
049: public final static int LEFT = 3;
050: /**
051: * Three-way change constant indicating the same change in both right and left,
052: * that is only the ancestor is different.
053: */
054: public final static int ANCESTOR = 4;
055:
056: /** Constant indicating an unknown change kind. */
057: public final static int ERROR = 5;
058:
059: /** the kind of change: NOCHANGE, CHANGE, LEFT, RIGHT, ANCESTOR, CONFLICT, ERROR */
060: final int fKind;
061:
062: int fLeftStart;
063: int fLeftLength;
064: int fRightStart;
065: int fRightLength;
066: int lAncestorStart;
067: int lAncestorLength;
068: private DiffRegion fRegion;
069:
070: /**
071: * Creates a new range difference with the given change kind.
072: *
073: * @param changeKind the kind of change
074: */
075: public RangeDifference(int changeKind) {
076: fKind = changeKind;
077: }
078:
079: /**
080: * Creates a new <code>RangeDifference</code> with the given change kind
081: * and left and right ranges.
082: *
083: * @param kind the kind of change
084: * @param rightStart start index of entity on right side
085: * @param rightLength number of entities on right side
086: * @param leftStart start index of entity on left side
087: * @param leftLength number of entities on left side
088: */
089: public RangeDifference(int kind, int rightStart, int rightLength,
090: int leftStart, int leftLength) {
091: fKind = kind;
092: fRightStart = rightStart;
093: fRightLength = rightLength;
094: fLeftStart = leftStart;
095: fLeftLength = leftLength;
096: }
097:
098: /**
099: * Creates a new <code>RangeDifference</code> with the given change kind
100: * and left, right, and ancestor ranges.
101: *
102: * @param kind the kind of change
103: * @param rightStart start index of entity on right side
104: * @param rightLength number of entities on right side
105: * @param leftStart start index of entity on left side
106: * @param leftLength number of entities on left side
107: * @param ancestorStart start index of entity on ancestor side
108: * @param ancestorLength number of entities on ancestor side
109: */
110: public RangeDifference(int kind, int rightStart, int rightLength,
111: int leftStart, int leftLength, int ancestorStart,
112: int ancestorLength) {
113: this (kind, rightStart, rightLength, leftStart, leftLength);
114: lAncestorStart = ancestorStart;
115: lAncestorLength = ancestorLength;
116: }
117:
118: /**
119: * Returns the kind of difference.
120: *
121: * @return the kind of difference, one of
122: * <code>NOCHANGE</code>, <code>CHANGE</code>, <code>LEFT</code>, <code>RIGHT</code>,
123: * <code>ANCESTOR</code>, <code>CONFLICT</code>, <code>ERROR</code>
124: */
125: public int kind() {
126: return fKind;
127: }
128:
129: /**
130: * Returns the start index of the entity range on the ancestor side.
131: *
132: * @return the start index of the entity range on the ancestor side
133: */
134: public int ancestorStart() {
135: return lAncestorStart;
136: }
137:
138: /**
139: * Returns the number of entities on the ancestor side.
140: *
141: * @return the number of entities on the ancestor side
142: */
143: public int ancestorLength() {
144: return lAncestorLength;
145: }
146:
147: /**
148: * Returns the end index of the entity range on the ancestor side.
149: *
150: * @return the end index of the entity range on the ancestor side
151: */
152: public int ancestorEnd() {
153: return lAncestorStart + lAncestorLength;
154: }
155:
156: /**
157: * Returns the start index of the entity range on the right side.
158: *
159: * @return the start index of the entity range on the right side
160: */
161: public int rightStart() {
162: return fRightStart;
163: }
164:
165: /**
166: * Returns the number of entities on the right side.
167: *
168: * @return the number of entities on the right side
169: */
170: public int rightLength() {
171: return fRightLength;
172: }
173:
174: /**
175: * Returns the end index of the entity range on the right side.
176: *
177: * @return the end index of the entity range on the right side
178: */
179: public int rightEnd() {
180: return fRightStart + fRightLength;
181: }
182:
183: /**
184: * Returns the start index of the entity range on the left side.
185: *
186: * @return the start index of the entity range on the left side
187: */
188: public int leftStart() {
189: return fLeftStart;
190: }
191:
192: /**
193: * Returns the number of entities on the left side.
194: *
195: * @return the number of entities on the left side
196: */
197: public int leftLength() {
198: return fLeftLength;
199: }
200:
201: /**
202: * Returns the end index of the entity range on the left side.
203: *
204: * @return the end index of the entity range on the left side
205: */
206: public int leftEnd() {
207: return fLeftStart + fLeftLength;
208: }
209:
210: /**
211: * Returns the maximum number of entities in the left, right, and ancestor sides of this range.
212: *
213: * @return the maximum number of entities in the left, right, and ancestor sides of this range
214: */
215: public int maxLength() {
216: return Math.max(fRightLength, Math.max(fLeftLength,
217: lAncestorLength));
218: }
219:
220: /**
221: * Shifts the offset into the left document of the receiver.
222: *
223: * @param shift the number of elements to shift
224: */
225: public void shiftLeft(int shift) {
226: Assert.isTrue(shift + fLeftStart >= 0);
227: fLeftStart += shift;
228: }
229:
230: /**
231: * Shifts the offset into the right document of the receiver.
232: *
233: * @param shift the number of elements to shift
234: */
235: public void shiftRight(int shift) {
236: Assert.isTrue(shift + fRightStart >= 0);
237: fRightStart += shift;
238: }
239:
240: /**
241: * Resizes the receiver <code>shift</code> units, on both sides, by
242: * moving the start of the difference.
243: *
244: * @param shift the number of elements to shift
245: */
246: public void extendStart(int shift) {
247: Assert.isTrue(shift + fRightStart >= 0);
248: Assert.isTrue(shift + fLeftStart >= 0);
249: fRightStart += shift;
250: fRightLength -= shift;
251: fLeftStart += shift;
252: fLeftLength -= shift;
253: }
254:
255: /**
256: * Resizes the receiver <code>shift</code> units, on both sides, by
257: * moving the end of the difference.
258: *
259: * @param shift the number of elements to shift
260: */
261: public void extendEnd(int shift) {
262: Assert.isTrue(shift + fRightLength >= 0);
263: Assert.isTrue(shift + fLeftLength >= 0);
264: fRightLength += shift;
265: fLeftLength += shift;
266: }
267:
268: /*
269: * @see java.lang.Object#equals(java.lang.Object)
270: */
271: public boolean equals(Object obj) {
272: if (obj instanceof RangeDifference) {
273: RangeDifference d = (RangeDifference) obj;
274: return fKind == d.fKind && fRightStart == d.fRightStart
275: && fRightLength == d.fRightLength
276: && fLeftStart == d.fLeftStart
277: && fLeftLength == d.fLeftLength;
278: }
279: return false;
280: }
281:
282: /**
283: * Returns {@link Object#hashCode()}.
284: *
285: * @return the hash code which is {@link Object#hashCode()}
286: */
287: public final int hashCode() {
288: return super .hashCode();
289: }
290:
291: /**
292: * Returns the diff region corresponding to this range difference.
293: *
294: * @param differences the list of differences around this one difference
295: * @param source the original document (left document) that this difference refers to
296: * @return a <code>DiffRegion</code> corresponding to this difference
297: */
298: public DiffRegion getDiffRegion(List differences, IDocument source) {
299: if (fRegion == null)
300: fRegion = new DiffRegion(this , 0, differences, source);
301: return fRegion;
302: }
303:
304: /*
305: * @since 3.2
306: */
307: public String toString() {
308: StringBuffer buf = new StringBuffer("RangeDifference {"); //$NON-NLS-1$
309: switch (fKind) {
310: case NOCHANGE:
311: buf.append("NOCHANGE"); //$NON-NLS-1$
312: break;
313: case CHANGE:
314: buf.append("CHANGE/RIGHT"); //$NON-NLS-1$
315: break;
316: case CONFLICT:
317: buf.append("CONFLICT"); //$NON-NLS-1$
318: break;
319: case LEFT:
320: buf.append("LEFT"); //$NON-NLS-1$
321: break;
322: case ERROR:
323: buf.append("ERROR"); //$NON-NLS-1$
324: break;
325: case ANCESTOR:
326: buf.append("ANCESTOR"); //$NON-NLS-1$
327: break;
328: default:
329: break;
330: }
331:
332: buf.append(", Left: [" + fLeftStart + "+" + fLeftLength + ")"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
333: buf
334: .append(", Right: [" + fRightStart + "+" + fRightLength + ")"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
335: buf.append("]"); //$NON-NLS-1$
336:
337: return buf.toString();
338: }
339: }
|