// 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();
}
}