Esempio n. 1
0
void CumulativeConflator::conflate(const QStringList inputs, const QString output)
{
  assert(inputs.size() >= 3);

  //for NoInformationElementRemover
  if (ConfigOptions().getWriterCleanReviewTags())
  {
    throw HootException(
      "Multi-conflation must be run with " +
      ConfigOptions::getWriterCleanReviewTagsKey() + "=false");
  }

  //for TagMergerFactory
  if (ConfigOptions().getTagMergerDefault() != "hoot::ProvenanceAwareOverwriteTagMerger")
  {
    throw HootException(
      "Multi-conflation must be run with " + ConfigOptions::getTagMergerDefaultKey() +
      "=hoot::ProvenanceAwareOverwriteTagMerger");
  }

  OsmMapPtr cumulativeMap(new OsmMap());
  LOG_VARD(inputs.size());
  for (int i = 0; i < inputs.size(); i++)
  {
    OsmMapPtr reviewCache;
    if (i == 0)
    {
      OsmMapReaderFactory::read(
        cumulativeMap, inputs[i], ConfigOptions().getReaderConflateUseDataSourceIds1(),
        Status::Unknown1);

      //keep a source tag history on the data for provenance; append to any existing source values
      //(this shouldn't be added to any review relations)
      LOG_DEBUG("Setting source tags for map " << QString::number(i + 1) << "...");
      SetTagValueVisitor sourceTagVisitor(MetadataTags::HootSource(), QString::number(i + 1));
      cumulativeMap->visitRw(sourceTagVisitor);
    }
    else
    {
      if (i == 1)
      {
        LOG_INFO("Conflating " << inputs[i - 1] << " with " << inputs[i] << "...");
      }
      else
      {
        LOG_INFO("Conflating cumulative map with " << inputs[i] << "...");
      }

      //I'm not yet sure all the projecting going on here is the right way to go about this, but
      //the maps must be in the same projection for the appending to work.

      OsmMapPtr unknown2Map(new OsmMap());
      OsmMapReaderFactory::read(
        unknown2Map, inputs[i], ConfigOptions().getReaderConflateUseDataSourceIds2(),
        Status::Unknown2);
      MapProjector::projectToWgs84(unknown2Map);

      //Same as above, but do this before combining the cumulative map with the unknown2 map to
      //prevent incorrect tags from being added to the cumulative map.
      LOG_DEBUG("Setting source tags for map " << QString::number(i + 1) << "...");
      SetTagValueVisitor sourceTagVisitor(
        MetadataTags::HootSource(), QString::number(i + 1)/*, true*/);
      unknown2Map->visitRw(sourceTagVisitor);

      //now combine the two maps before conflation
      MapProjector::projectToWgs84(cumulativeMap);
      MapProjector::projectToWgs84(unknown2Map);
      cumulativeMap->append(unknown2Map);

      //load in cached reviews from previous conflations - I believe this is necessary, b/c the
      //UnifyingConflator is ignoring any incoming reviews by design (need to verify this).  It
      //could be argued that modifying it to optionally retain the reviews is a better design
      //than the caching going on here...
      if (reviewCache.get() && reviewCache->getElementCount() > 0)
      {
        LOG_DEBUG("Adding previous reviews...");
        const RelationMap& reviews = reviewCache->getRelations();
        for (RelationMap::const_iterator it = reviews.begin(); it != reviews.end(); ++it)
        {
          RelationPtr review = it->second;
          review->setId(cumulativeMap->createNextRelationId());
          cumulativeMap->addRelation(review);
        }
        LOG_DEBUG("Added " << reviews.size() << " cached reviews.");
      }

      NamedOp(ConfigOptions().getConflatePreOps()).apply(cumulativeMap);
      UnifyingConflator().apply(cumulativeMap);
      //going to apply this at the end of all conflation jobs, but maybe we'll find out later that
      //it needs to be done here instead (?)
      //NamedOp(ConfigOptions().getConflatePostOps()).apply(cumulativeMap);

      if (i < inputs.size() - 1)
      {
        //Up until just before the last conflate job, set the status tag back to 1 so that the
        //accumulated data will conflate with the next dataset.
        //there is a bug here that will affect river conflation in that somehow hoot:status=3
        //tags are being left in at some point which causes the SearchRadiusCalculator to skip the
        //features.
        LOG_DEBUG("Setting status tags for map " << QString::number(i + 1) << "...");
        SetTagValueVisitor statusTagVisitor(
          MetadataTags::HootStatus(), QString("%1").arg(Status(Status::Unknown1).getEnum()));
        cumulativeMap->visitRw(statusTagVisitor);
      }

      //copy the map and save the reviews
      LOG_DEBUG("Caching reviews...");
      reviewCache.reset(new OsmMap(cumulativeMap->getProjection()));
      KeepReviewsVisitor vis;
      reviewCache->visitRw(vis);
      LOG_DEBUG("Cached " << reviewCache->getElementCount() << " reviews.");
    }
  }

  NamedOp(ConfigOptions().getConflatePostOps()).apply(cumulativeMap);

  MapProjector::projectToWgs84(cumulativeMap);
  OsmMapWriterFactory::write(cumulativeMap, output);
}