// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.set.v0_6.impl; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.openstreetmap.osmosis.core.container.v0_6.ChangeContainer; import org.openstreetmap.osmosis.core.task.common.ChangeAction; import org.openstreetmap.osmosis.core.task.v0_6.ChangeSink; import org.openstreetmap.osmosis.core.task.v0_6.ChangeSinkChangeSource; /** * Looks at a sorted change stream and condenses multiple changes for a single entity into a single * change. * * @author Brett Henderson */ public class ChangeSimplifierImpl implements ChangeSinkChangeSource { private List<ChangeContainer> currentChanges; private ChangeSink changeSink; /** * Creates a new instance. */ public ChangeSimplifierImpl() { currentChanges = new ArrayList<ChangeContainer>(); } private void flushCurrentChanges() { ChangeContainer changeBegin; ChangeContainer changeEnd; ChangeAction actionBegin; ChangeAction actionEnd; ChangeAction actionResult; changeBegin = currentChanges.get(0); changeEnd = currentChanges.get(currentChanges.size() - 1); actionBegin = changeBegin.getAction(); actionEnd = changeEnd.getAction(); // If the final action is a delete we'll send a delete action regardless of whether the // first action was a create just in case the create should have been a modify. // If the first action is a create, then the result is always a create (except for delete // case above). // Everything else is treated as a modify. if (actionEnd.equals(ChangeAction.Delete)) { actionResult = ChangeAction.Delete; } else if (actionBegin.equals(ChangeAction.Create)) { actionResult = ChangeAction.Create; } else { actionResult = ChangeAction.Modify; } changeSink.process(new ChangeContainer(changeEnd.getEntityContainer(), actionResult)); currentChanges.clear(); } /** * {@inheritDoc} */ @Override public void initialize(Map<String, Object> metaData) { changeSink.initialize(metaData); } /** * {@inheritDoc} */ @Override public void process(ChangeContainer change) { // If the current change is for a different entity to those in our current changes list, // then we must process the current changes. if (currentChanges.size() > 0) { long currentId; currentId = currentChanges.get(0).getEntityContainer().getEntity().getId(); if (currentId != change.getEntityContainer().getEntity().getId()) { flushCurrentChanges(); } } currentChanges.add(change); } /** * {@inheritDoc} */ @Override public void complete() { if (!currentChanges.isEmpty()) { flushCurrentChanges(); } changeSink.complete(); } /** * {@inheritDoc} */ @Override public void close() { changeSink.close(); } /** * {@inheritDoc} */ @Override public void setChangeSink(ChangeSink changeSink) { this.changeSink = changeSink; } }