// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.apidb.v0_6.impl; import java.util.Date; import java.util.List; import java.util.NoSuchElementException; import org.openstreetmap.osmosis.core.container.v0_6.ChangeContainer; import org.openstreetmap.osmosis.core.container.v0_6.EntityContainer; import org.openstreetmap.osmosis.core.lifecycle.ReleasableIterator; import org.openstreetmap.osmosis.core.store.PeekableIterator; import org.openstreetmap.osmosis.core.task.common.ChangeAction; /** * Produces a snapshot at a point in time from a complete history stream. * * @author Brett Henderson */ public class EntitySnapshotReader implements ReleasableIterator<EntityContainer> { private PeekableIterator<List<ChangeContainer>> sourceIterator; private Date snapshotInstant; private EntityContainer nextValue; private boolean nextValueLoaded; /** * Creates a new instance. * * @param sourceIterator * An iterator containing the full history for entities. * @param snapshotInstant * The state of the entity at this point in time will be dumped. * This ensures a consistent snapshot. */ public EntitySnapshotReader( ReleasableIterator<ChangeContainer> sourceIterator, Date snapshotInstant) { this.sourceIterator = new PeekableIterator<List<ChangeContainer>>(new EntityHistoryListReader(sourceIterator)); this.snapshotInstant = snapshotInstant; nextValueLoaded = false; } /** * {@inheritDoc} */ public boolean hasNext() { while (!nextValueLoaded && sourceIterator.hasNext()) { List<ChangeContainer> changeList; ChangeContainer changeContainer; // Get the next change list from the underlying stream. changeList = sourceIterator.next(); // Loop until all history values for the current element are exhausted and get the // latest version of the entity that fits within the snapshot timestamp. changeContainer = null; for (ChangeContainer tmpChangeContainer : changeList) { // We're only interested in elements prior or equal to the snapshot point. if (tmpChangeContainer.getEntityContainer().getEntity() .getTimestamp().compareTo(snapshotInstant) <= 0) { // Replace the current change container with the later version. changeContainer = tmpChangeContainer; } } // We are not interested in items created after the snapshot timestamp (ie. null) or deleted items. if (changeContainer != null && !ChangeAction.Delete.equals(changeContainer.getAction())) { nextValue = changeContainer.getEntityContainer(); nextValueLoaded = true; } } return nextValueLoaded; } /** * {@inheritDoc} */ public EntityContainer next() { if (!hasNext()) { throw new NoSuchElementException(); } nextValueLoaded = false; return nextValue; } /** * {@inheritDoc} */ public void remove() { throw new UnsupportedOperationException(); } /** * {@inheritDoc} */ public void close() { sourceIterator.close(); } }