All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.javersion.util.AbstractTreeMap Maven / Gradle / Ivy

The newest version!
/*
 *  Copyright 2013 Samppa Saarela
 *
 * 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 org.javersion.util;

import static com.google.common.collect.Iterables.transform;
import static org.javersion.util.AbstractRedBlackTree.Color.RED;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.javersion.util.AbstractTreeMap.Node;

import com.google.common.base.Objects;
import com.google.common.collect.Iterators;

public abstract class AbstractTreeMap>
        extends AbstractRedBlackTree, This> implements Iterable> {

    protected AbstractTreeMap() {
        super();
    }

    protected AbstractTreeMap(Comparator comparator) {
        super(comparator);
    }

    public abstract int size();

    protected abstract Node root();

    protected UpdateContext> updateContext() {
        return updateContext(null);
    }
    protected UpdateContext> updateContext(Merger> merger) {
        return new UpdateContext>(1, merger);
    }

    public V get(Object key) {
        Node node = find(root(), key);
        return node != null ? node.value : null;
    }

    public V max() {
        Node max = findMax(root());
        return max != null ? max.value : null;
    }

    public V min() {
        Node min = findMin(root());
        return min != null ? min.value : null;
    }

    public This assoc(K key, V value) {
        UpdateContext> context = updateContext();
        return doAdd(context, root(), new Node(context, key, value, RED));
    }

    @SuppressWarnings("unchecked")
    public This assocAll(Map map) {
        final UpdateContext> context = updateContext();
        return (This) doAddAll(context, root(), transform(map.entrySet(), (entry) -> entryToNode(entry, context)));
    }

    private Node entryToNode(Entry entry, UpdateContext> context) {
        if (entry instanceof Node) {
            return (Node) entry;
        } else {
            return new Node(context, entry.getKey(), entry.getValue(), RED);
        }
    }

    public This dissoc(Object keyObj) {
        return doRemove(updateContext(), root(), keyObj);
    }

    public This assocAll(Iterable> entries) {
        final UpdateContext> context = updateContext();
        return (This) doAddAll(context, root(), transform(entries, (entry) -> entryToNode(entry, context)));
    }

    public This merge(K key, V value, Merger> merger) {
        final UpdateContext> context = updateContext(merger);
        return doAdd(context, root(), new Node(context, key, value, RED));
    }

    public This mergeAll(Map map, Merger> merger) {
        final UpdateContext> context = updateContext(merger);
        return (This) doAddAll(context, root(), transform(map.entrySet(), (entry) -> entryToNode(entry, context)));
    }

    public This mergeAll(Iterable> entries, Merger> merger) {
        final UpdateContext> context = updateContext(merger);
        return (This) doAddAll(context, root(), transform(entries, (entry) -> entryToNode(entry, context)));
    }

    public This dissoc(Object key, Merger> merger) {
        final UpdateContext> context = updateContext(merger);
        return doRemove(context, root(), key);
    }

    public boolean containsKey(Object key) {
        return find(root(), key) != null;
    }


    @Override
    public Iterator> iterator() {
        return iterator(true);
    }

    public Iterator> iterator(boolean asc) {
        return Iterators.transform(doIterator(root(), true), Map.Entry.class::cast);
    }

    public Iterable> range(K from, K to) {
        return range(from, true, to, false, true);
    }

    public Iterable> range(K from, K to, boolean asc) {
        return range(from, true, to, false, asc);
    }

    public Iterable> range(final K from, final boolean fromInclusive, final K to, final boolean toInclusive) {
        return range(from, fromInclusive, to, toInclusive, true);
    }

    public Iterable> range(final K from, final boolean fromInclusive, final K to, final boolean toInclusive, final boolean asc) {
        return new Iterable>() {
            @Override
            public Iterator> iterator() {
                return Iterators.transform(doRangeIterator(root(), asc, from, fromInclusive, to, toInclusive),  Map.Entry.class::cast);
            }
        };
    }

    static class Node extends AbstractRedBlackTree.Node> implements Map.Entry{
        V value;

        public Node(UpdateContext> context, K key, V value, Color color) {
            this(context, key, value, color, null, null);
        }

        public Node(UpdateContext> context, K key, V value, Color color, Node left, Node right) {
            super(context, key, color, left, right);
            this.value = value;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public Node self() {
            return this;
        }

        @Override
        public V setValue(V value) {
            throw new UnsupportedOperationException();
        }

        @Override
        protected Node cloneWith(UpdateContext> currentContext) {
            return new Node(currentContext, key, value, color, left, right);
        }

        @Override
        protected Node replaceWith(UpdateContext> currentContext, Node node) {
            if (node == this || Objects.equal(this.value, node.value)) {
                return null;
            }
            else if (context.isSameAs(currentContext)) {
                this.value = node.value;
                return this;
            }
            else if (node.context.isSameAs(currentContext)) {
                node.color = this.color;
                node.left = this.left;
                node.right = this.right;
                return node;
            }
            else {
                // This should never happen
                throw new IllegalStateException("node from another UpdateContext");
            }
        }

        public String toString() {
            return getKey() + ": " + getValue();
        }
    }

    static class EntrySpliterator extends RBSpliterator, Node> {

        private final Comparator comparator;

        public EntrySpliterator(Node root, int size, Comparator comparator, boolean immutable) {
            super(root, size, SORTED | DISTINCT | (immutable ? IMMUTABLE : 0));
            this.comparator = comparator;
        }

        protected EntrySpliterator(int sizeEstimate, Comparator comparator, boolean immutable) {
            super(sizeEstimate, SORTED | DISTINCT | (immutable ? IMMUTABLE : 0));
            this.comparator = comparator;
        }

        @Override
        protected RBSpliterator, Node> newSpliterator(int sizeEstimate) {
            return new EntrySpliterator<>(sizeEstimate, comparator, hasCharacteristics(IMMUTABLE));
        }

        @Override
        protected Entry apply(Node node) {
            return node;
        }

        @Override
        public Comparator> getComparator() {
            return Map.Entry.comparingByKey(comparator);
        }
    }

    static class KeySpliterator extends RBSpliterator> {

        private final Comparator comparator;

        public KeySpliterator(Node root, int size, Comparator comparator, boolean immutable) {
            super(root, size, SORTED | DISTINCT | (immutable ? IMMUTABLE : 0));
            this.comparator = comparator;
        }

        protected KeySpliterator(int sizeEstimate, Comparator comparator, boolean immutable) {
            super(sizeEstimate, SORTED | DISTINCT | (immutable ? IMMUTABLE : 0));
            this.comparator = comparator;
        }

        @Override
        protected RBSpliterator> newSpliterator(int sizeEstimate) {
            return new KeySpliterator<>(sizeEstimate, comparator, hasCharacteristics(IMMUTABLE));
        }

        @Override
        protected K apply(Node node) {
            return node.key;
        }

        @Override
        public Comparator getComparator() {
            return comparator;
        }
    }

    static class ValueSpliterator extends RBSpliterator> {

        private final Comparator comparator;

        public ValueSpliterator(Node root, int size, Comparator comparator, boolean immutable) {
            super(root, size, (immutable ? IMMUTABLE : 0));
            this.comparator = comparator;
        }

        protected ValueSpliterator(int sizeEstimate, Comparator comparator, boolean immutable) {
            super(sizeEstimate, (immutable ? IMMUTABLE : 0));
            this.comparator = comparator;
        }

        @Override
        protected RBSpliterator> newSpliterator(int sizeEstimate) {
            return new ValueSpliterator<>(sizeEstimate, comparator, hasCharacteristics(IMMUTABLE));
        }

        @Override
        protected V apply(Node node) {
            return node.value;
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy