Skip to content

v0.2.47..v0.2.48 changeset PreserveTypesTagMerger.cpp

Garret Voltz edited this page Sep 27, 2019 · 1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/schema/PreserveTypesTagMerger.cpp b/hoot-core/src/main/cpp/hoot/core/schema/PreserveTypesTagMerger.cpp
index a6e83d5..bc27649 100644
--- a/hoot-core/src/main/cpp/hoot/core/schema/PreserveTypesTagMerger.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/schema/PreserveTypesTagMerger.cpp
@@ -68,6 +68,7 @@ Tags PreserveTypesTagMerger::mergeTags(const Tags& t1, const Tags& t2, ElementTy
     tagsToBeOverwritten = t2;
   }
 
+  // handle name and text tags in the standard fashion
   TagComparator::getInstance().mergeNames(tagsToOverwriteWith, tagsToBeOverwritten, result);
   TagComparator::getInstance().mergeText(tagsToOverwriteWith, tagsToBeOverwritten, result);
   LOG_TRACE("Tags after name/text merging: " << result);
@@ -83,8 +84,8 @@ Tags PreserveTypesTagMerger::mergeTags(const Tags& t1, const Tags& t2, ElementTy
   }
   LOG_TRACE("Tags after alt_types handling: " << result);
 
-  //combine the rest of the tags together; if two tags with the same key are found, use the most
-  //specific one or use both if they aren't related in any way
+  // Combine the rest of the tags together. If two tags with the same key are found, use the most
+  // specific one. Keep both if they aren't related in any way.
   OsmSchema& schema = OsmSchema::getInstance();
   for (Tags::ConstIterator it = tagsToOverwriteWith.constBegin();
        it != tagsToOverwriteWith.constEnd(); ++it)
@@ -93,12 +94,14 @@ Tags PreserveTypesTagMerger::mergeTags(const Tags& t1, const Tags& t2, ElementTy
     LOG_VART(it.value());
 
     bool skippingTagPreservation = false;
+    // ignore tags that we're specified to be explicitly skipped
     if (_skipTagKeys.find(it.key()) != _skipTagKeys.end())
     {
       LOG_TRACE(
         "Explicitly skipping type handling for tag: " << it.key() << "=" <<  it.value() << "...");
       skippingTagPreservation = true;
     }
+    // ignore metadata tags
     else if (schema.isMetaData(it.key(), it.value()))
     {
       LOG_TRACE(
@@ -119,18 +122,20 @@ Tags PreserveTypesTagMerger::mergeTags(const Tags& t1, const Tags& t2, ElementTy
     if (!skippingTagPreservation && !tagsToBeOverwritten[it.key()].trimmed().isEmpty())
     {
       LOG_VART(tagsToBeOverwritten[it.key()]);
-      //if one is more specific than the other, add it, but then remove both tags so we don't
-      //try to add them again
-      if (schema.isAncestor(
-            it.key() % "=" % tagsToBeOverwritten[it.key()], it.key() % "=" % it.value()))
+      // If one is more specific than the other, add it, but then remove both tags so we don't
+      // try to add them again.
+      //if (schema.isAncestor(
+            //it.key() % "=" % tagsToBeOverwritten[it.key()], it.key() % "=" % it.value()))
+      if (_isAncestor(it.key(), tagsToBeOverwritten[it.key()], it.key(), it.value()))
       {
         LOG_TRACE(
           it.key() % "=" % tagsToBeOverwritten[it.key()] << " is more specific than " <<
           it.key() % "=" % it.value() << ".  Using more specific tag.");
         result[it.key()] = tagsToBeOverwritten[it.key()];
       }
-      else if (schema.isAncestor(
-                 it.key() % "=" % it.key(), it.key() % "=" % tagsToBeOverwritten[it.value()]))
+      //else if (schema.isAncestor(
+                 //it.key() % "=" % it.value(), it.key() % "=" % tagsToBeOverwritten[it.key()]))
+      else if (_isAncestor(it.key(), it.value(), it.key(), tagsToBeOverwritten[it.key()]))
       {
         LOG_TRACE(
           it.key() % "=" % it.value() << " is more specific than " <<
@@ -139,10 +144,17 @@ Tags PreserveTypesTagMerger::mergeTags(const Tags& t1, const Tags& t2, ElementTy
       }
       else if (it.key() != ALT_TYPES_TAG_KEY)
       {
-        //arbitrarily use first one and add second to an alt_types field
-        LOG_TRACE(
-          "Both tag sets contain same type: " << it.key() <<
-          " but neither is more specific.  Keeping both...");
+        if (tagsToBeOverwritten[it.key()] == tagsToOverwriteWith[it.key()])
+        {
+          LOG_TRACE("Merging duplicate tag: " << it.key() << "=" << it.value() << "...");
+        }
+        else
+        {
+          // arbitrarily use first tag and add the second to an alt_types field
+          LOG_TRACE(
+            "Both tag sets contain same type: " << it.key() <<
+            " but neither is more specific.  Keeping both...");
+        }
         result[it.key()] = it.value();
         LOG_VART(result[ALT_TYPES_TAG_KEY]);
         if (!result[ALT_TYPES_TAG_KEY].trimmed().isEmpty())
@@ -161,6 +173,8 @@ Tags PreserveTypesTagMerger::mergeTags(const Tags& t1, const Tags& t2, ElementTy
         LOG_VART(result[ALT_TYPES_TAG_KEY]);
       }
     }
+    // None of the special cases for skipping or type merging apply to this tag, so let's just add
+    // it as is.
     else if (!it.value().isEmpty())
     {
       LOG_TRACE("Adding tag: " << it.key() << "=" << it.value() << "...");
@@ -169,6 +183,7 @@ Tags PreserveTypesTagMerger::mergeTags(const Tags& t1, const Tags& t2, ElementTy
   }
   LOG_TRACE("Tags after type handling: " << result);
 
+  // handle all the remaining tags that don't conflict
   for (Tags::ConstIterator it = tagsToBeOverwritten.constBegin();
        it != tagsToBeOverwritten.constEnd(); ++it)
   {
@@ -189,6 +204,26 @@ Tags PreserveTypesTagMerger::mergeTags(const Tags& t1, const Tags& t2, ElementTy
   return result;
 }
 
+bool PreserveTypesTagMerger::_isAncestor(const QString& childKey, const QString& childVal,
+                                         const QString& parentKey, const QString& parentVal) const
+{
+  // It seems like OsmSchema::isAncestor doesn't handle generic type tags correctly, e.g.
+  // building=yes. Its also possible that it does handle them correctly and our schema is not
+  // correct somehow. Until that's determined, I'm adding this custom logic to make sure that if,
+  // for example, building=yes is compared to building=mosque we always end up with the more
+  // specific building=mosque in the output.
+
+  // If the tags have the same key, the parent is generic, and the child is not, the parent is
+  // an ancestor of the child. not completely sure this is covering all possible cases yet...
+  if (childKey == parentKey && (parentVal == "yes" || parentVal == "true") && childVal != "yes" &&
+      childVal != "true")
+  {
+    return true;
+  }
+  return
+    OsmSchema::getInstance().isAncestor(childKey % "=" % childVal, parentKey % "=" % parentVal);
+}
+
 void PreserveTypesTagMerger::_removeRedundantAltTypeTags(Tags& tags) const
 {
   LOG_VART(tags.contains(ALT_TYPES_TAG_KEY));
Clone this wiki locally