com.google.cloud.firestore.collection.LLRBValueNode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of google-cloud-firestore Show documentation
Show all versions of google-cloud-firestore Show documentation
Java idiomatic client for Google Cloud Firestore.
/*
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.cloud.firestore.collection;
import com.google.api.core.InternalApi;
import java.util.Comparator;
// Note: This package is copied from https://github.com/firebase/firebase-admin-java/tree/master/
// src/main/java/com/google/firebase/database/collection
@InternalApi
public abstract class LLRBValueNode implements LLRBNode {
private static Color oppositeColor(LLRBNode node) {
return node.isRed() ? Color.BLACK : Color.RED;
}
private final K key;
private final V value;
private LLRBNode left;
private final LLRBNode right;
LLRBValueNode(K key, V value, LLRBNode left, LLRBNode right) {
this.key = key;
this.value = value;
this.left = left == null ? LLRBEmptyNode.getInstance() : left;
this.right = right == null ? LLRBEmptyNode.getInstance() : right;
}
@Override
public LLRBNode getLeft() {
return left;
}
@Override
public LLRBNode getRight() {
return right;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
protected abstract Color getColor();
protected abstract LLRBValueNode copy(
K key, V value, LLRBNode left, LLRBNode right);
@Override
public LLRBValueNode copy(
K key, V value, Color color, LLRBNode left, LLRBNode right) {
K newKey = key == null ? this.key : key;
V newValue = value == null ? this.value : value;
LLRBNode newLeft = left == null ? this.left : left;
LLRBNode newRight = right == null ? this.right : right;
if (color == Color.RED) {
return new LLRBRedValueNode<>(newKey, newValue, newLeft, newRight);
} else {
return new LLRBBlackValueNode<>(newKey, newValue, newLeft, newRight);
}
}
@Override
public LLRBNode insert(K key, V value, Comparator comparator) {
int cmp = comparator.compare(key, this.key);
LLRBValueNode n;
if (cmp < 0) {
// new key is less than current key
LLRBNode newLeft = this.left.insert(key, value, comparator);
n = copy(null, null, newLeft, null);
} else if (cmp == 0) {
// same key
n = copy(key, value, null, null);
} else {
// new key is greater than current key
LLRBNode newRight = this.right.insert(key, value, comparator);
n = copy(null, null, null, newRight);
}
return n.fixUp();
}
@Override
public LLRBNode remove(K key, Comparator comparator) {
LLRBValueNode n = this;
if (comparator.compare(key, n.key) < 0) {
if (!n.left.isEmpty() && !n.left.isRed() && !((LLRBValueNode) n.left).left.isRed()) {
n = n.moveRedLeft();
}
n = n.copy(null, null, n.left.remove(key, comparator), null);
} else {
if (n.left.isRed()) {
n = n.rotateRight();
}
if (!n.right.isEmpty() && !n.right.isRed() && !((LLRBValueNode) n.right).left.isRed()) {
n = n.moveRedRight();
}
if (comparator.compare(key, n.key) == 0) {
if (n.right.isEmpty()) {
return LLRBEmptyNode.getInstance();
} else {
LLRBNode smallest = n.right.getMin();
n =
n.copy(
smallest.getKey(),
smallest.getValue(),
null,
((LLRBValueNode) n.right).removeMin());
}
}
n = n.copy(null, null, null, n.right.remove(key, comparator));
}
return n.fixUp();
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public LLRBNode getMin() {
if (left.isEmpty()) {
return this;
} else {
return left.getMin();
}
}
@Override
public LLRBNode getMax() {
if (right.isEmpty()) {
return this;
} else {
return right.getMax();
}
}
@Override
public void inOrderTraversal(NodeVisitor visitor) {
left.inOrderTraversal(visitor);
visitor.visitEntry(key, value);
right.inOrderTraversal(visitor);
}
@Override
public boolean shortCircuitingInOrderTraversal(ShortCircuitingNodeVisitor visitor) {
if (left.shortCircuitingInOrderTraversal(visitor)) {
if (visitor.shouldContinue(key, value)) {
return right.shortCircuitingInOrderTraversal(visitor);
}
}
return false;
}
@Override
public boolean shortCircuitingReverseOrderTraversal(ShortCircuitingNodeVisitor visitor) {
if (right.shortCircuitingReverseOrderTraversal(visitor)) {
if (visitor.shouldContinue(key, value)) {
return left.shortCircuitingReverseOrderTraversal(visitor);
}
}
return false;
}
// For use by the builder, which is package local
void setLeft(LLRBNode left) {
this.left = left;
}
private LLRBNode removeMin() {
if (left.isEmpty()) {
return LLRBEmptyNode.getInstance();
} else {
LLRBValueNode n = this;
if (!n.getLeft().isRed() && !n.getLeft().getLeft().isRed()) {
n = n.moveRedLeft();
}
n = n.copy(null, null, ((LLRBValueNode) n.left).removeMin(), null);
return n.fixUp();
}
}
private LLRBValueNode moveRedLeft() {
LLRBValueNode n = colorFlip();
if (n.getRight().getLeft().isRed()) {
n = n.copy(null, null, null, ((LLRBValueNode) n.getRight()).rotateRight());
n = n.rotateLeft();
n = n.colorFlip();
}
return n;
}
private LLRBValueNode moveRedRight() {
LLRBValueNode n = colorFlip();
if (n.getLeft().getLeft().isRed()) {
n = n.rotateRight();
n = n.colorFlip();
}
return n;
}
private LLRBValueNode fixUp() {
LLRBValueNode n = this;
if (n.right.isRed() && !n.left.isRed()) {
n = n.rotateLeft();
}
if (n.left.isRed() && ((LLRBValueNode) (n.left)).left.isRed()) {
n = n.rotateRight();
}
if (n.left.isRed() && n.right.isRed()) {
n = n.colorFlip();
}
return n;
}
private LLRBValueNode rotateLeft() {
LLRBValueNode newLeft =
this.copy(null, null, Color.RED, null, ((LLRBValueNode) (this.right)).left);
return (LLRBValueNode) this.right.copy(null, null, this.getColor(), newLeft, null);
}
private LLRBValueNode rotateRight() {
LLRBValueNode newRight =
this.copy(null, null, Color.RED, ((LLRBValueNode) (this.left)).right, null);
return (LLRBValueNode) this.left.copy(null, null, this.getColor(), null, newRight);
}
private LLRBValueNode colorFlip() {
LLRBNode newLeft = this.left.copy(null, null, oppositeColor(this.left), null, null);
LLRBNode newRight = this.right.copy(null, null, oppositeColor(this.right), null, null);
return this.copy(null, null, oppositeColor(this), newLeft, newRight);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy