// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.pgsnapshot.v0_6.impl; import java.util.ArrayList; import java.util.List; import org.openstreetmap.osmosis.core.database.DbFeature; import org.openstreetmap.osmosis.core.database.DbOrderedFeature; import org.openstreetmap.osmosis.core.database.FeaturePopulator; import org.openstreetmap.osmosis.core.database.RelationMemberCollectionLoader; import org.openstreetmap.osmosis.core.database.SortingStoreRowMapperListener; import org.openstreetmap.osmosis.core.domain.v0_6.Relation; import org.openstreetmap.osmosis.core.domain.v0_6.RelationMember; import org.openstreetmap.osmosis.core.lifecycle.ReleasableIterator; import org.openstreetmap.osmosis.core.sort.common.FileBasedSort; import org.openstreetmap.osmosis.core.store.SingleClassObjectSerializationFactory; import org.openstreetmap.osmosis.core.store.StoreReleasingIterator; import org.openstreetmap.osmosis.core.store.UpcastIterator; import org.openstreetmap.osmosis.pgsnapshot.common.DatabaseContext; import org.openstreetmap.osmosis.pgsnapshot.common.RowMapperRowCallbackListener; import org.springframework.jdbc.core.JdbcTemplate; /** * Performs all relation-specific db operations. * * @author Brett Henderson */ public class RelationDao extends EntityDao<Relation> { private JdbcTemplate jdbcTemplate; private EntityFeatureDao<RelationMember, DbOrderedFeature<RelationMember>> relationMemberDao; private RelationMemberMapper relationMemberMapper; /** * Creates a new instance. * * @param dbCtx * The database context to use for accessing the database. * @param actionDao * The dao to use for adding action records to the database. */ public RelationDao(DatabaseContext dbCtx, ActionDao actionDao) { super(dbCtx.getJdbcTemplate(), new RelationMapper(), actionDao); jdbcTemplate = dbCtx.getJdbcTemplate(); relationMemberMapper = new RelationMemberMapper(); relationMemberDao = new EntityFeatureDao<RelationMember, DbOrderedFeature<RelationMember>>( dbCtx.getJdbcTemplate(), relationMemberMapper); } private void loadFeatures(long entityId, Relation entity) { entity.getMembers().addAll(relationMemberDao.getAllRaw(entityId)); } /** * {@inheritDoc} */ @Override public Relation getEntity(long entityId) { Relation entity; entity = super.getEntity(entityId); loadFeatures(entityId, entity); return entity; } /** * Adds the specified relation member list to the database. * * @param entityId * The identifier of the entity to add these features to. * @param memberList * The list of features to add. */ private void addMembers(long entityId, List<RelationMember> memberList) { List<DbOrderedFeature<RelationMember>> dbList; dbList = new ArrayList<DbOrderedFeature<RelationMember>>(memberList.size()); for (int i = 0; i < memberList.size(); i++) { dbList.add(new DbOrderedFeature<RelationMember>(entityId, memberList.get(i), i)); } relationMemberDao.addAll(dbList); } /** * {@inheritDoc} */ @Override public void addEntity(Relation entity) { super.addEntity(entity); addMembers(entity.getId(), entity.getMembers()); } /** * {@inheritDoc} */ @Override public void modifyEntity(Relation entity) { long relationId; super.modifyEntity(entity); relationId = entity.getId(); relationMemberDao.removeList(relationId); addMembers(entity.getId(), entity.getMembers()); } /** * {@inheritDoc} */ @Override public void removeEntity(long entityId) { relationMemberDao.removeList(entityId); super.removeEntity(entityId); } private ReleasableIterator<DbOrderedFeature<RelationMember>> getRelationMembers(String tablePrefix) { FileBasedSort<DbOrderedFeature<RelationMember>> sortingStore = new FileBasedSort<DbOrderedFeature<RelationMember>>( new SingleClassObjectSerializationFactory(DbOrderedFeature.class), new DbOrderedFeatureComparator<RelationMember>(), true); try { String sql; SortingStoreRowMapperListener<DbOrderedFeature<RelationMember>> storeListener; RowMapperRowCallbackListener<DbOrderedFeature<RelationMember>> rowCallbackListener; ReleasableIterator<DbOrderedFeature<RelationMember>> resultIterator; sql = relationMemberMapper.getSqlSelect(tablePrefix, false, false); // Sends all received data into the object store. storeListener = new SortingStoreRowMapperListener<DbOrderedFeature<RelationMember>>(sortingStore); // Converts result set rows into objects and passes them into the store. rowCallbackListener = new RowMapperRowCallbackListener<DbOrderedFeature<RelationMember>>( relationMemberMapper.getRowMapper(), storeListener); // Perform the query passing the row mapper chain to process rows in a streamy fashion. jdbcTemplate.query(sql, rowCallbackListener); // Open a iterator on the store that will release the store upon completion. resultIterator = new StoreReleasingIterator<DbOrderedFeature<RelationMember>>(sortingStore.iterate(), sortingStore); // The store itself shouldn't be released now that it has been attached to the iterator. sortingStore = null; return resultIterator; } finally { if (sortingStore != null) { sortingStore.close(); } } } /** * {@inheritDoc} */ @Override protected List<FeaturePopulator<Relation>> getFeaturePopulators(String tablePrefix) { ReleasableIterator<DbFeature<RelationMember>> relationMemberIterator; List<FeaturePopulator<Relation>> featurePopulators; featurePopulators = new ArrayList<FeaturePopulator<Relation>>(); // Get the way nodes for the selected entities. relationMemberIterator = new UpcastIterator<DbFeature<RelationMember>, DbOrderedFeature<RelationMember>>( getRelationMembers(tablePrefix)); // Wrap the way node source into a feature populator that can attach them to their // owning ways. featurePopulators.add( new FeaturePopulatorImpl<Relation, RelationMember, DbFeature<RelationMember>>( relationMemberIterator, new RelationMemberCollectionLoader())); return featurePopulators; } }