Package com.almworks.jira.structure.api.forest

Source Code of com.almworks.jira.structure.api.forest.ForestOp$Move

package com.almworks.jira.structure.api.forest;

import com.almworks.integers.LongArray;
import com.almworks.integers.LongList;
import com.almworks.integers.util.LongListConcatenation;
import com.almworks.jira.structure.api.StructureManager;
import org.jetbrains.annotations.NotNull;

import static com.almworks.jira.structure.util.StructureUtil.lastOrZero;

/**
* <p>A <code>ForestOp</code> represents a single operation on a forest, such as move or delete.
* A list of <code>ForestOp</code>s in the {@link ForestUpdate.Incremental} define a sequence
* of operations that bring a forest from one version to another, newer version.
* </p>
*
* <p>There are several types of the operations, all defined as the inner classes of <code>ForestOp:</code></p>
*
* <ul>
*   <li>{@link ForestOp.Add} - add operation;</li>
*   <li>{@link ForestOp.Remove} - remove operation;</li>
*   <li>{@link ForestOp.Move} - move operation.</li>
* </ul>
*
* <p>Typically, a client code would inspect the exact type of each <code>ForestOp</code>
* and perform the required action to bring their forest to the up-to-date state.
* </p>
*
* @see ForestUpdate
* @see StructureManager#getForestUpdate
* @author Igor Sereda
*/
public abstract class ForestOp {
  private final LongList myParents;
  private final LongList myAncestors;

  protected ForestOp(LongList parents, LongList ancestors) {
    assert parents != null;
    assert ancestors != null;
    myParents = parents;
    myAncestors = ancestors;
  }

  /**
   * <p>This method returns the list of issues that were subject to the operation, or possibly
   * the reduced set of these issues if other affected issues can be implied from the returned
   * list and the current forest state.</p>
   *
   * <p>Namely, {@link ForestOp.Move} returns only the top
   * issue in this list because all other issues moved can be figured
   * from the state after the operation. If it wasn't the last operation then this
   * holds true transitively via other operations.</p>
   *
   * @return a list of issues affected by this operation
   */
  @NotNull
  public abstract LongList getAffectedIssues();

  /**
   * @return a list of issues that are parents or used to be parents of the affected issues,
   * may contain issues from the affected issues set if one issue was (is) a parent of another
   */
  @NotNull
  public LongList getParents() {
    return myParents;
  }

  /**
   * @return a list of all ancestors of the affected issues,
   * may contain issues from the affected issues set if one issue was (is) a parent of another
   */
  public LongList getAncestors() {
    return myAncestors;
  }

  /**
   * @return issues that are used to define this operation - used to check whether the operation
   * is visible to a user
   */
  @NotNull
  public abstract LongList getAnchorIssues();

  /**
   * Represents move operation.
   *
   * @see ForestOp
   * @see ForestAccessor#moveSubtree
   * @see ForestAccessor#mergeForest
   */
  public static class Move extends ForestOp {
    private final long myIssue;
    private final Forest myMovedSubtree;
    private final LongList myParentPathFrom;
    private final long myAfterFrom;
    private final LongList myParentPathTo;
    private final long myAfterTo;
    private final int myDirection;
    private final LongArray myAnchor = new LongArray(3);

    public Move(
      long issue, Forest movedSubtree, LongList parentPathFrom, long afterFrom,
      LongList parentPathTo, long afterTo, int direction, LongList parents, LongList ancestors)
    {
      super(parents, ancestors);
      myIssue = issue;
      myMovedSubtree = movedSubtree.makeImmutable();
      myParentPathFrom = parentPathFrom;
      myAfterFrom = afterFrom;
      myParentPathTo = parentPathTo;
      myAfterTo = afterTo;
      myDirection = direction;
      long under = lastOrZero(parentPathTo);
      myAnchor.add(issue);
      if (under > 0) myAnchor.add(under);
      if (myAfterTo > 0) myAnchor.add(myAfterTo);
    }

    @NotNull
    public LongList getAffectedIssues() {
      return LongArray.create(myIssue);
    }

    @NotNull
    public LongList getAnchorIssues() {
      return myAnchor;
    }

    /**
     * @return The new parent of the moved issue, 0 if top level.
     */
    public long getUnder() {
      return lastOrZero(myParentPathTo);
    }

    /**
     * @return The new immediately preceding sibling of the moved issue, 0 if none.
     */
    public long getAfter() {
      return myAfterTo;
    }

    /**
     * @return The moved issue.
     */
    public long getIssue() {
      return myIssue;
    }

    /**
     * @return The whole moved subtree rooted at {@link #getIssue()}.
     */
    @NotNull
    public Forest getMovedSubtree() {
      return myMovedSubtree;
    }

    /**
     * @return The old parent path of the moved issue.
     * @see Forest#getParentPathForIndex(int)
     */
    @NotNull
    public LongList getParentPathFrom() {
      return myParentPathFrom;
    }

    /**
     * @return The old immediately preceding sibling of the moved issue, 0 if none.
     */
    public long getAfterFrom() {
      return myAfterFrom;
    }

    /**
     * @return The new parent path of the moved issue.
     * @see Forest#getParentPathForIndex(int)
     */
    @NotNull
    public LongList getParentPathTo() {
      return myParentPathTo;
    }

    /**
     * @return Positive if the issue has been moved downwards; negative if upwards.
     */
    public int getDirection() {
      return myDirection;
    }

    public String toString() {
      return "move(" + myParentPathFrom + "/" + myAfterFrom + "=>" + myParentPathTo + "/" + myAfterTo + "," + myMovedSubtree + ")";
    }
  }


  /**
   * Represents the add operation.
   *
   * @see ForestOp
   * @see ForestAccessor#mergeForest
   * @see ForestAccessor#addIssue
   */
  public static class Add extends ForestOp {
    private final Forest myForest;
    private final LongList myParentPath;
    private final long myAfter;
    private final LongList myAnchor;

    public Add(Forest forest, LongList parentPath, long after, LongList parents, LongList ancestors) {
      super(parents, ancestors);
      assert forest.size() > 0 : forest + " " + parentPath + " " + after;
      myForest = forest.makeImmutable();
      myParentPath = parentPath;
      myAfter = after;
      long under = lastOrZero(parentPath);
      if (under > 0 || after > 0) {
        LongArray array = new LongArray();
        if (under > 0) array.add(under);
        if (after > 0) array.add(after);
        myAnchor = new LongListConcatenation(array, myForest.getIssues());
      } else {
        myAnchor = myForest.getIssues();
      }
    }

    @NotNull
    public LongList getAffectedIssues() {
      return myForest.getIssues();
    }

    @NotNull
    public LongList getAnchorIssues() {
      return myAnchor;
    }

    /**
     * @return The added forest.
     */
    @NotNull
    public Forest getAddedForest() {
      return myForest;
    }

    /**
     * @return The parent path of the (roots of the) added forest.
     * @see Forest#getParentPathForIndex(int)
     */
    @NotNull
    public LongList getParentPath() {
      return myParentPath;
    }

    /**
     * @return The parent of the (roots of the) added forest, 0 if top level.
     */
    public long getUnder() {
      return lastOrZero(myParentPath);
    }

    /**
     * @return The immediately preceding sibling of the (first root of the) added forest.
     */
    public long getAfter() {
      return myAfter;
    }

    public String toString() {
      return "add(" + myParentPath + "/" + myAfter + "," + myForest + ")";
    }
  }


  /**
   * Represents the remove operation.
   *
   * @see ForestOp
   * @see ForestAccessor#removeSubtree
   */
  public static class Remove extends ForestOp {
    private final long myIssue;
    private final Forest myRemovedSubtree;
    private final LongList myParentPath;
    private final long myAfter;

    public Remove(long issue, Forest removedSubtree, LongList parentPath, long after, LongList parents, LongList ancestors) {
      super(parents, ancestors);
      myIssue = issue;
      myRemovedSubtree = removedSubtree;
      myParentPath = parentPath;
      myAfter = after;
      assert removedSubtree.isEmpty() || removedSubtree.getIssues().get(0) == issue : issue + " " + removedSubtree;
    }

    /**
     * @return The removed issue.
     */
    public long getIssue() {
      return myIssue;
    }

    /**
     * @return The whole removed subtree rooted at {@link #getIssue()}.
     */
    @NotNull
    public Forest getRemovedSubtree() {
      return myRemovedSubtree;
    }

    /**
     * @return The parent path of the removed issue in the original forest.
     * @see Forest#getParentPathForIndex(int)
     */
    @NotNull
    public LongList getParentPath() {
      return myParentPath;
    }

    /**
     * @return The immediately preceding sibling of the removed issue in the original forest, 0 if none.
     */
    public long getAfter() {
      return myAfter;
    }

    @NotNull
    public LongList getAffectedIssues() {
      return myRemovedSubtree.getIssues();
    }

    @NotNull
    public LongList getAnchorIssues() {
      return myRemovedSubtree.isEmpty() ? LongList.EMPTY : LongArray.create(myIssue);
    }

    public String toString() {
      return "remove(" + myParentPath + "/" + myAfter + "," + myRemovedSubtree + ")";
    }
  }
}
TOP

Related Classes of com.almworks.jira.structure.api.forest.ForestOp$Move

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.