Beispiel #1
0
void Editor::LoadMapEdits()
{
    if (!m_delegate)
    {
        LOG(LERROR, ("Can't load any map edits, delegate has not been set."));
        return;
    }

    xml_document doc;
    if (!m_storage->Load(doc))
        return;

    array<pair<FeatureStatus, char const *>, 4> const sections =
    {{
            {FeatureStatus::Deleted, kDeleteSection},
            {FeatureStatus::Modified, kModifySection},
            {FeatureStatus::Obsolete, kObsoleteSection},
            {FeatureStatus::Created, kCreateSection}
        }
    };
    int deleted = 0, obsolete = 0, modified = 0, created = 0;

    bool needRewriteEdits = false;

    // TODO(mgsergio): synchronize access to m_features.
    m_features.clear();
    for (xml_node mwm : doc.child(kXmlRootNode).children(kXmlMwmNode))
    {
        string const mapName = mwm.attribute("name").as_string("");
        int64_t const mapVersion = mwm.attribute("version").as_llong(0);
        MwmSet::MwmId const mwmId = GetMwmIdByMapName(mapName);
        // TODO(mgsergio, AlexZ): Is it normal to have isMwmIdAlive and mapVersion
        // NOT equal to mwmId.GetInfo()->GetVersion() at the same time?
        auto const needMigrateEdits = !mwmId.IsAlive() || mapVersion != mwmId.GetInfo()->GetVersion();
        needRewriteEdits |= needMigrateEdits;

        for (auto const & section : sections)
        {
            for (auto const nodeOrWay : mwm.child(section.second).select_nodes("node|way"))
            {
                try
                {
                    XMLFeature const xml(nodeOrWay.node());

                    // TODO(mgsergio): A map could be renamed, we'll treat it as deleted.
                    // The right thing to do is to try to migrate all changes anyway.
                    if (!mwmId.IsAlive())
                    {
                        LOG(LINFO, ("Mwm", mapName, "was deleted"));
                        goto SECTION_END;
                    }

                    TForEachFeaturesNearByFn forEach = [this](TFeatureTypeFn && fn,
                    m2::PointD const & point) {
                        return ForEachFeatureAtPoint(move(fn), point);
                    };

                    // TODO(mgsergio): Deleted features are not properly handled yet.
                    auto const fid = needMigrateEdits
                                     ? editor::MigrateFeatureIndex(
                                         forEach, xml, section.first,
                                         [this, &mwmId] { return GenerateNewFeatureId(mwmId); })
                                     : FeatureID(mwmId, xml.GetMWMFeatureIndex());

                    // Remove obsolete changes during migration.
                    if (needMigrateEdits && IsObsolete(xml, fid))
                        continue;

                    FeatureTypeInfo fti;
                    if (section.first == FeatureStatus::Created)
                    {
                        fti.m_feature.FromXML(xml);
                    }
                    else
                    {
                        auto const originalFeaturePtr = GetOriginalFeature(fid);
                        if (!originalFeaturePtr)
                        {
                            LOG(LERROR, ("A feature with id", fid, "cannot be loaded."));
                            alohalytics::LogEvent("Editor_MissingFeature_Error");
                            goto SECTION_END;
                        }

                        fti.m_feature = *originalFeaturePtr;
                        fti.m_feature.ApplyPatch(xml);
                    }

                    fti.m_feature.SetID(fid);
                    fti.m_street = xml.GetTagValue(kAddrStreetTag);

                    fti.m_modificationTimestamp = xml.GetModificationTime();
                    ASSERT_NOT_EQUAL(my::INVALID_TIME_STAMP, fti.m_modificationTimestamp, ());
                    fti.m_uploadAttemptTimestamp = xml.GetUploadTime();
                    fti.m_uploadStatus = xml.GetUploadStatus();
                    fti.m_uploadError = xml.GetUploadError();
                    fti.m_status = section.first;
                    switch (section.first)
                    {
                    case FeatureStatus::Deleted:
                        ++deleted;
                        break;
                    case FeatureStatus::Modified:
                        ++modified;
                        break;
                    case FeatureStatus::Obsolete:
                        ++obsolete;
                        break;
                    case FeatureStatus::Created:
                        ++created;
                        break;
                    case FeatureStatus::Untouched:
                        ASSERT(false, ());
                        continue;
                    }
                    // Insert initialized structure at the end: exceptions are possible in above code.
                    m_features[fid.m_mwmId].emplace(fid.m_index, move(fti));
                }
                catch (editor::XMLFeatureError const & ex)
                {
                    ostringstream s;
                    nodeOrWay.node().print(s, "  ");
                    LOG(LERROR, (ex.what(), "Can't create XMLFeature in section", section.second, s.str()));
                }
                catch (editor::MigrationError const & ex)
                {
                    LOG(LWARNING, (ex.Msg(), "mwmId =", mwmId, XMLFeature(nodeOrWay.node())));
                }
            } // for nodes
        } // for sections
SECTION_END:
        ;
    } // for mwms

    // Save edits with new indexes and mwm version to avoid another migration on next startup.
    if (needRewriteEdits)
        Save();
    LOG(LINFO, ("Loaded", modified, "modified,",
                created, "created,", deleted, "deleted and", obsolete, "obsolete features."));
}
Beispiel #2
0
void Editor::LoadMapEdits()
{
  if (!m_mwmIdByMapNameFn)
  {
    LOG(LERROR, ("Can't load any map edits, MwmIdByNameAndVersionFn has not been set."));
    return;
  }

  xml_document doc;
  {
    string const fullFilePath = GetEditorFilePath();
    xml_parse_result const res = doc.load_file(fullFilePath.c_str());
    // Note: status_file_not_found is ok if user has never made any edits.
    if (res != status_ok && res != status_file_not_found)
    {
      LOG(LERROR, ("Can't load map edits from disk:", fullFilePath));
      return;
    }
  }

  array<pair<FeatureStatus, char const *>, 3> const sections =
  {{
      {FeatureStatus::Deleted, kDeleteSection},
      {FeatureStatus::Modified, kModifySection},
      {FeatureStatus::Created, kCreateSection}
  }};
  int deleted = 0, modified = 0, created = 0;

  bool needRewriteEdits = false;

  for (xml_node mwm : doc.child(kXmlRootNode).children(kXmlMwmNode))
  {
    string const mapName = mwm.attribute("name").as_string("");
    int64_t const mapVersion = mwm.attribute("version").as_llong(0);
    MwmSet::MwmId const mwmId = m_mwmIdByMapNameFn(mapName);
    // TODO(mgsergio, AlexZ): Is it normal to have isMwmIdAlive and mapVersion
    // NOT equal to mwmId.GetInfo()->GetVersion() at the same time?
    auto const needMigrateEdits = !mwmId.IsAlive() || mapVersion != mwmId.GetInfo()->GetVersion();
    needRewriteEdits |= needMigrateEdits;

    for (auto const & section : sections)
    {
      for (auto const nodeOrWay : mwm.child(section.second).select_nodes("node|way"))
      {
        try
        {
          XMLFeature const xml(nodeOrWay.node());

          auto const fid = needMigrateEdits
                               ? editor::MigrateFeatureIndex(m_forEachFeatureAtPointFn, xml)
                               : FeatureID(mwmId, xml.GetMWMFeatureIndex());

          // Remove obsolete edit during migration.
          if (needMigrateEdits && IsObsolete(xml, fid))
            continue;

          FeatureTypeInfo fti;
          if (section.first == FeatureStatus::Created)
          {
            fti.m_feature.FromXML(xml);
          }
          else
          {
            fti.m_feature = *m_getOriginalFeatureFn(fid);
            fti.m_feature.ApplyPatch(xml);
          }

          fti.m_feature.SetID(fid);
          fti.m_street = xml.GetTagValue(kAddrStreetTag);

          fti.m_modificationTimestamp = xml.GetModificationTime();
          ASSERT_NOT_EQUAL(my::INVALID_TIME_STAMP, fti.m_modificationTimestamp, ());
          fti.m_uploadAttemptTimestamp = xml.GetUploadTime();
          fti.m_uploadStatus = xml.GetUploadStatus();
          fti.m_uploadError = xml.GetUploadError();
          fti.m_status = section.first;
          switch (section.first)
          {
          case FeatureStatus::Deleted: ++deleted; break;
          case FeatureStatus::Modified: ++modified; break;
          case FeatureStatus::Created: ++created; break;
          case FeatureStatus::Untouched: ASSERT(false, ()); continue;
          }
          // Insert initialized structure at the end: exceptions are possible in above code.
          m_features[fid.m_mwmId].emplace(fid.m_index, move(fti));
        }
        catch (editor::XMLFeatureError const & ex)
        {
          ostringstream s;
          nodeOrWay.node().print(s, "  ");
          LOG(LERROR, (ex.what(), "Can't create XMLFeature in section", section.second, s.str()));
        }
        catch (editor::MigrationError const & ex)
        {
          LOG(LWARNING, (ex.Msg(), "mwmId =", mwmId, XMLFeature(nodeOrWay.node())));
        }
      } // for nodes
    } // for sections
  } // for mwms

  // Save edits with new indexes and mwm version to avoid another migration on next startup.
  if (needRewriteEdits)
    Save(GetEditorFilePath());
  LOG(LINFO, ("Loaded", modified, "modified,", created, "created and", deleted, "deleted features."));
}