// 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 org.openstreetmap.osmosis.core.OsmosisRuntimeException; import org.openstreetmap.osmosis.core.database.DbFeature; import org.openstreetmap.osmosis.core.database.DbFeatureHistory; import org.openstreetmap.osmosis.core.domain.v0_6.Entity; import org.openstreetmap.osmosis.core.domain.v0_6.Tag; import org.openstreetmap.osmosis.core.lifecycle.ReleasableContainer; import org.openstreetmap.osmosis.core.lifecycle.ReleasableIterator; /** * Provides a single iterator based on data provided by underlying iterators from each of the * underlying entity and feature iterators. Each underlying iterator provides one component of the * overall entity. * * @param <T> * The type of entity provided by this iterator. */ public class EntityHistoryReader<T extends Entity> implements ReleasableIterator<EntityHistory<T>> { private ReleasableContainer releasableContainer; private ReleasableIterator<EntityHistory<T>> entityIterator; private FeatureHistoryPopulator<T, Tag, ?> tagPopulator; private List<FeatureHistoryPopulator<T, ?, ?>> featurePopulators; private EntityHistory<T> nextValue; /** * Creates a new instance. * * @param entityIterator * The entity source. * @param tagIterator * The tag source. * @param featurePopulators * Populators to add entity specific features to the generated entities. */ public EntityHistoryReader(ReleasableIterator<EntityHistory<T>> entityIterator, ReleasableIterator<DbFeatureHistory<DbFeature<Tag>>> tagIterator, List<FeatureHistoryPopulator<T, ?, ?>> featurePopulators) { releasableContainer = new ReleasableContainer(); this.entityIterator = releasableContainer.add(entityIterator); tagPopulator = releasableContainer.add(new FeatureHistoryPopulator<T, Tag, DbFeature<Tag>>(tagIterator, new TagCollectionLoader<T>())); for (FeatureHistoryPopulator<T, ?, ?> featurePopulator : featurePopulators) { releasableContainer.add(featurePopulator); } this.featurePopulators = featurePopulators; } /** * Consolidates the output of all history readers so that entities are fully * populated. * * @return An entity history record where the entity is fully populated. */ private EntityHistory<T> readNextEntityHistory() { EntityHistory<T> entityHistory; T entity; entityHistory = entityIterator.next(); entity = entityHistory.getEntity(); // Add all applicable tags to the entity. tagPopulator.populateFeatures(entity); // Add entity type specific features to the entity. for (FeatureHistoryPopulator<T, ?, ?> populator : featurePopulators) { populator.populateFeatures(entity); } return entityHistory; } /** * {@inheritDoc} */ @Override public boolean hasNext() { while (nextValue == null && entityIterator.hasNext()) { nextValue = readNextEntityHistory(); } return (nextValue != null); } /** * {@inheritDoc} */ @Override public EntityHistory<T> next() { EntityHistory<T> result; if (!hasNext()) { throw new OsmosisRuntimeException("No records are available, call hasNext first."); } result = nextValue; nextValue = null; return result; } /** * {@inheritDoc} */ @Override public void remove() { throw new UnsupportedOperationException(); } /** * {@inheritDoc} */ @Override public void close() { releasableContainer.close(); } }