Edit.java

  1. /*
  2.  * Copyright (C) 2008-2009, Johannes E. Schindelin <johannes.schindelin@gmx.de>
  3.  * and other copyright owners as documented in the project's IP log.
  4.  *
  5.  * This program and the accompanying materials are made available
  6.  * under the terms of the Eclipse Distribution License v1.0 which
  7.  * accompanies this distribution, is reproduced below, and is
  8.  * available at http://www.eclipse.org/org/documents/edl-v10.php
  9.  *
  10.  * All rights reserved.
  11.  *
  12.  * Redistribution and use in source and binary forms, with or
  13.  * without modification, are permitted provided that the following
  14.  * conditions are met:
  15.  *
  16.  * - Redistributions of source code must retain the above copyright
  17.  *   notice, this list of conditions and the following disclaimer.
  18.  *
  19.  * - Redistributions in binary form must reproduce the above
  20.  *   copyright notice, this list of conditions and the following
  21.  *   disclaimer in the documentation and/or other materials provided
  22.  *   with the distribution.
  23.  *
  24.  * - Neither the name of the Eclipse Foundation, Inc. nor the
  25.  *   names of its contributors may be used to endorse or promote
  26.  *   products derived from this software without specific prior
  27.  *   written permission.
  28.  *
  29.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30.  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42.  */

  43. package org.eclipse.jgit.diff;

  44. /**
  45.  * A modified region detected between two versions of roughly the same content.
  46.  * <p>
  47.  * An edit covers the modified region only. It does not cover a common region.
  48.  * <p>
  49.  * Regions should be specified using 0 based notation, so add 1 to the start and
  50.  * end marks for line numbers in a file.
  51.  * <p>
  52.  * An edit where {@code beginA == endA && beginB < endB} is an insert edit, that
  53.  * is sequence B inserted the elements in region <code>[beginB, endB)</code> at
  54.  * <code>beginA</code>.
  55.  * <p>
  56.  * An edit where {@code beginA < endA && beginB == endB} is a delete edit, that
  57.  * is sequence B has removed the elements between <code>[beginA, endA)</code>.
  58.  * <p>
  59.  * An edit where {@code beginA < endA && beginB < endB} is a replace edit, that
  60.  * is sequence B has replaced the range of elements between
  61.  * <code>[beginA, endA)</code> with those found in <code>[beginB, endB)</code>.
  62.  */
  63. public class Edit {
  64.     /** Type of edit */
  65.     public static enum Type {
  66.         /** Sequence B has inserted the region. */
  67.         INSERT,

  68.         /** Sequence B has removed the region. */
  69.         DELETE,

  70.         /** Sequence B has replaced the region with different content. */
  71.         REPLACE,

  72.         /** Sequence A and B have zero length, describing nothing. */
  73.         EMPTY;
  74.     }

  75.     int beginA;

  76.     int endA;

  77.     int beginB;

  78.     int endB;

  79.     /**
  80.      * Create a new empty edit.
  81.      *
  82.      * @param as
  83.      *            beginA: start and end of region in sequence A; 0 based.
  84.      * @param bs
  85.      *            beginB: start and end of region in sequence B; 0 based.
  86.      */
  87.     public Edit(int as, int bs) {
  88.         this(as, as, bs, bs);
  89.     }

  90.     /**
  91.      * Create a new edit.
  92.      *
  93.      * @param as
  94.      *            beginA: start of region in sequence A; 0 based.
  95.      * @param ae
  96.      *            endA: end of region in sequence A; must be &gt;= as.
  97.      * @param bs
  98.      *            beginB: start of region in sequence B; 0 based.
  99.      * @param be
  100.      *            endB: end of region in sequence B; must be &gt; = bs.
  101.      */
  102.     public Edit(int as, int ae, int bs, int be) {
  103.         beginA = as;
  104.         endA = ae;

  105.         beginB = bs;
  106.         endB = be;
  107.     }

  108.     /**
  109.      * Get type
  110.      *
  111.      * @return the type of this region
  112.      */
  113.     public final Type getType() {
  114.         if (beginA < endA) {
  115.             if (beginB < endB)
  116.                 return Type.REPLACE;
  117.             else /* if (beginB == endB) */
  118.                 return Type.DELETE;

  119.         } else /* if (beginA == endA) */{
  120.             if (beginB < endB)
  121.                 return Type.INSERT;
  122.             else /* if (beginB == endB) */
  123.                 return Type.EMPTY;
  124.         }
  125.     }

  126.     /**
  127.      * Whether edit is empty
  128.      *
  129.      * @return {@code true} if the edit is empty (lengths of both a and b is
  130.      *         zero)
  131.      */
  132.     public final boolean isEmpty() {
  133.         return beginA == endA && beginB == endB;
  134.     }

  135.     /**
  136.      * Get start point in sequence A
  137.      *
  138.      * @return start point in sequence A
  139.      */
  140.     public final int getBeginA() {
  141.         return beginA;
  142.     }

  143.     /**
  144.      * Get end point in sequence A
  145.      *
  146.      * @return end point in sequence A
  147.      */
  148.     public final int getEndA() {
  149.         return endA;
  150.     }

  151.     /**
  152.      * Get start point in sequence B
  153.      *
  154.      * @return start point in sequence B
  155.      */
  156.     public final int getBeginB() {
  157.         return beginB;
  158.     }

  159.     /**
  160.      * Get end point in sequence B
  161.      *
  162.      * @return end point in sequence B
  163.      */
  164.     public final int getEndB() {
  165.         return endB;
  166.     }

  167.     /**
  168.      * Get length of the region in A
  169.      *
  170.      * @return length of the region in A
  171.      */
  172.     public final int getLengthA() {
  173.         return endA - beginA;
  174.     }

  175.     /**
  176.      * Get length of the region in B
  177.      *
  178.      * @return return length of the region in B
  179.      */
  180.     public final int getLengthB() {
  181.         return endB - beginB;
  182.     }

  183.     /**
  184.      * Move the edit region by the specified amount.
  185.      *
  186.      * @param amount
  187.      *            the region is shifted by this amount, and can be positive or
  188.      *            negative.
  189.      * @since 4.8
  190.      */
  191.     public final void shift(int amount) {
  192.         beginA += amount;
  193.         endA += amount;
  194.         beginB += amount;
  195.         endB += amount;
  196.     }

  197.     /**
  198.      * Construct a new edit representing the region before cut.
  199.      *
  200.      * @param cut
  201.      *            the cut point. The beginning A and B points are used as the
  202.      *            end points of the returned edit.
  203.      * @return an edit representing the slice of {@code this} edit that occurs
  204.      *         before {@code cut} starts.
  205.      */
  206.     public final Edit before(Edit cut) {
  207.         return new Edit(beginA, cut.beginA, beginB, cut.beginB);
  208.     }

  209.     /**
  210.      * Construct a new edit representing the region after cut.
  211.      *
  212.      * @param cut
  213.      *            the cut point. The ending A and B points are used as the
  214.      *            starting points of the returned edit.
  215.      * @return an edit representing the slice of {@code this} edit that occurs
  216.      *         after {@code cut} ends.
  217.      */
  218.     public final Edit after(Edit cut) {
  219.         return new Edit(cut.endA, endA, cut.endB, endB);
  220.     }

  221.     /**
  222.      * Increase {@link #getEndA()} by 1.
  223.      */
  224.     public void extendA() {
  225.         endA++;
  226.     }

  227.     /**
  228.      * Increase {@link #getEndB()} by 1.
  229.      */
  230.     public void extendB() {
  231.         endB++;
  232.     }

  233.     /**
  234.      * Swap A and B, so the edit goes the other direction.
  235.      */
  236.     public void swap() {
  237.         final int sBegin = beginA;
  238.         final int sEnd = endA;

  239.         beginA = beginB;
  240.         endA = endB;

  241.         beginB = sBegin;
  242.         endB = sEnd;
  243.     }

  244.     /** {@inheritDoc} */
  245.     @Override
  246.     public int hashCode() {
  247.         return beginA ^ endA;
  248.     }

  249.     /** {@inheritDoc} */
  250.     @Override
  251.     public boolean equals(Object o) {
  252.         if (o instanceof Edit) {
  253.             final Edit e = (Edit) o;
  254.             return this.beginA == e.beginA && this.endA == e.endA
  255.                     && this.beginB == e.beginB && this.endB == e.endB;
  256.         }
  257.         return false;
  258.     }

  259.     /** {@inheritDoc} */
  260.     @SuppressWarnings("nls")
  261.     @Override
  262.     public String toString() {
  263.         final Type t = getType();
  264.         return t + "(" + beginA + "-" + endA + "," + beginB + "-" + endB + ")";
  265.     }
  266. }