// This software is released into the Public Domain. See copying.txt for details.
package org.openstreetmap.osmosis.set.v0_6;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openstreetmap.osmosis.core.OsmosisRuntimeException;
import org.openstreetmap.osmosis.core.container.v0_6.ChangeContainer;
import org.openstreetmap.osmosis.set.v0_6.impl.DataPostboxChangeSink;
import org.openstreetmap.osmosis.core.store.DataPostbox;
import org.openstreetmap.osmosis.core.task.v0_6.ChangeSink;
import org.openstreetmap.osmosis.core.task.v0_6.MultiChangeSinkRunnableChangeSource;
/**
* Combines multiple change sources into a single data set. It is done by writing the contents of
* each of the input sources to the sink in order.
*
* @author Brett Henderson
*/
public class ChangeAppender implements MultiChangeSinkRunnableChangeSource {
private List<DataPostbox<ChangeContainer>> sources;
private ChangeSink changeSink;
/**
* Creates a new instance.
*
* @param sourceCount
* The number of sources to be appended.
* @param inputBufferCapacity
* The capacity of the buffer to use for each source, in objects.
*/
public ChangeAppender(int sourceCount, int inputBufferCapacity) {
sources = new ArrayList<DataPostbox<ChangeContainer>>(sourceCount);
for (int i = 0; i < sourceCount; i++) {
sources.add(new DataPostbox<ChangeContainer>(inputBufferCapacity));
}
}
/**
* {@inheritDoc}
*/
@Override
public ChangeSink getChangeSink(int instance) {
if (instance < 0 || instance >= sources.size()) {
throw new OsmosisRuntimeException("Sink instance " + instance + " is not valid.");
}
return new DataPostboxChangeSink(sources.get(instance));
}
/**
* {@inheritDoc}
*/
@Override
public int getChangeSinkCount() {
return sources.size();
}
/**
* {@inheritDoc}
*/
@Override
public void setChangeSink(ChangeSink changeSink) {
this.changeSink = changeSink;
}
/**
* {@inheritDoc}
*/
@Override
public void run() {
try {
Map<String, Object> metaData;
metaData = new HashMap<String, Object>();
// Get the initialization data from each source in turn and merge
// it. If the same data exists in multiple sources the last will
// win.
for (DataPostbox<ChangeContainer> source : sources) {
metaData.putAll(source.outputInitialize());
}
changeSink.initialize(metaData);
// Write the data from each source to the sink in turn.
for (DataPostbox<ChangeContainer> source : sources) {
while (source.hasNext()) {
changeSink.process(source.getNext());
}
}
changeSink.complete();
// Complete all input sources.
for (DataPostbox<ChangeContainer> source : sources) {
source.outputComplete();
}
} finally {
changeSink.close();
// Release all input sources.
for (DataPostbox<ChangeContainer> source : sources) {
source.outputRelease();
}
}
}
}