11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2011 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in compliance with the License. You may obtain a copy of the License at
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software distributed under the
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * express or implied. See the License for the specific language governing permissions and
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect;
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstModificationResult.ModificationType.IDENTITY;
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstModificationResult.ModificationType.REBUILDING_CHANGE;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstModificationResult.ModificationType.REBALANCING_CHANGE;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstSide.LEFT;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BstSide.RIGHT;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.BstModificationResult.ModificationType;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The result of a mutation operation performed at a single location in a binary search tree.
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Louis Wasserman
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param <K> The key type of the nodes in the modified binary search tree.
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param <N> The type of the nodes in the modified binary search tree.
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertfinal class BstMutationResult<K, N extends BstNode<K, N>> {
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates a {@code BstMutationResult}.
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param targetKey The key targeted for modification. If {@code originalTarget} or {@code
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *        changedTarget} are non-null, their keys must compare as equal to {@code targetKey}.
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param originalRoot The root of the subtree that was modified.
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param changedRoot The root of the subtree, after the modification and any rebalancing.
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param modificationResult The result of the local modification to an entry.
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K, N extends BstNode<K, N>> BstMutationResult<K, N> mutationResult(
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Nullable K targetKey, @Nullable N originalRoot, @Nullable N changedRoot,
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      BstModificationResult<N> modificationResult) {
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new BstMutationResult<K, N>(targetKey, originalRoot, changedRoot, modificationResult);
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final K targetKey;
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private N originalRoot;
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private N changedRoot;
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final BstModificationResult<N> modificationResult;
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private BstMutationResult(@Nullable K targetKey, @Nullable N originalRoot,
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Nullable N changedRoot, BstModificationResult<N> modificationResult) {
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.targetKey = targetKey;
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.originalRoot = originalRoot;
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.changedRoot = changedRoot;
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.modificationResult = checkNotNull(modificationResult);
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the key which was the target of this modification.
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public K getTargetKey() {
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return targetKey;
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the root of the subtree that was modified.
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public N getOriginalRoot() {
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return originalRoot;
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the root of the subtree, after the modification and any rebalancing was performed.
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public N getChangedRoot() {
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return changedRoot;
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the entry in the original subtree with key {@code targetKey}, if any. This should not
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * be treated as a subtree, but only as an entry, and no guarantees are made about its children
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * when viewed as a subtree.
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public N getOriginalTarget() {
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return modificationResult.getOriginalTarget();
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the result of the modification to {@link #getOriginalTarget()}. This should not be
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * treated as a subtree, but only as an entry, and no guarantees are made about its children when
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * viewed as a subtree.
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public N getChangedTarget() {
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return modificationResult.getChangedTarget();
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ModificationType modificationType() {
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return modificationResult.getType();
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * If this mutation was to an immediate child subtree of the specified root on the specified
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * side, returns the {@code BstMutationResult} of applying the mutation to the appropriate child
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of the specified root and rebalancing using the specified mutation rule.
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public BstMutationResult<K, N> lift(N liftOriginalRoot, BstSide side,
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      BstNodeFactory<N> nodeFactory, BstBalancePolicy<N> balancePolicy) {
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assert liftOriginalRoot != null & side != null & nodeFactory != null & balancePolicy != null;
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    switch (modificationType()) {
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      case IDENTITY:
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.originalRoot = this.changedRoot = liftOriginalRoot;
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      case REBUILDING_CHANGE:
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      case REBALANCING_CHANGE:
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.originalRoot = liftOriginalRoot;
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        N resultLeft = liftOriginalRoot.childOrNull(LEFT);
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        N resultRight = liftOriginalRoot.childOrNull(RIGHT);
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        switch (side) {
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          case LEFT:
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            resultLeft = changedRoot;
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            break;
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          case RIGHT:
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            resultRight = changedRoot;
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            break;
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          default:
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            throw new AssertionError();
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (modificationType() == REBUILDING_CHANGE) {
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          this.changedRoot = nodeFactory.createNode(liftOriginalRoot, resultLeft, resultRight);
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else {
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          this.changedRoot =
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              balancePolicy.balance(nodeFactory, liftOriginalRoot, resultLeft, resultRight);
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      default:
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw new AssertionError();
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
157