001/*
002 * ====================================================================
003 *
004 * The Apache Software License, Version 1.1
005 *
006 * Copyright (c) 1999-2003 The Apache Software Foundation.
007 * All rights reserved.
008 *
009 * Redistribution and use in source and binary forms, with or without
010 * modification, are permitted provided that the following conditions
011 * are met:
012 *
013 * 1. Redistributions of source code must retain the above copyright
014 *    notice, this list of conditions and the following disclaimer.
015 *
016 * 2. Redistributions in binary form must reproduce the above copyright
017 *    notice, this list of conditions and the following disclaimer in
018 *    the documentation and/or other materials provided with the
019 *    distribution.
020 *
021 * 3. The end-user documentation included with the redistribution, if
022 *    any, must include the following acknowledgement:
023 *       "This product includes software developed by the
024 *        Apache Software Foundation (http://www.apache.org/)."
025 *    Alternately, this acknowledgement may appear in the software itself,
026 *    if and wherever such third-party acknowledgements normally appear.
027 *
028 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
029 *    Foundation" must not be used to endorse or promote products derived
030 *    from this software without prior written permission. For written
031 *    permission, please contact apache@apache.org.
032 *
033 * 5. Products derived from this software may not be called "Apache"
034 *    nor may "Apache" appear in their names without prior written
035 *    permission of the Apache Software Foundation.
036 *
037 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
038 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
039 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
040 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
041 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
042 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
043 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
044 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
045 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
046 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
047 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
048 * SUCH DAMAGE.
049 * ====================================================================
050 *
051 * This software consists of voluntary contributions made by many
052 * individuals on behalf of the Apache Software Foundation.  For more
053 * information on the Apache Software Foundation, please see
054 * <http://www.apache.org/>.
055 *
056 */
057
058package org.apache.wicket.util.diff;
059
060import java.util.List;
061
062/**
063 * Holds a "delta" difference between to revisions of a text.
064 * 
065 * @version $Revision: 1.1 $ $Date: 2006/03/12 00:24:21 $
066 * 
067 * @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
068 * @author <a href="mailto:bwm@hplb.hpl.hp.com">Brian McBride</a>
069 * @see Diff
070 * @see Chunk
071 * @see Revision modifications
072 * 
073 *      27 Apr 2003 bwm
074 * 
075 *      Added getOriginal() and getRevised() accessor methods Added visitor pattern accept() method
076 */
077
078public abstract class Delta extends ToString
079{
080
081        protected Chunk original;
082
083        protected Chunk revised;
084
085        static Class<?>[][] DeltaClass;
086
087        static
088        {
089                DeltaClass = new Class[2][2];
090                try
091                {
092                        DeltaClass[0][0] = ChangeDelta.class;
093                        DeltaClass[0][1] = AddDelta.class;
094                        DeltaClass[1][0] = DeleteDelta.class;
095                        DeltaClass[1][1] = ChangeDelta.class;
096                }
097                catch (Exception ignored)
098                {
099                }
100        }
101
102        /**
103         * Returns a Delta that corresponds to the given chunks in the original and revised text
104         * respectively.
105         * 
106         * @param orig
107         *            the chunk in the original text.
108         * @param rev
109         *            the chunk in the revised text.
110         * @return Delta
111         */
112        public static Delta newDelta(final Chunk orig, final Chunk rev)
113        {
114                Class<?> c = DeltaClass[orig.size() > 0 ? 1 : 0][rev.size() > 0 ? 1 : 0];
115                Delta result;
116                try
117                {
118                        result = (Delta)c.getDeclaredConstructor().newInstance();
119                }
120                catch (Exception e)
121                {
122                        return null;
123                }
124                result.init(orig, rev);
125                return result;
126        }
127
128        /**
129         * Creates an uninitialized delta.
130         */
131        protected Delta()
132        {
133        }
134
135        /**
136         * Creates a delta object with the given chunks from the original and revised texts.
137         * 
138         * @param orig
139         * @param rev
140         */
141        protected Delta(final Chunk orig, final Chunk rev)
142        {
143                init(orig, rev);
144        }
145
146        /**
147         * Initializes the delta with the given chunks from the original and revised texts.
148         * 
149         * @param orig
150         * @param rev
151         */
152        protected void init(final Chunk orig, final Chunk rev)
153        {
154                original = orig;
155                revised = rev;
156        }
157
158        /**
159         * Verifies that this delta can be used to patch the given text.
160         * 
161         * @param target
162         *            the text to patch.
163         * @throws PatchFailedException
164         *             if the patch cannot be applied.
165         */
166        public abstract void verify(List<Object> target) throws PatchFailedException;
167
168        /**
169         * Applies this delta as a patch to the given text.
170         * 
171         * @param target
172         *            the text to patch.
173         * @throws PatchFailedException
174         *             if the patch cannot be applied.
175         */
176        public final void patch(final List<Object> target) throws PatchFailedException
177        {
178                verify(target);
179                try
180                {
181                        applyTo(target);
182                }
183                catch (Exception e)
184                {
185                        throw new PatchFailedException(e.getMessage());
186                }
187        }
188
189        /**
190         * Applies this delta as a patch to the given text.
191         * 
192         * @param target
193         *            the text to patch.
194         */
195        public abstract void applyTo(List<Object> target);
196
197        /**
198         * Converts this delta into its Unix diff style string representation.
199         * 
200         * @param s
201         *            a {@link StringBuilder StringBuffer} to which the string representation will be
202         *            appended.
203         */
204        @Override
205        public void toString(final StringBuilder s)
206        {
207                original.rangeString(s);
208                s.append("x");
209                revised.rangeString(s);
210                s.append(Diff.NL);
211                original.toString(s, "> ", "\n");
212                s.append("---");
213                s.append(Diff.NL);
214                revised.toString(s, "< ", "\n");
215        }
216
217        /**
218         * Converts this delta into its RCS style string representation.
219         * 
220         * @param s
221         *            a {@link StringBuilder StringBuffer} to which the string representation will be
222         *            appended.
223         * @param EOL
224         *            the string to use as line separator.
225         */
226        public abstract void toRCSString(StringBuilder s, String EOL);
227
228        /**
229         * Converts this delta into its RCS style string representation.
230         * 
231         * @param EOL
232         *            the string to use as line separator.
233         * @return String
234         */
235        public String toRCSString(final String EOL)
236        {
237                StringBuilder s = new StringBuilder();
238                toRCSString(s, EOL);
239                return s.toString();
240        }
241
242        /**
243         * Accessor method to return the chunk representing the original sequence of items
244         * 
245         * @return the original sequence
246         */
247        public Chunk getOriginal()
248        {
249                return original;
250        }
251
252        /**
253         * Accessor method to return the chunk representing the updated sequence of items.
254         * 
255         * @return the updated sequence
256         */
257        public Chunk getRevised()
258        {
259                return revised;
260        }
261
262        /**
263         * Accepts a visitor.
264         * <p>
265         * See the Visitor pattern in "Design Patterns" by the GOF4.
266         * 
267         * @param visitor
268         *            The visitor.
269         */
270        public abstract void accept(RevisionVisitor visitor);
271}