001: /*
002: * ====================================================================
003: *
004: * The Apache Software License, Version 1.1
005: *
006: * Copyright (c) 1999-2003 The Apache Software Foundation. All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright notice,
012: * this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright notice,
015: * this list of conditions and the following disclaimer in the documentation
016: * and/or other materials provided with the distribution.
017: *
018: * 3. The end-user documentation included with the redistribution, if any, must
019: * include the following acknowledgement: "This product includes software
020: * developed by the Apache Software Foundation (http://www.apache.org/)."
021: * Alternately, this acknowledgement may appear in the software itself, if and
022: * wherever such third-party acknowledgements normally appear.
023: *
024: * 4. The names "The Jakarta Project", "Commons", and "Apache Software
025: * Foundation" must not be used to endorse or promote products derived from this
026: * software without prior written permission. For written permission, please
027: * contact apache@apache.org.
028: *
029: * 5. Products derived from this software may not be called "Apache" nor may
030: * "Apache" appear in their names without prior written permission of the Apache
031: * Software Foundation.
032: *
033: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
034: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
035: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE
036: * SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
037: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
038: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
039: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
040: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
041: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
042: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
043: * ====================================================================
044: *
045: * This software consists of voluntary contributions made by many individuals on
046: * behalf of the Apache Software Foundation. For more information on the Apache
047: * Software Foundation, please see <http://www.apache.org/>.
048: *
049: */
050:
051: package wicket.util.diff;
052:
053: import java.util.ArrayList;
054: import java.util.Arrays;
055: import java.util.Iterator;
056: import java.util.List;
057:
058: /**
059: * Holds a information about a parrt of the text involved in a differencing or
060: * patching operation.
061: *
062: * @version $Id: Chunk.java,v 1.1 2006/03/12 00:24:21 juanca Exp $
063: * @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
064: * @see Diff
065: * @see Delta
066: */
067: public class Chunk extends ToString {
068:
069: protected int anchor;
070:
071: protected int count;
072:
073: protected List chunk;
074:
075: /**
076: * Creates a chunk that doesn't copy the original text.
077: *
078: * @param pos
079: * the start position in the text.
080: * @param count
081: * the size of the chunk.
082: */
083: public Chunk(int pos, int count) {
084: this .anchor = pos;
085: this .count = (count >= 0 ? count : 0);
086: }
087:
088: /**
089: * Creates a chunk and saves a copy the original chunk's text.
090: *
091: * @param iseq
092: * the original text.
093: * @param pos
094: * the start position in the text.
095: * @param count
096: * the size of the chunk.
097: */
098: public Chunk(Object[] iseq, int pos, int count) {
099: this (pos, count);
100: chunk = slice(iseq, pos, count);
101: }
102:
103: /**
104: * Creates a chunk that will be displaced in the resulting text, and saves a
105: * copy the original chunk's text.
106: *
107: * @param iseq
108: * the original text.
109: * @param pos
110: * the start position in the text.
111: * @param count
112: * the size of the chunk.
113: * @param offset
114: * the position the chunk should have in the resulting text.
115: */
116: public Chunk(Object[] iseq, int pos, int count, int offset) {
117: this (offset, count);
118: chunk = slice(iseq, pos, count);
119: }
120:
121: /**
122: * Creates a chunk and saves a copy the original chunk's text.
123: *
124: * @param iseq
125: * the original text.
126: * @param pos
127: * the start position in the text.
128: * @param count
129: * the size of the chunk.
130: */
131: public Chunk(List iseq, int pos, int count) {
132: this (pos, count);
133: chunk = slice(iseq, pos, count);
134: }
135:
136: /**
137: * Creates a chunk that will be displaced in the resulting text, and saves a
138: * copy the original chunk's text.
139: *
140: * @param iseq
141: * the original text.
142: * @param pos
143: * the start position in the text.
144: * @param count
145: * the size of the chunk.
146: * @param offset
147: * the position the chunk should have in the resulting text.
148: */
149: public Chunk(List iseq, int pos, int count, int offset) {
150: this (offset, count);
151: chunk = slice(iseq, pos, count);
152: }
153:
154: /**
155: * Returns the anchor position of the chunk.
156: *
157: * @return the anchor position.
158: */
159: public int anchor() {
160: return anchor;
161: }
162:
163: /**
164: * Returns the size of the chunk.
165: *
166: * @return the size.
167: */
168: public int size() {
169: return count;
170: }
171:
172: /**
173: * Returns the index of the first line of the chunk.
174: *
175: * @return int
176: */
177: public int first() {
178: return anchor();
179: }
180:
181: /**
182: * Returns the index of the last line of the chunk.
183: *
184: * @return int
185: */
186: public int last() {
187: return anchor() + size() - 1;
188: }
189:
190: /**
191: * Returns the <i>from</i> index of the chunk in RCS terms.
192: *
193: * @return int
194: */
195: public int rcsfrom() {
196: return anchor + 1;
197: }
198:
199: /**
200: * Returns the <i>to</i> index of the chunk in RCS terms.
201: *
202: * @return int
203: */
204: public int rcsto() {
205: return anchor + count;
206: }
207:
208: /**
209: * Returns the text saved for this chunk.
210: *
211: * @return the text.
212: */
213: public List chunk() {
214: return chunk;
215: }
216:
217: /**
218: * Verifies that this chunk's saved text matches the corresponding text in
219: * the given sequence.
220: *
221: * @param target
222: * the sequence to verify against.
223: * @return true if the texts match.
224: */
225: public boolean verify(List target) {
226: if (chunk == null) {
227: return true;
228: }
229: if (last() > target.size()) {
230: return false;
231: }
232: for (int i = 0; i < count; i++) {
233: if (!target.get(anchor + i).equals(chunk.get(i))) {
234: return false;
235: }
236: }
237: return true;
238: }
239:
240: /**
241: * Delete this chunk from he given text.
242: *
243: * @param target
244: * the text to delete from.
245: */
246: public void applyDelete(List target) {
247: for (int i = last(); i >= first(); i--) {
248: target.remove(i);
249: }
250: }
251:
252: /**
253: * Add the text of this chunk to the target at the given position.
254: *
255: * @param start
256: * where to add the text.
257: * @param target
258: * the text to add to.
259: */
260: public void applyAdd(int start, List target) {
261: Iterator i = chunk.iterator();
262: while (i.hasNext()) {
263: target.add(start++, i.next());
264: }
265: }
266:
267: /**
268: * Provide a string image of the chunk using the an empty prefix and
269: * postfix.
270: *
271: * @param s
272: */
273: public void toString(StringBuffer s) {
274: toString(s, "", "");
275: }
276:
277: /**
278: * Provide a string image of the chunk using the given prefix and postfix.
279: *
280: * @param s
281: * where the string image should be appended.
282: * @param prefix
283: * the text thatshould prefix each line.
284: * @param postfix
285: * the text that should end each line.
286: * @return StringBuffer
287: */
288: public StringBuffer toString(StringBuffer s, String prefix,
289: String postfix) {
290: if (chunk != null) {
291: Iterator i = chunk.iterator();
292: while (i.hasNext()) {
293: s.append(prefix);
294: s.append(i.next());
295: s.append(postfix);
296: }
297: }
298: return s;
299: }
300:
301: /**
302: * Retreives the specified part from a {@link List List}.
303: *
304: * @param seq
305: * the list to retreive a slice from.
306: * @param pos
307: * the start position.
308: * @param count
309: * the number of items in the slice.
310: * @return a {@link List List} containing the specified items.
311: */
312: public static List slice(List seq, int pos, int count) {
313: if (count <= 0) {
314: return new ArrayList(seq.subList(pos, pos));
315: } else {
316: return new ArrayList(seq.subList(pos, pos + count));
317: }
318: }
319:
320: /**
321: * Retrieves a slice from an {@link Object Object} array.
322: *
323: * @param seq
324: * the list to retreive a slice from.
325: * @param pos
326: * the start position.
327: * @param count
328: * the number of items in the slice.
329: * @return a {@link List List} containing the specified items.
330: */
331: public static List slice(Object[] seq, int pos, int count) {
332: return slice(Arrays.asList(seq), pos, count);
333: }
334:
335: /**
336: * Provide a string representation of the numeric range of this chunk.
337: *
338: * @return String
339: */
340: public String rangeString() {
341: StringBuffer result = new StringBuffer();
342: rangeString(result);
343: return result.toString();
344: }
345:
346: /**
347: * Provide a string representation of the numeric range of this chunk.
348: *
349: * @param s
350: * where the string representation should be appended.
351: */
352: public void rangeString(StringBuffer s) {
353: rangeString(s, ",");
354: }
355:
356: /**
357: * Provide a string representation of the numeric range of this chunk.
358: *
359: * @param s
360: * where the string representation should be appended.
361: * @param separ
362: * what to use as line separator.
363: */
364: public void rangeString(StringBuffer s, String separ) {
365: if (size() <= 1) {
366: s.append(Integer.toString(rcsfrom()));
367: } else {
368: s.append(Integer.toString(rcsfrom()));
369: s.append(separ);
370: s.append(Integer.toString(rcsto()));
371: }
372: }
373: }
|