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

org.dizitart.no2.index.IndexMap Maven / Gradle / Ivy

/*
 * Copyright (c) 2017-2021 Nitrite author or authors.
 *
 * 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.dizitart.no2.index;

import lombok.Getter;
import lombok.Setter;
import org.dizitart.no2.collection.NitriteId;
import org.dizitart.no2.common.DBNull;
import org.dizitart.no2.common.DBValue;
import org.dizitart.no2.common.tuples.Pair;
import org.dizitart.no2.store.NitriteMap;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author Anindya Chatterjee
 * @since 4.0
 */
@SuppressWarnings("unchecked")
public class IndexMap {
    private NitriteMap nitriteMap;
    private NavigableMap navigableMap;

    @Getter
    @Setter
    private boolean reverseScan;

    /**
     * Instantiates a new {@link IndexMap}.
     *
     * @param nitriteMap the nitrite map
     */
    public IndexMap(NitriteMap nitriteMap) {
        this.nitriteMap = nitriteMap;
    }

    /**
     * Instantiates a new {@link IndexMap}.
     *
     * @param navigableMap the navigable map
     */
    public IndexMap(NavigableMap navigableMap) {
        this.navigableMap = navigableMap;
    }

    public > T firstKey() {
        DBValue dbKey;
        if (nitriteMap != null) {
            dbKey = nitriteMap.firstKey();
        } else if (navigableMap != null) {
            dbKey = navigableMap.firstKey();
        } else {
            return null;
        }

        return dbKey == null || dbKey instanceof DBNull ? null : (T) dbKey.getValue();
    }

    public > T lastKey() {
        DBValue dbKey;
        if (nitriteMap != null) {
            dbKey = nitriteMap.lastKey();
        } else if (navigableMap != null) {
            dbKey = navigableMap.lastKey();
        } else {
            return null;
        }

        return dbKey == null || dbKey instanceof DBNull ? null : (T) dbKey.getValue();
    }

    /**
     * Get the largest key that is smaller than the given key, or null if no
     * such key exists.
     *
     * @param  the type parameter
     * @param key the key
     * @return the t
     */
    public > T lowerKey(T key) {
        DBValue dbKey = key == null ? DBNull.getInstance() : new DBValue(key);
        if (nitriteMap != null) {
            dbKey = nitriteMap.lowerKey(dbKey);
        } else if (navigableMap != null) {
            dbKey = navigableMap.lowerKey(dbKey);
        }

        return dbKey == null || dbKey instanceof DBNull ? null : (T) dbKey.getValue();
    }

    /**
     * Get the smallest key that is larger than the given key, or null if no
     * such key exists.
     *
     * @param  the type parameter
     * @param key the key
     * @return the t
     */
    public > T higherKey(T key) {
        DBValue dbKey = key == null ? DBNull.getInstance() : new DBValue(key);
        if (nitriteMap != null) {
            dbKey = nitriteMap.higherKey(dbKey);
        } else if (navigableMap != null) {
            dbKey = navigableMap.higherKey(dbKey);
        }

        return dbKey == null || dbKey instanceof DBNull ? null : (T) dbKey.getValue();
    }

    /**
     * Get the smallest key that is larger or equal to this key.
     *
     * @param  the type parameter
     * @param key the key
     * @return the t
     */
    public > T ceilingKey(T key) {
        DBValue dbKey = key == null ? DBNull.getInstance() : new DBValue(key);
        if (nitriteMap != null) {
            dbKey = nitriteMap.ceilingKey(dbKey);
        } else if (navigableMap != null) {
            dbKey = navigableMap.ceilingKey(dbKey);
        }

        return dbKey == null || dbKey instanceof DBNull ? null : (T) dbKey.getValue();
    }

    /**
     * Get the largest key that is smaller or equal to this key.
     *
     * @param  the type parameter
     * @param key the key
     * @return the t
     */
    public > T floorKey(T key) {
        DBValue dbKey = key == null ? DBNull.getInstance() : new DBValue(key);
        if (nitriteMap != null) {
            dbKey = nitriteMap.floorKey(dbKey);
        } else if (navigableMap != null) {
            dbKey = navigableMap.floorKey(dbKey);
        }

        return dbKey == null || dbKey instanceof DBNull ? null : (T) dbKey.getValue();
    }

    /**
     * Gets the value mapped with the specified key or null otherwise.
     *
     * @param comparable the comparable
     * @return the object
     */
    public Object get(Comparable comparable) {
        DBValue dbKey = comparable == null ? DBNull.getInstance() : new DBValue(comparable);
        if (nitriteMap != null) {
            return nitriteMap.get(dbKey);
        } else if (navigableMap != null) {
            return navigableMap.get(dbKey);
        }
        return null;
    }

    /**
     * Returns the iterable entries of the indexed items.
     *
     * @return the iterable
     */
    public Iterable, ?>> entries() {
        if (nitriteMap != null) {
            Iterator> entryIterator;
            if (!reverseScan) {
                entryIterator = nitriteMap.entries().iterator();
            } else {
                entryIterator = nitriteMap.reversedEntries().iterator();
            }

            return (Iterable, ?>>) () -> new Iterator<>() {
                @Override
                public boolean hasNext() {
                    return entryIterator.hasNext();
                }

                @Override
                public Pair, ?> next() {
                    Pair next = entryIterator.next();
                    DBValue dbKey = next.getFirst();
                    if (dbKey instanceof DBNull) {
                        return new Pair<>(null, next.getSecond());
                    } else {
                        return new Pair<>(dbKey.getValue(), next.getSecond());
                    }
                }
            };
        } else if (navigableMap != null) {
            Iterator> entryIterator;
            if (reverseScan) {
                entryIterator = navigableMap.descendingMap().entrySet().iterator();
            } else {
                entryIterator = navigableMap.entrySet().iterator();
            }

            return (Iterable, ?>>) () -> new Iterator, ?>>() {
                @Override
                public boolean hasNext() {
                    return entryIterator.hasNext();
                }

                @Override
                public Pair, ?> next() {
                    Map.Entry next = entryIterator.next();
                    DBValue dbKey = next.getKey();
                    if (dbKey instanceof DBNull) {
                        return new Pair<>(null, next.getValue());
                    } else {
                        return new Pair<>(dbKey.getValue(), next.getValue());
                    }
                }
            };
        }
        return Collections.EMPTY_SET;
    }

    /**
     * Gets the terminal nitrite ids from this map.
     *
     * @return the terminal nitrite ids
     */
    public List getTerminalNitriteIds() {
        List terminalResult = new CopyOnWriteArrayList<>();

        // scan each entry of the navigable map and collect all terminal nitrite-ids
        for (Pair, ?> entry : entries()) {
            // if the value is terminal, collect all nitrite-ids
            if (entry.getSecond() instanceof List) {
                List nitriteIds = (List) entry.getSecond();
                terminalResult.addAll(nitriteIds);
            }

            // if the value is not terminal, scan recursively
            if (entry.getSecond() instanceof NavigableMap) {
                NavigableMap subMap = (NavigableMap) entry.getSecond();
                IndexMap indexMap = new IndexMap(subMap);
                List nitriteIds = indexMap.getTerminalNitriteIds();
                terminalResult.addAll(nitriteIds);
            }
        }

        return terminalResult;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy