Edit.java

  1. /*
  2.  * Copyright (C) 2008-2009, Johannes E. Schindelin <johannes.schindelin@gmx.de> and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.diff;

  11. /**
  12.  * A modified region detected between two versions of roughly the same content.
  13.  * <p>
  14.  * An edit covers the modified region only. It does not cover a common region.
  15.  * <p>
  16.  * Regions should be specified using 0 based notation, so add 1 to the start and
  17.  * end marks for line numbers in a file.
  18.  * <p>
  19.  * An edit where {@code beginA == endA && beginB < endB} is an insert edit, that
  20.  * is sequence B inserted the elements in region <code>[beginB, endB)</code> at
  21.  * <code>beginA</code>.
  22.  * <p>
  23.  * An edit where {@code beginA < endA && beginB == endB} is a delete edit, that
  24.  * is sequence B has removed the elements between <code>[beginA, endA)</code>.
  25.  * <p>
  26.  * An edit where {@code beginA < endA && beginB < endB} is a replace edit, that
  27.  * is sequence B has replaced the range of elements between
  28.  * <code>[beginA, endA)</code> with those found in <code>[beginB, endB)</code>.
  29.  */
  30. public class Edit {
  31.     /** Type of edit */
  32.     public enum Type {
  33.         /** Sequence B has inserted the region. */
  34.         INSERT,

  35.         /** Sequence B has removed the region. */
  36.         DELETE,

  37.         /** Sequence B has replaced the region with different content. */
  38.         REPLACE,

  39.         /** Sequence A and B have zero length, describing nothing. */
  40.         EMPTY;
  41.     }

  42.     int beginA;

  43.     int endA;

  44.     int beginB;

  45.     int endB;

  46.     /**
  47.      * Create a new empty edit.
  48.      *
  49.      * @param as
  50.      *            beginA: start and end of region in sequence A; 0 based.
  51.      * @param bs
  52.      *            beginB: start and end of region in sequence B; 0 based.
  53.      */
  54.     public Edit(int as, int bs) {
  55.         this(as, as, bs, bs);
  56.     }

  57.     /**
  58.      * Create a new edit.
  59.      *
  60.      * @param as
  61.      *            beginA: start of region in sequence A; 0 based.
  62.      * @param ae
  63.      *            endA: end of region in sequence A; must be &gt;= as.
  64.      * @param bs
  65.      *            beginB: start of region in sequence B; 0 based.
  66.      * @param be
  67.      *            endB: end of region in sequence B; must be &gt; = bs.
  68.      */
  69.     public Edit(int as, int ae, int bs, int be) {
  70.         beginA = as;
  71.         endA = ae;

  72.         beginB = bs;
  73.         endB = be;
  74.     }

  75.     /**
  76.      * Get type
  77.      *
  78.      * @return the type of this region
  79.      */
  80.     public final Type getType() {
  81.         if (beginA < endA) {
  82.             if (beginB < endB) {
  83.                 return Type.REPLACE;
  84.             }
  85.             return Type.DELETE;

  86.         }
  87.         if (beginB < endB) {
  88.             return Type.INSERT;
  89.         }
  90.         // beginB == endB)
  91.         return Type.EMPTY;
  92.     }

  93.     /**
  94.      * Whether edit is empty
  95.      *
  96.      * @return {@code true} if the edit is empty (lengths of both a and b is
  97.      *         zero)
  98.      */
  99.     public final boolean isEmpty() {
  100.         return beginA == endA && beginB == endB;
  101.     }

  102.     /**
  103.      * Get start point in sequence A
  104.      *
  105.      * @return start point in sequence A
  106.      */
  107.     public final int getBeginA() {
  108.         return beginA;
  109.     }

  110.     /**
  111.      * Get end point in sequence A
  112.      *
  113.      * @return end point in sequence A
  114.      */
  115.     public final int getEndA() {
  116.         return endA;
  117.     }

  118.     /**
  119.      * Get start point in sequence B
  120.      *
  121.      * @return start point in sequence B
  122.      */
  123.     public final int getBeginB() {
  124.         return beginB;
  125.     }

  126.     /**
  127.      * Get end point in sequence B
  128.      *
  129.      * @return end point in sequence B
  130.      */
  131.     public final int getEndB() {
  132.         return endB;
  133.     }

  134.     /**
  135.      * Get length of the region in A
  136.      *
  137.      * @return length of the region in A
  138.      */
  139.     public final int getLengthA() {
  140.         return endA - beginA;
  141.     }

  142.     /**
  143.      * Get length of the region in B
  144.      *
  145.      * @return return length of the region in B
  146.      */
  147.     public final int getLengthB() {
  148.         return endB - beginB;
  149.     }

  150.     /**
  151.      * Move the edit region by the specified amount.
  152.      *
  153.      * @param amount
  154.      *            the region is shifted by this amount, and can be positive or
  155.      *            negative.
  156.      * @since 4.8
  157.      */
  158.     public final void shift(int amount) {
  159.         beginA += amount;
  160.         endA += amount;
  161.         beginB += amount;
  162.         endB += amount;
  163.     }

  164.     /**
  165.      * Construct a new edit representing the region before cut.
  166.      *
  167.      * @param cut
  168.      *            the cut point. The beginning A and B points are used as the
  169.      *            end points of the returned edit.
  170.      * @return an edit representing the slice of {@code this} edit that occurs
  171.      *         before {@code cut} starts.
  172.      */
  173.     public final Edit before(Edit cut) {
  174.         return new Edit(beginA, cut.beginA, beginB, cut.beginB);
  175.     }

  176.     /**
  177.      * Construct a new edit representing the region after cut.
  178.      *
  179.      * @param cut
  180.      *            the cut point. The ending A and B points are used as the
  181.      *            starting points of the returned edit.
  182.      * @return an edit representing the slice of {@code this} edit that occurs
  183.      *         after {@code cut} ends.
  184.      */
  185.     public final Edit after(Edit cut) {
  186.         return new Edit(cut.endA, endA, cut.endB, endB);
  187.     }

  188.     /**
  189.      * Increase {@link #getEndA()} by 1.
  190.      */
  191.     public void extendA() {
  192.         endA++;
  193.     }

  194.     /**
  195.      * Increase {@link #getEndB()} by 1.
  196.      */
  197.     public void extendB() {
  198.         endB++;
  199.     }

  200.     /**
  201.      * Swap A and B, so the edit goes the other direction.
  202.      */
  203.     public void swap() {
  204.         final int sBegin = beginA;
  205.         final int sEnd = endA;

  206.         beginA = beginB;
  207.         endA = endB;

  208.         beginB = sBegin;
  209.         endB = sEnd;
  210.     }

  211.     /** {@inheritDoc} */
  212.     @Override
  213.     public int hashCode() {
  214.         return beginA ^ endA;
  215.     }

  216.     /** {@inheritDoc} */
  217.     @Override
  218.     public boolean equals(Object o) {
  219.         if (o instanceof Edit) {
  220.             final Edit e = (Edit) o;
  221.             return this.beginA == e.beginA && this.endA == e.endA
  222.                     && this.beginB == e.beginB && this.endB == e.endB;
  223.         }
  224.         return false;
  225.     }

  226.     /** {@inheritDoc} */
  227.     @SuppressWarnings("nls")
  228.     @Override
  229.     public String toString() {
  230.         final Type t = getType();
  231.         return t + "(" + beginA + "-" + endA + "," + beginB + "-" + endB + ")";
  232.     }
  233. }