Skip to content

v0.2.47..v0.2.48 changeset OsmXmlChangesetFileWriter.cpp

Garret Voltz edited this page Sep 27, 2019 · 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 72f4c69..cc0f05e 100644
--- a/hoot-core/src/main/cpp/hoot/core/io/OsmXmlChangesetFileWriter.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/io/OsmXmlChangesetFileWriter.cpp
@@ -45,7 +45,6 @@ namespace hoot
 
 OsmXmlChangesetFileWriter::OsmXmlChangesetFileWriter() :
 _precision(ConfigOptions().getWriterPrecision()),
-_changesetMaxSize(ConfigOptions().getChangesetMaxSize()),
 _multipleChangesetsWritten(false),
 _addTimestamp(ConfigOptions().getChangesetXmlWriterAddTimestamp()),
 _includeDebugTags(ConfigOptions().getWriterIncludeDebugTags())
@@ -74,116 +73,97 @@ void OsmXmlChangesetFileWriter::write(const QString& path, const ChangesetProvid
   LOG_VARD(path);
   LOG_VARD(cs->hasMoreChanges());
 
-  QFileInfo info(path);
-  info.setCaching(false);
-  QString file = info.baseName();
-  QString dir = info.path();
-  QString ext = info.completeSuffix();
-  int fileCount = 0;
   QString filepath = path;
 
   _initIdCounters();
 
-  while (cs->hasMoreChanges())
-  {
-    long changesetProgress = 1;
-    //  Create a new filepath if the file is split in multiple files because of the
-    //  changeset.max.size setting
-    //   i.e. <filepath>/<filename>-001.<ext>
-    if (fileCount > 0)
-    {
-      filepath =
-        QString("%1/%2-%3.%4").arg(dir).arg(file).arg(fileCount, 3, 10, QChar('0')).arg(ext);
-      _multipleChangesetsWritten = true;
-    }
-    LOG_INFO("Writing changeset to " << filepath);
+  long changesetProgress = 1;
 
-    QFile f;
-    f.setFileName(filepath);
-    if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
-    {
-      throw HootException(QObject::tr("Error opening %1 for writing").arg(path));
-    }
+  LOG_INFO("Writing changeset to " << filepath);
+
+  QFile f;
+  f.setFileName(filepath);
+  if (!f.open(QIODevice::WriteOnly | QIODevice::Text))
+  {
+    throw HootException(QObject::tr("Error opening %1 for writing").arg(path));
+  }
 
-    QXmlStreamWriter writer(&f);
-    writer.setCodec("UTF-8");
-    writer.setAutoFormatting(true);
-    writer.writeStartDocument();
+  QXmlStreamWriter writer(&f);
+  writer.setCodec("UTF-8");
+  writer.setAutoFormatting(true);
+  writer.writeStartDocument();
 
-    writer.writeStartElement("osmChange");
-    writer.writeAttribute("version", "0.6");
-    writer.writeAttribute("generator", HOOT_PACKAGE_NAME);
+  writer.writeStartElement("osmChange");
+  writer.writeAttribute("version", "0.6");
+  writer.writeAttribute("generator", HOOT_PACKAGE_NAME);
 
-    Change::ChangeType last = Change::Unknown;
+  Change::ChangeType last = Change::Unknown;
 
-    while (cs->hasMoreChanges() && changesetProgress <= _changesetMaxSize)
+  while (cs->hasMoreChanges())
+  {
+    LOG_TRACE("Reading next XML change...");
+    _change = cs->readNextChange();
+    LOG_VART(_change.toString());
+    if (_change.getType() != last)
     {
-      LOG_TRACE("Reading next XML change...");
-      _change = cs->readNextChange();
-      LOG_VART(_change.toString());
-      if (_change.getType() != last)
+      if (last != Change::Unknown)
       {
-        if (last != Change::Unknown)
-        {
-          writer.writeEndElement();
-        }
-        switch (_change.getType())
-        {
-          case Change::Create:
-            writer.writeStartElement("create");
-            break;
-          case Change::Delete:
-            writer.writeStartElement("delete");
-            break;
-          case Change::Modify:
-            writer.writeStartElement("modify");
-            break;
-          case Change::Unknown:
-            //see comment in ChangesetDeriver::_nextChange() when
-            //_fromE->getElementId() < _toE->getElementId() as to why we do a no-op here.
-            break;
-          default:
-            throw IllegalArgumentException("Unexpected change type.");
-        }
-        last = _change.getType();
-        LOG_VART(last);
+        writer.writeEndElement();
       }
-
-      if (_change.getType() != Change::Unknown)
+      switch (_change.getType())
       {
-        ElementType::Type type = _change.getElement()->getElementType().getEnum();
-        switch (type)
-        {
-          case ElementType::Node:
-            _writeNode(writer, std::dynamic_pointer_cast<const Node>(_change.getElement()));
-            break;
-          case ElementType::Way:
-            _writeWay(writer, std::dynamic_pointer_cast<const Way>(_change.getElement()));
-            break;
-          case ElementType::Relation:
-            _writeRelation(
-              writer, std::dynamic_pointer_cast<const Relation>(_change.getElement()));
-            break;
-          default:
-            throw IllegalArgumentException("Unexpected element type.");
-        }
-        changesetProgress++;
-        //  Update the stats
-        _stats(last, type)++;
+        case Change::Create:
+          writer.writeStartElement("create");
+          break;
+        case Change::Delete:
+          writer.writeStartElement("delete");
+          break;
+        case Change::Modify:
+          writer.writeStartElement("modify");
+          break;
+        case Change::Unknown:
+          //see comment in ChangesetDeriver::_nextChange() when
+          //_fromE->getElementId() < _toE->getElementId() as to why we do a no-op here.
+          break;
+        default:
+          throw IllegalArgumentException("Unexpected change type.");
       }
+      last = _change.getType();
+      LOG_VART(last);
     }
 
-    if (last != Change::Unknown)
+    if (_change.getType() != Change::Unknown)
     {
-      writer.writeEndElement();
+      ElementType::Type type = _change.getElement()->getElementType().getEnum();
+      switch (type)
+      {
+        case ElementType::Node:
+          _writeNode(writer, std::dynamic_pointer_cast<const Node>(_change.getElement()));
+          break;
+        case ElementType::Way:
+          _writeWay(writer, std::dynamic_pointer_cast<const Way>(_change.getElement()));
+          break;
+        case ElementType::Relation:
+          _writeRelation(
+            writer, std::dynamic_pointer_cast<const Relation>(_change.getElement()));
+          break;
+        default:
+          throw IllegalArgumentException("Unexpected element type.");
+      }
+      changesetProgress++;
+      //  Update the stats
+      _stats(last, type)++;
     }
-    writer.writeEndElement();
-    writer.writeEndDocument();
+  }
 
-    f.close();
-    //  Increment the file number if needed for split files
-    fileCount++;
+  if (last != Change::Unknown)
+  {
+    writer.writeEndElement();
   }
+  writer.writeEndElement();
+  writer.writeEndDocument();
+
+  f.close();
 }
 
 void OsmXmlChangesetFileWriter::_writeNode(QXmlStreamWriter& writer, ConstNodePtr n)
@@ -208,8 +188,15 @@ void OsmXmlChangesetFileWriter::_writeNode(QXmlStreamWriter& writer, ConstNodePt
   //  for xml changeset OSM rails port expects created elements to have version = 0
   if (_change.getType() == Change::Create)
     version = 0;
+  else if (n->getVersion() < 1)
+  {
+    throw HootException(
+      QString("Elements being modified or deleted in an .osc changeset must always have a ") +
+      QString("version greater than zero: ") + n->getElementId().toString());
+  }
   else
     version = n->getVersion();
+  LOG_VART(version);
   writer.writeAttribute("version", QString::number(version));
 
   writer.writeAttribute("lat", QString::number(n->getY(), 'f', _precision));
@@ -250,8 +237,15 @@ void OsmXmlChangesetFileWriter::_writeWay(QXmlStreamWriter& writer, ConstWayPtr
   // for xml changeset OSM rails port expects created elements to have version = 0
   if (_change.getType() == Change::Create)
     version = 0;
+  else if (w->getVersion() < 1)
+  {
+    throw HootException(
+      QString("Elements being modified or deleted in an .osc changeset must always have a ") +
+      QString("version greater than zero: ")  + w->getElementId().toString());
+  }
   else
     version = w->getVersion();
+  LOG_VART(version);
   writer.writeAttribute("version", QString::number(version));
   if (_addTimestamp)
   {
@@ -304,8 +298,15 @@ void OsmXmlChangesetFileWriter::_writeRelation(QXmlStreamWriter& writer, ConstRe
   //  for xml changeset OSM rails port expects created elements to have version = 0
   if (_change.getType() == Change::Create)
     version = 0;
+  else if (r->getVersion() < 1)
+  {
+    throw HootException(
+      QString("Elements being modified or deleted in an .osc changeset must always have a ") +
+      QString("version greater than zero: ") + r->getElementId().toString());
+  }
   else
     version = r->getVersion();
+  LOG_VART(version);
   writer.writeAttribute("version", QString::number(version));
   if (_addTimestamp)
   {
@@ -358,14 +359,18 @@ void OsmXmlChangesetFileWriter::setConfiguration(const Settings &conf)
 {
   ConfigOptions co(conf);
   _precision = co.getWriterPrecision();
-  _changesetMaxSize = co.getChangesetMaxSize();
 }
 
-void OsmXmlChangesetFileWriter::_writeTags(QXmlStreamWriter& writer, Tags& tags, const Element* element)
+void OsmXmlChangesetFileWriter::_writeTags(QXmlStreamWriter& writer, Tags& tags,
+                                           const Element* element)
 {
   if (_includeDebugTags)
   {
     tags.set(MetadataTags::HootStatus(), QString::number(element->getStatus().getEnum()));
+    tags.set(MetadataTags::HootId(), QString::number(element->getId()));
+    // This just makes sifting through the xml elements a little bit easier during debugging vs
+    // 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)
   {
Clone this wiki locally