/**
* Copyright 2010 Molindo GmbH
*
* 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 at.molindo.esi4j.rebuild.scrutineer;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import at.molindo.esi4j.mapping.TypeMapping;
import at.molindo.esi4j.rebuild.Esi4JRebuildSession;
import at.molindo.scrutineer.IdAndVersion;
import at.molindo.scrutineer.IdAndVersionStream;
public final class ModuleIdAndVersionStream implements IdAndVersionStream {
private final int _batchSize;
private final TypeMapping _mapping;
private Esi4JRebuildSession _rebuildSession;
public ModuleIdAndVersionStream(final Esi4JRebuildSession rebuildSession, final int batchSize, final TypeMapping mapping) {
_rebuildSession = rebuildSession;
_batchSize = batchSize;
_mapping = mapping;
}
@Override
public boolean isSorted() {
return _rebuildSession.isOrdered();
}
@Override
public void open() {
}
@Override
public Iterator<IdAndVersion> iterator() {
verifyOpen();
return new ModuleIdAndVersionStreamIterator();
}
@Override
public void close() {
_rebuildSession = null;
}
final class ModuleIdAndVersionStreamIterator implements Iterator<IdAndVersion> {
private Iterator<?> _iter;
private Object _next;
private boolean _lastBatchFetched = false;
private ModuleIdAndVersionStreamIterator() {
// init _iter
fetchBatch();
}
/**
* find next item if necessary
*/
private void findNext() {
while (_next == null && _iter != null) {
if (!_iter.hasNext()) {
// end of batch
fetchBatch();
}
if (_iter.hasNext()) {
_next = _iter.next();
if (_mapping.isFiltered(_next)) {
_next = null;
}
} else if (_lastBatchFetched) {
// end reached
_iter = null;
break;
}
}
}
/**
* fetch next batch from session if necessary
*/
private void fetchBatch() {
verifyOpen();
if (_iter == null || !_lastBatchFetched && !_iter.hasNext()) {
// defer calling as long as possible
final List<?> list = _rebuildSession.getNext(_batchSize);
if (list.size() < _batchSize) {
_lastBatchFetched = true;
}
_iter = list.iterator();
}
}
@Override
public boolean hasNext() {
findNext();
return _next != null;
}
@Override
public IdAndVersion next() {
findNext();
if (_next == null) {
throw new NoSuchElementException();
}
final Object next = _next;
_next = null;
Object id = _mapping.getId(next);
Long version = _mapping.getVersion(next);
if (version == null) {
// force update
version = Long.MAX_VALUE;
}
if (!ObjectIdAndVersion.isIdSupported(id)) {
id = _mapping.toIdString(id);
}
return new ObjectIdAndVersion(id, version, next);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
private void verifyOpen() {
if (_rebuildSession == null) {
throw new IllegalStateException("stream not open");
}
}
}