blob: df533d15f8ee03df9168c1978303e7359f2867db [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.openjpa.lib.rop;
import java.util.NoSuchElementException;
import org.apache.openjpa.lib.util.Localizer;
/**
* Prevents a view of a given range of indices from the delegate
* result object provider.
*
* @author Abe White
*/
public class RangeResultObjectProvider implements ResultObjectProvider {
private static final Localizer _loc = Localizer.forPackage
(RangeResultObjectProvider.class);
private final ResultObjectProvider _delegate;
private final int _startIdx;
private final int _endIdx;
private int _idx = -1;
/**
* Constructor. Because this is a wrapper around some delegate,
* and result object providers work with int indexes, neither the start
* or end index can be greater than Integer.MAX_VALUE(with the exception
* of Long.MAX_VALUE, which is used to indicate no limit).
*
* @param delegate the result object provider to delegate to
* @param startIdx 0-based inclusive start index of the range
* to present; must be < Integer.MAX_VALUE
* @param endIdx 0-based exclusive end index of the range to
* present; must be < Integer.MAX_VALUE, or Long.MAX_VALUE for no limit
*/
public RangeResultObjectProvider(ResultObjectProvider delegate,
long startIdx, long endIdx) {
// use Integer.MAX_VALUE for no limit internally
if (endIdx == Long.MAX_VALUE)
endIdx = Integer.MAX_VALUE;
_delegate = delegate;
if (startIdx > Integer.MAX_VALUE || endIdx > Integer.MAX_VALUE)
throw new IllegalArgumentException(_loc.get("range-too-high",
String.valueOf(startIdx), String.valueOf(endIdx)).getMessage());
_startIdx = (int) startIdx;
_endIdx = (int) endIdx;
}
@Override
public boolean supportsRandomAccess() {
return _delegate.supportsRandomAccess();
}
@Override
public void open() throws Exception {
_delegate.open();
}
@Override
public Object getResultObject() throws Exception {
if (_idx < _startIdx || _idx >= _endIdx)
throw new NoSuchElementException(String.valueOf(_idx));
return _delegate.getResultObject();
}
@Override
public boolean next() throws Exception {
// advance up to just behind _startIdx if we haven't already
while (_idx < _startIdx - 1) {
if (_delegate.supportsRandomAccess()) {
_idx = _startIdx - 1;
if (!_delegate.absolute(_startIdx - 1))
return false;
} else {
_idx++;
if (!_delegate.next())
return false;
}
}
// make sure we're not falling off the end of the range
if (_idx >= _endIdx - 1)
return false;
_idx++;
return _delegate.next();
}
@Override
public boolean absolute(int pos) throws Exception {
_idx = pos + _startIdx;
if (_idx >= _endIdx)
return false;
return _delegate.absolute(_idx);
}
@Override
public int size() throws Exception {
int size = _delegate.size();
if (size == Integer.MAX_VALUE)
return size;
size = Math.min(_endIdx, size) - _startIdx;
return (size < 0) ? 0 : size;
}
@Override
public void reset() throws Exception {
_idx = -1;
_delegate.reset();
}
@Override
public void close() throws Exception {
_delegate.close();
}
@Override
public void handleCheckedException(Exception e) {
_delegate.handleCheckedException(e);
}
public ResultObjectProvider getDelegate() {
return _delegate;
}
}