com.bigdata.btree.raba.SubRangeRaba Maven / Gradle / Ivy
/*
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
[email protected]
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.bigdata.btree.raba;
import java.io.DataInput;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* A read-only {@link IRaba} that exposes a limited sub-range of a backing {@link IRaba}.
*
* @author bryan
*
* @see BLZG-1537 (Schedule more IOs when loading data)
*/
public class SubRangeRaba implements IRaba {
/** The delegate. */
private final IRaba delegate;
/** The inclusive lower bound index into the delegate (offset). */
private final int fromIndex;
/** The exclusive upper bound index into the delegate. */
private final int toIndex;
/** The #of visible entries in this view of the delegate. */
private final int size;
/**
*
* @param delegate
* The delegate
* @param fromIndex
* The inclusive lower bound in the delegate.
* @param toIndex
* The exclusive upper bound in the delegate.
* @throws IllegalArgumentException
* if the delegate is null.
* @throws IllegalArgumentException
* if the fromIndex is LT ZERO (0).
* @throws IllegalArgumentException
* if the toIndex is GT the delegate {@link IRaba#size()}.
* @throws IllegalArgumentException
* if the fromIndex is GTE to toIndex.
*/
public SubRangeRaba(final IRaba delegate, final int fromIndex, final int toIndex) {
if (delegate == null)
throw new IllegalArgumentException();
if (fromIndex < 0)
throw new IllegalArgumentException();
if (toIndex > delegate.size())
throw new IllegalArgumentException();
if (fromIndex >= toIndex)
throw new IllegalArgumentException();
this.delegate = delegate;
this.fromIndex = fromIndex;
this.toIndex = toIndex;
this.size = toIndex - fromIndex;
}
@Override
final public boolean isReadOnly() {
return true;
}
@Override
public boolean isKeys() {
return delegate.isKeys();
}
@Override
public int capacity() {
return size;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
/**
* {@inheritDoc}
*
* It is assumed that the delegate is full and this view does not allow
* mutation, so this always returns false
.
*/
@Override
public boolean isFull() {
return true;
}
private void rangeCheck(final int index) {
if (index < 0)
throw new IndexOutOfBoundsException();
if (index >= size)
throw new IndexOutOfBoundsException();
}
@Override
public boolean isNull(final int index) {
rangeCheck(index);
return delegate.isNull(index + fromIndex);
}
@Override
public int length(final int index) {
rangeCheck(index);
return delegate.length(index + fromIndex);
}
@Override
public byte[] get(final int index) {
rangeCheck(index);
return delegate.get(index + fromIndex);
}
@Override
public int copy(final int index, final OutputStream os) {
rangeCheck(index);
return delegate.copy(index + fromIndex, os);
}
@Override
public Iterator iterator() {
return new Iterator() {
private int i = fromIndex;
@Override
public boolean hasNext() {
return i < toIndex;
}
@Override
public byte[] next() {
if (!hasNext())
throw new NoSuchElementException();
return delegate.get(i++);
}
@Override
public void remove() {
if (isReadOnly())
throw new UnsupportedOperationException();
// @todo support remove on the iterator when mutable.
throw new UnsupportedOperationException();
}
};
}
@Override
public void set(int index, byte[] a) {
throw new UnsupportedOperationException();
}
@Override
public int add(byte[] a) {
throw new UnsupportedOperationException();
}
@Override
public int add(byte[] value, int off, int len) {
throw new UnsupportedOperationException();
}
@Override
public int add(DataInput in, int len) throws IOException {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException
* always.
*
* TODO I am not sure about the semantics of search() for a
* sub-range so it is just disallowed for now. The issue is the
* meaning of a key probe that is LT the key at fromIndex in the
* delegate or GTE the key at toIndex in the delegate. Search in
* fact can generally report positions before the start of an
* ordered array of keys or after their end. But in this case we
* can't see any keys before fromIndex or GTE toIndex. This
* leads to some ambiguity about how to respond to key probes
* that really below in a different {@link SubRangeRaba}.
*/
@Override
public int search(final byte[] searchKey) {
throw new UnsupportedOperationException();
}
// /**
// * {@inheritDoc}
// *
// * @return The adjusted search position into this key range.
// *
// * @throws IndexOutOfBoundsException
// * if the probe key would lie before the first key in the
// * buffer.
// * @throws IndexOutOfBoundsException
// * if the probe key would lie after the last key in the buffer.
// */
// @Override
// public int search(final byte[] searchKey) {
// // throw new UnsupportedOperationException();
// final int search = delegate.search(searchKey);
// int entryIndex = search;
// if (entryIndex < 0) {
// entryIndex = -entryIndex;
// }
// /*
// * Note: Throws exception if the search key lies outside of the key
// * range that is visible to the caller when using this IRaba instance.
// */
// rangeCheck(entryIndex);
// return search;
// }
@Override
public String toString() {
return getClass().getName() + "{fromIndex=" + fromIndex + ",toIndex=" + toIndex + ",size=" + size + ",delegate="
+ delegate + "}";
}
}