// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.apidb.v0_6.impl; import java.util.List; import java.util.NoSuchElementException; import org.openstreetmap.osmosis.core.container.v0_6.ChangeContainer; import org.openstreetmap.osmosis.core.lifecycle.ReleasableIterator; import org.openstreetmap.osmosis.core.store.PeekableIterator; import org.openstreetmap.osmosis.core.task.common.ChangeAction; /** * Takes an underlying full history delta stream and converts it into a diff stream. The difference * between the two is that a delta stream may contain multiple changes for a single entity, a diff * stream will contain a single change for the entity to get from the beginning to end point. */ public class DeltaToDiffReader implements ReleasableIterator<ChangeContainer> { private PeekableIterator<List<ChangeContainer>> sourceIterator; private ChangeContainer nextValue; private boolean nextValueLoaded; /** * Creates a new instance. * * @param sourceIterator * An iterator containing the full history for entities. */ public DeltaToDiffReader( ReleasableIterator<ChangeContainer> sourceIterator) { this.sourceIterator = new PeekableIterator<List<ChangeContainer>>(new EntityHistoryListReader(sourceIterator)); nextValueLoaded = false; } /** * {@inheritDoc} */ public boolean hasNext() { while (!nextValueLoaded && sourceIterator.hasNext()) { List<ChangeContainer> changeList; ChangeContainer changeContainer; boolean createdPreviously; // Get the next change list from the underlying stream. changeList = sourceIterator.next(); // Check the first node, if it has a version greater than 1 the node // existed prior to the interval beginning and therefore cannot be a // create. createdPreviously = (changeList.get(0).getEntityContainer().getEntity().getVersion() > 1); // Get the most current change. changeContainer = changeList.get(changeList.size() - 1); // The entity has been modified if it is a create/modify and was created previously. // It is a create if it is create/modify and was NOT created previously. // It is a delete if it is a delete and was created previously. // No action if it is a delete and was NOT created previously. if (!ChangeAction.Delete.equals(changeContainer.getAction()) && createdPreviously) { nextValue = new ChangeContainer(changeContainer.getEntityContainer(), ChangeAction.Modify); nextValueLoaded = true; } else if (!ChangeAction.Delete.equals(changeContainer.getAction()) && !createdPreviously) { nextValue = new ChangeContainer(changeContainer.getEntityContainer(), ChangeAction.Create); nextValueLoaded = true; } else if (ChangeAction.Delete.equals(changeContainer.getAction()) && createdPreviously) { nextValue = new ChangeContainer(changeContainer.getEntityContainer(), ChangeAction.Delete); nextValueLoaded = true; } } return nextValueLoaded; } /** * {@inheritDoc} */ public ChangeContainer next() { if (!hasNext()) { throw new NoSuchElementException(); } nextValueLoaded = false; return nextValue; } /** * {@inheritDoc} */ public void remove() { throw new UnsupportedOperationException(); } /** * {@inheritDoc} */ public void close() { sourceIterator.close(); } }