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

org.iq80.leveldb.iterator.ASeekingIterator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2011 the original author or authors.
 * See the notice.md file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * 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.iq80.leveldb.iterator;

import org.iq80.leveldb.DBException;

import java.io.IOException;
import java.util.NoSuchElementException;

/**
 * Seeking Iterator base implementation that ensure proper state validation before
 * each call and implement shared direction management between iterator implementations.
 *
 * @param  type of the key
 * @param  type of the value
 */
public abstract class ASeekingIterator implements SeekingIterator
{
    private static final String RELEASED_EXCEPTION = "Illegal use of iterator after release";
    private Direction direction = Direction.START_OF_ITERATOR;

    @Override
    public final boolean valid()
    {
        return direction.isValid();
    }

    @Override
    public final boolean seekToFirst()
    {
        if (direction == Direction.RELEASED) {
            throw new DBException(RELEASED_EXCEPTION);
        }
        if (internalSeekToFirst()) {
            direction = Direction.FORWARD;
            return true;
        }
        this.direction = Direction.END_OF_ITERATOR;
        return false;
    }

    @Override
    public final boolean seekToLast()
    {
        if (direction == Direction.RELEASED) {
            throw new DBException(RELEASED_EXCEPTION);
        }
        if (internalSeekToLast()) {
            direction = Direction.REVERSE;
            return true;
        }
        this.direction = Direction.START_OF_ITERATOR;
        return false;
    }

    @Override
    public final boolean seek(K key)
    {
        if (direction == Direction.RELEASED) {
            throw new DBException(RELEASED_EXCEPTION);
        }
        if (internalSeek(key)) {
            direction = Direction.FORWARD;
            return true;
        }
        direction = Direction.END_OF_ITERATOR;
        return false;
    }

    @Override
    public final boolean next()
    {
        switch (direction) {
            case START_OF_ITERATOR:
                return seekToFirst();
            case RELEASED:
                throw new DBException(RELEASED_EXCEPTION);
            case END_OF_ITERATOR:
                return false;
        }
        boolean switchDirection = direction == Direction.REVERSE;
        if (internalNext(switchDirection)) {
            if (switchDirection) {
                direction = Direction.FORWARD;
            }
            return true;
        }
        direction = Direction.END_OF_ITERATOR;
        return false;
    }

    @Override
    public final boolean prev()
    {
        switch (direction) {
            case RELEASED:
                throw new DBException(RELEASED_EXCEPTION);
            case START_OF_ITERATOR:
                return false;
            case END_OF_ITERATOR:
                return seekToLast();
        }
        boolean switchDirection = direction == Direction.FORWARD;
        if (internalPrev(switchDirection)) {
            if (switchDirection) {
                direction = Direction.REVERSE;
            }
            return true;
        }
        direction = Direction.START_OF_ITERATOR;
        return false;
    }

    @Override
    public final K key()
    {
        if (!direction.isValid()) {
            throw new NoSuchElementException();
        }
        return internalKey();
    }

    @Override
    public final V value()
    {
        if (!direction.isValid()) {
            throw new NoSuchElementException();
        }
        return internalValue();
    }

    @Override
    public final void close()
    {
        if (direction != Direction.RELEASED) {
            direction = Direction.RELEASED;
            try {
                internalClose();
            }
            catch (IOException e) {
                throw new DBException(e);
            }
        }
        else {
            throw new DBException("Releasing iterator more than once");
        }
    }

    protected abstract void internalClose() throws IOException;

    protected abstract boolean internalSeek(K key);

    protected abstract boolean internalNext(boolean switchDirection);

    protected abstract boolean internalPrev(boolean switchDirection);

    protected abstract boolean internalSeekToFirst();

    protected abstract boolean internalSeekToLast();

    protected abstract V internalValue();

    protected abstract K internalKey();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy