Skip to content

v0.2.50..v0.2.51 changeset OsmApiChangesetElement.cpp

Garret Voltz edited this page Jan 15, 2020 · 1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/io/OsmApiChangesetElement.cpp b/hoot-core/src/main/cpp/hoot/core/io/OsmApiChangesetElement.cpp
index ecf659e..1d74420 100644
--- a/hoot-core/src/main/cpp/hoot/core/io/OsmApiChangesetElement.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/io/OsmApiChangesetElement.cpp
@@ -36,17 +36,26 @@
 namespace hoot
 {
 
-XmlElement::XmlElement(const XmlObject& object, ElementIdToIdMap* idMap)
+/** Custom ID sort order */
+bool id_sort_order(long lhs, long rhs)
+{
+  if (lhs > 0 && rhs > 0)       return lhs < rhs; //  Positive numbers count up
+  else if (lhs < 0 && rhs < 0)  return lhs > rhs; //  Negative numbers count down
+  else                          return lhs < rhs; //  Negative numbers come before positive
+}
+
+ChangesetElement::ChangesetElement(const XmlObject& object, ElementIdToIdMap* idMap)
   : _type(ElementType::Unknown),
     _id(object.second.value("id").toString().toLong()),
     _version(object.second.value("version").toString().toLong()),
-    _object(object),
     _idMap(idMap),
-    _status(XmlElement::Available)
+    _status(ChangesetElement::Available)
 {
+  for (QXmlStreamAttributes::const_iterator it = object.second.begin(); it != object.second.end(); ++it)
+    _object.push_back(std::make_pair(it->name().toString(), it->value().toString()));
 }
 
-XmlElement::XmlElement(const XmlElement& element)
+ChangesetElement::ChangesetElement(const ChangesetElement& element)
   : _type(element._type),
     _id(element._id),
     _version(element._version),
@@ -57,58 +66,73 @@ XmlElement::XmlElement(const XmlElement& element)
 {
 }
 
-void XmlElement::addTag(const XmlObject& tag)
+void ChangesetElement::addTag(const XmlObject& tag)
 {
   //  Make sure that the object is in fact a tag before adding it
   if (tag.first == "tag")
-    _tags.push_back(tag);
+  {
+    QString key;
+    QString value;
+    for (QXmlStreamAttributes::const_iterator it = tag.second.begin(); it != tag.second.end(); ++it)
+    {
+      if (it->name() == "k")
+        key = it->value().toString();
+      else if (it->name() == "v")
+        value = it->value().toString();
+    }
+    if (key != "" and value != "")
+      _tags.push_back(std::make_pair(key, value));
+  }
 }
 
-QString XmlElement::getTagKey(int index)
+QString ChangesetElement::getTagKey(int index)
 {
-  if (index < 0 || index >= _tags.size() || !_tags[index].second.hasAttribute("k"))
+  if (index < 0 || index >= (int)_tags.size())
     throw IllegalArgumentException();
-  return _tags[index].second.value("k").toString();
+  return _tags[index].first;
 }
 
-QString XmlElement::getTagValue(int index)
+QString ChangesetElement::getTagValue(int index)
 {
-  if (index < 0 || index >= _tags.size() || !_tags[index].second.hasAttribute("v"))
+  if (index < 0 || index >= (int)_tags.size())
     throw IllegalArgumentException();
-  return _tags[index].second.value("v").toString();
+  return _tags[index].second;
 }
 
-QString XmlElement::toString(const QXmlStreamAttributes& attributes, long changesetId) const
+QString ChangesetElement::toString(const ElementAttributes& attributes, long changesetId) const
 {
   QString buffer;
   QTextStream ts(&buffer);
   //  Setting the codec to UTF-8 is the special sauce for foreign characters
   ts.setCodec("UTF-8");
-  for (int i = 0; i < attributes.size(); ++i)
+  bool hasChangeset = false;
+  for (ElementAttributes::const_iterator it = attributes.begin(); it != attributes.end(); ++it)
   {
-    const QXmlStreamAttribute& attribute = attributes.at(i);
-    QStringRef name = attribute.name();
+    QString name = it->first;
     if (name == "action")
       continue;
-    ts << name.toString() << "=\"";
+    ts << name << "=\"";
     //  Some attributes need to be overridden
     if (name == "changeset")    //  Changeset ID is provided by the OSM API
+    {
       ts << changesetId;
+      hasChangeset = true;
+    }
     else if (name == "id")      //  Element ID could be different than provided in the file, could be from the API
-      ts << (_idMap ? _idMap->getNewId(_type, _id) : _id);
+      ts << (_idMap ? _idMap->getId(_type, _id) : _id);
     else if (name == "version") //  Versions are updated by the API
       ts << _version;
     else
-      ts << attribute.value().toString();
+      ts << it->second;
     ts << "\" ";
   }
   //  Add the changeset attribute if the original data didn't include it
-  if (!attributes.hasAttribute("changeset"))
+  if (!hasChangeset)
     ts << "changeset=\"" << changesetId << "\"";
   return ts.readAll();
 }
 
-QString& XmlElement::escapeString(QString& value) const
+QString& ChangesetElement::escapeString(QString& value) const
 {
   //  Simple XML encoding of some problematic characters
   return value.replace("&", "&amp;")
@@ -118,18 +142,18 @@ QString& XmlElement::escapeString(QString& value) const
               .replace("<", "&lt;");
 }
 
-QString XmlElement::toTagString(const QXmlStreamAttributes& attributes) const
+QString ChangesetElement::toTagString(const ElementTag& tag) const
 {
   QString buffer;
   QTextStream ts(&buffer);
   ts.setCodec("UTF-8");
-  QString key(attributes.value("k").toString());
-  QString value(attributes.value("v").toString());
+  QString key(tag.first);
+  QString value(tag.second);
   //  Tag values of length 255 need to be truncated
   QString newValue(ApiTagTruncateVisitor::truncateTag(key, value));
 
   //  Make sure to XML encode the value
-  ts << "\t\t\t<tag k=\"" << attributes.value("k").toString() << "\" v=\"";
+  ts << "\t\t\t<tag k=\"" << key << "\" v=\"";
   if (newValue != "")
     ts << escapeString(newValue);
   else
@@ -138,29 +162,29 @@ QString XmlElement::toTagString(const QXmlStreamAttributes& attributes) const
   return ts.readAll();
 }
 
-XmlNode::XmlNode(const XmlObject& node, ElementIdToIdMap* idMap)
-  : XmlElement(node, idMap)
+ChangesetNode::ChangesetNode(const XmlObject& node, ElementIdToIdMap* idMap)
+  : ChangesetElement(node, idMap)
 {
   //  Override the type
   _type = ElementType::Node;
 }
 
-XmlNode::XmlNode(const XmlNode &node)
-  : XmlElement(node)
+ChangesetNode::ChangesetNode(const ChangesetNode &node)
+  : ChangesetElement(node)
 {
 }
 
-QString XmlNode::toString(long changesetId) const
+QString ChangesetNode::toString(long changesetId) const
 {
   QString buffer;
   QTextStream ts(&buffer);
   ts.setCodec("UTF-8");
-  ts << "\t\t<node " << XmlElement::toString(_object.second, changesetId);
+  ts << "\t\t<node " << ChangesetElement::toString(_object, changesetId);
   if (_tags.size() > 0)
   {
     ts << ">\n";
-    for (QVector<XmlObject>::const_iterator it = _tags.begin(); it != _tags.end(); ++it)
-      ts << toTagString(it->second);
+    for (ElementTags::const_iterator it = _tags.begin(); it != _tags.end(); ++it)
+      ts << toTagString(*it);
     ts << "\t\t</node>\n";
   }
   else
@@ -168,20 +192,20 @@ QString XmlNode::toString(long changesetId) const
   return ts.readAll();
 }
 
-XmlWay::XmlWay(const XmlObject& way, ElementIdToIdMap* idMap)
-  : XmlElement(way, idMap)
+ChangesetWay::ChangesetWay(const XmlObject& way, ElementIdToIdMap* idMap)
+  : ChangesetElement(way, idMap)
 {
   //  Override the type
   _type = ElementType::Way;
 }
 
-XmlWay::XmlWay(const XmlWay &way)
-  : XmlElement(way),
+ChangesetWay::ChangesetWay(const ChangesetWay &way)
+  : ChangesetElement(way),
     _nodes(way._nodes)
 {
 }
 
-void XmlWay::removeNodes(int position, int count)
+void ChangesetWay::removeNodes(int position, int count)
 {
   if (position < 0 || count == 0 || _nodes.size() < 1)
     return;
@@ -190,40 +214,40 @@ void XmlWay::removeNodes(int position, int count)
   _nodes.remove(position, count);
 }
 
-QString XmlWay::toString(long changesetId) const
+QString ChangesetWay::toString(long changesetId) const
 {
   QString buffer;
   QTextStream ts(&buffer);
   ts.setCodec("UTF-8");
-  ts << "\t\t<way " << XmlElement::toString(_object.second, changesetId) << ">\n";
+  ts << "\t\t<way " << ChangesetElement::toString(_object, changesetId) << ">\n";
   for (QVector<long>::const_iterator it = _nodes.begin(); it != _nodes.end(); ++it)
-    ts << "\t\t\t<nd ref=\"" << (_idMap ? _idMap->getNewId(ElementType::Node, *it) : *it) << "\"/>\n";
+    ts << "\t\t\t<nd ref=\"" << (_idMap ? _idMap->getId(ElementType::Node, *it) : *it) << "\"/>\n";
   if (_tags.size() > 0)
   {
-    for (QVector<XmlObject>::const_iterator it = _tags.begin(); it != _tags.end(); ++it)
-      ts << toTagString(it->second);
+    for (ElementTags::const_iterator it = _tags.begin(); it != _tags.end(); ++it)
+      ts << toTagString(*it);
   }
   ts << "\t\t</way>\n";
   return ts.readAll();
 }
 
-XmlRelation::XmlRelation(const XmlObject& relation, ElementIdToIdMap* idMap)
-  : XmlElement(relation, idMap)
+ChangesetRelation::ChangesetRelation(const XmlObject& relation, ElementIdToIdMap* idMap)
+  : ChangesetElement(relation, idMap)
 {
   //  Override the type
   _type = ElementType::Relation;
 }
 
-XmlRelation::XmlRelation(const XmlRelation &relation)
-  : XmlElement(relation),
+ChangesetRelation::ChangesetRelation(const ChangesetRelation &relation)
+  : ChangesetElement(relation),
     _members(relation._members)
 {
 }
 
-bool XmlRelation::hasMember(ElementType::Type type, long id)
+bool ChangesetRelation::hasMember(ElementType::Type type, long id)
 {
   //  Iterate all of the members
-  for (QList<XmlMember>::iterator it = _members.begin(); it != _members.end(); ++it)
+  for (QList<ChangesetRelationMember>::iterator it = _members.begin(); it != _members.end(); ++it)
   {
     switch (type)
     {
@@ -249,41 +273,40 @@ bool XmlRelation::hasMember(ElementType::Type type, long id)
   return false;
 }
 
-QString XmlRelation::toString(long changesetId) const
+QString ChangesetRelation::toString(long changesetId) const
 {
   QString buffer;
   QTextStream ts(&buffer);
   ts.setCodec("UTF-8");
-  ts << "\t\t<relation " << XmlElement::toString(_object.second, changesetId) << ">\n";
-  for (QList<XmlMember>::const_iterator it = _members.begin(); it != _members.end(); ++it)
+  ts << "\t\t<relation " << ChangesetElement::toString(_object, changesetId) << ">\n";
+  for (QList<ChangesetRelationMember>::const_iterator it = _members.begin(); it != _members.end(); ++it)
     ts << it->toString();
   if (_tags.size() > 0)
   {
-    for (QVector<XmlObject>::const_iterator it = _tags.begin(); it != _tags.end(); ++it)
-      ts << toTagString(it->second);
+    for (ElementTags::const_iterator it = _tags.begin(); it != _tags.end(); ++it)
+      ts << toTagString(*it);
   }
   ts << "\t\t</relation>\n";
   return ts.readAll();
 }
 
-XmlMember::XmlMember(const QXmlStreamAttributes& member, ElementIdToIdMap* idMap)
-  : _type(member.value("type").toString()),
+ChangesetRelationMember::ChangesetRelationMember(const QXmlStreamAttributes& member, ElementIdToIdMap* idMap)
+  : _type(ElementType::fromString(member.value("type").toString().toLower())),
     _ref(member.value("ref").toString().toLong()),
     _role(member.value("role").toString()),
     _idMap(idMap)
 {
 }
 
-QString XmlMember::toString() const
+QString ChangesetRelationMember::toString() const
 {
   QString buffer;
   QTextStream ts(&buffer);
   ts.setCodec("UTF-8");
-  ts << "\t\t\t<member type=\"" << _type << "\" ref=\""
-     << (_idMap ? _idMap->getNewId(ElementType::fromString(_type),_ref) : _ref)
+  ts << "\t\t\t<member type=\"" << ElementType(_type).toString().toLower() << "\" ref=\""
+     << (_idMap ? _idMap->getId(_type, _ref) : _ref)
      << "\" role=\"" << _role << "\"/>\n";
   return ts.readAll();
 }
 
-
 }
Clone this wiki locally