Skip to content

v0.2.50..v0.2.51 changeset OsmXmlChangesetFileWriter.cpp

Garret Voltz edited this page Jan 15, 2020 · 1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/io/OsmXmlChangesetFileWriter.cpp b/hoot-core/src/main/cpp/hoot/core/io/OsmXmlChangesetFileWriter.cpp
index 6938714..32a24cd 100644
--- a/hoot-core/src/main/cpp/hoot/core/io/OsmXmlChangesetFileWriter.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/io/OsmXmlChangesetFileWriter.cpp
@@ -32,6 +32,7 @@
 #include <hoot/core/schema/MetadataTags.h>
 #include <hoot/core/elements/OsmUtils.h>
 #include <hoot/core/util/Log.h>
+#include <hoot/core/util/Factory.h>
 
 // Qt
 #include <QFile>
@@ -43,16 +44,17 @@ using namespace std;
 namespace hoot
 {
 
+HOOT_FACTORY_REGISTER(OsmChangesetFileWriter, OsmXmlChangesetFileWriter)
+
 OsmXmlChangesetFileWriter::OsmXmlChangesetFileWriter() :
 _precision(ConfigOptions().getWriterPrecision()),
-_multipleChangesetsWritten(false),
 _addTimestamp(ConfigOptions().getChangesetXmlWriterAddTimestamp()),
 _includeDebugTags(ConfigOptions().getWriterIncludeDebugTags()),
 _includeCircularErrorTags(ConfigOptions().getWriterIncludeCircularErrorTags())
 {
   _stats.resize(Change::Unknown, ElementType::Unknown);
-  vector<QString> rows( {"Create", "Modify", "Delete"} );
-  vector<QString> columns( {"Node", "Way", "Relation"} );
+  vector<QString> rows({"Create", "Modify", "Delete"});
+  vector<QString> columns({"Node", "Way", "Relation"});
   _stats.setLabels(rows, columns);
 }
 
@@ -85,6 +87,7 @@ void OsmXmlChangesetFileWriter::write(const QString& path,
   QString filepath = path;
 
   _initIdCounters();
+  _parsedChanges.clear();
 
   long changesetProgress = 1;
 
@@ -109,31 +112,48 @@ void OsmXmlChangesetFileWriter::write(const QString& path,
   for (int i = 0; i < changesetProviders.size(); i++)
   {
     LOG_DEBUG(
-      "Derving changes with changeset provider: " << i + 1 << " / " << changesetProviders.size() <<
+      "Deriving changes with changeset provider: " << i + 1 << " / " << changesetProviders.size() <<
       "...");
 
     ChangesetProviderPtr changesetProvider = changesetProviders.at(i);
     LOG_VARD(changesetProvider->hasMoreChanges());
     while (changesetProvider->hasMoreChanges())
     {
+      LOG_VART(changesetProvider->hasMoreChanges());
       LOG_TRACE("Reading next XML change...");
       _change = changesetProvider->readNextChange();
       LOG_VART(_change.toString());
+
+      // When multiple changeset providers are passed in sometimes a duplicated change might exist
+      // between them, so we're skipping those dupes here. You could make the argument to prevent
+      // dupes from occurring before outputting this changeset file, but not quite sure how to do
+      // that yet, due to the fact that the changeset providers have a streaming interface.
+      if (_parsedChanges.contains(_change))
+      {
+        LOG_TRACE("Skipping adding duplicated change: " << _change << "...");
+        continue;
+      }
+
+      LOG_VART(Change::changeTypeToString(last));
       if (_change.getType() != last)
       {
         if (last != Change::Unknown)
         {
           writer.writeEndElement();
+          _parsedChanges.append(_change);
         }
         switch (_change.getType())
         {
           case Change::Create:
+            LOG_TRACE("Writing create start element...");
             writer.writeStartElement("create");
             break;
           case Change::Delete:
+            LOG_TRACE("Writing delete start element...");
             writer.writeStartElement("delete");
             break;
           case Change::Modify:
+            LOG_TRACE("Writing modify start element...");
             writer.writeStartElement("modify");
             break;
           case Change::Unknown:
@@ -171,16 +191,23 @@ void OsmXmlChangesetFileWriter::write(const QString& path,
       }
     }
 
+    LOG_VART(Change::changeTypeToString(last));
     if (last != Change::Unknown)
     {
+      LOG_TRACE("Writing change end element...");
       writer.writeEndElement();
+      last = Change::Unknown;
+      _parsedChanges.append(_change);
     }
   }
 
+  LOG_TRACE("Writing root end element...");
   writer.writeEndElement();
   writer.writeEndDocument();
 
   f.close();
+
+  LOG_DEBUG("Changeset written to: " << path << "...");
 }
 
 void OsmXmlChangesetFileWriter::_writeNode(QXmlStreamWriter& writer, ConstNodePtr n)
@@ -384,6 +411,8 @@ void OsmXmlChangesetFileWriter::setConfiguration(const Settings &conf)
 void OsmXmlChangesetFileWriter::_writeTags(QXmlStreamWriter& writer, Tags& tags,
                                            const Element* element)
 {
+  LOG_TRACE("Writing " << tags.size() << " tags for: " << element->getElementId() << "...");
+
   if (_includeDebugTags)
   {
     tags.set(MetadataTags::HootStatus(), QString::number(element->getStatus().getEnum()));
@@ -392,6 +421,7 @@ void OsmXmlChangesetFileWriter::_writeTags(QXmlStreamWriter& writer, Tags& tags,
     // having to scroll around looking for the change type for each element.
     tags.set(MetadataTags::HootChangeType(), Change::changeTypeToString(_change.getType()));
   }
+
   for (Tags::const_iterator it = tags.constBegin(); it != tags.constEnd(); ++it)
   {
     if (it.key().isEmpty() == false && it.value().isEmpty() == false)
@@ -401,17 +431,16 @@ void OsmXmlChangesetFileWriter::_writeTags(QXmlStreamWriter& writer, Tags& tags,
         continue;
       writer.writeStartElement("tag");
       writer.writeAttribute(
-        "k",
-        _invalidCharacterHandler.removeInvalidCharacters(it.key()));
+        "k", _invalidCharacterHandler.removeInvalidCharacters(it.key()));
       writer.writeAttribute(
-        "v",
-        _invalidCharacterHandler.removeInvalidCharacters(it.value()));
+        "v", _invalidCharacterHandler.removeInvalidCharacters(it.value()));
       writer.writeEndElement();
     }
   }
-  //  Only report the circular error for changesets when debug tags are turned on, circular error
-  //  tags are turned on, and (for nodes) there are other tags that aren't debug tags.  This is because
-  //  changesets are meant for non-hoot related databases and circular error is a hoot tag
+
+  // Only report the circular error for changesets when debug tags are turned on, circular error
+  // tags are turned on, and (for nodes) there are other tags that aren't debug tags.  This is
+  // because changesets are meant for non-hoot related databases and circular error is a hoot tag.
   if (_includeCircularErrorTags && element->hasCircularError() &&
       (element->getElementType() != ElementType::Node ||
       (element->getElementType() == ElementType::Node && tags.getNonDebugCount() > 0)) &&
Clone this wiki locally