Skip to content

v0.2.53..v0.2.54 changeset DiffCmd.cpp

Garret Voltz edited this page Mar 31, 2020 · 1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/cmd/DiffCmd.cpp b/hoot-core/src/main/cpp/hoot/core/cmd/DiffCmd.cpp
index c995c3a..fa50385 100644
--- a/hoot-core/src/main/cpp/hoot/core/cmd/DiffCmd.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/cmd/DiffCmd.cpp
@@ -22,21 +22,26 @@
  * This will properly maintain the copyright information. DigitalGlobe
  * copyrights will be updated automatically.
  *
- * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019 DigitalGlobe (http://www.digitalglobe.com/)
+ * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020 DigitalGlobe (http://www.digitalglobe.com/)
  */
 
 // Hoot
-#include <hoot/core/util/Factory.h>
-#include <hoot/core/util/MapProjector.h>
 #include <hoot/core/cmd/BaseCommand.h>
-#include <hoot/core/scoring/MapComparator.h>
-#include <hoot/core/util/Settings.h>
 #include <hoot/core/elements/OsmMap.h>
-#include <hoot/core/util/Log.h>
 #include <hoot/core/io/IoUtils.h>
+#include <hoot/core/io/OsmApiChangeset.h>
+#include <hoot/core/scoring/MapComparator.h>
+#include <hoot/core/util/Factory.h>
+#include <hoot/core/util/Log.h>
+#include <hoot/core/util/MapProjector.h>
+#include <hoot/core/util/Settings.h>
+#include <hoot/core/ops/DuplicateNodeRemover.h>
 
 using namespace std;
 
+#include <QDir>
+#include <QFileInfo>
+
 namespace hoot
 {
 
@@ -51,36 +56,39 @@ public:
   virtual QString getName() const override { return "diff"; }
 
   virtual QString getDescription() const override
-  { return "Calculates the difference between two maps"; }
+  { return "Calculates the difference between two maps or changesets"; }
 
   virtual int runSimple(QStringList& args) override
   {
-    MapComparator mapCompare;
+    bool ignoreUuid = false;
+    bool useDateTime = false;
+    bool setErrorLimit = false;
+    int errorLimit = -1;
 
     if (args.contains("--ignore-uuid"))
     {
       args.removeAll("--ignore-uuid");
-      mapCompare.setIgnoreUUID();
+      ignoreUuid = true;
     }
 
     if (args.contains("--use-datetime"))
     {
       args.removeAll("--use-datetime");
-      mapCompare.setUseDateTime();
+      useDateTime = true;
     }
 
     if (args.contains("--error-limit"))
     {
       const int errorLimitIndex = args.indexOf("--error-limit");
       bool ok = false;
-      const int errorLimit = args.at(errorLimitIndex + 1).trimmed().toInt(&ok);
+      errorLimit = args.at(errorLimitIndex + 1).trimmed().toInt(&ok);
       if (!ok)
       {
         throw IllegalArgumentException("Invalid error limit: " + args.at(errorLimitIndex + 1));
       }
       args.removeAt(errorLimitIndex + 1);
       args.removeAt(errorLimitIndex);
-      mapCompare.setErrorLimit(errorLimit);
+      setErrorLimit = true;
     }
 
     if (args.size() != 2)
@@ -89,26 +97,66 @@ public:
       throw HootException(QString("%1 takes two parameters.").arg(getName()));
     }
 
-    OsmMapPtr map1(new OsmMap());
-    IoUtils::loadMap(map1, args[0], true, Status::Unknown1);
-    //  Some maps that don't have IDs cooked in will fail comparison if the IDs aren't reset
-    OsmMap::resetCounters();
-    OsmMapPtr map2(new OsmMap());
-    IoUtils::loadMap(map2, args[1], true, Status::Unknown1);
+    // We always want to know if there are duplicate nodes during comparison.
+    conf().set(ConfigOptions::getMapMergeIgnoreDuplicateIdsKey(), true);
 
-    int result;
+    QString pathname1 = args[0];
+    QString pathname2 = args[1];
 
-    if (mapCompare.isMatch(map1, map2))
+    int result = 1;
+    //  Compare changesets differently than all other types
+    if (pathIsChangeset(pathname1) && pathIsChangeset(pathname2))
     {
-      result = 0;
+      XmlChangeset changeset1(pathname1);
+      XmlChangeset changeset2(pathname2);
+
+      if (changeset1.isMatch(changeset2))
+        result = 0;
     }
     else
     {
-      result = 1;
+      MapComparator mapCompare;
+      if (ignoreUuid)
+        mapCompare.setIgnoreUUID();
+      if (useDateTime)
+        mapCompare.setUseDateTime();
+      if (setErrorLimit)
+        mapCompare.setErrorLimit(errorLimit);
+
+      OsmMapPtr map1(new OsmMap());
+      IoUtils::loadMap(map1, pathname1, true, Status::Unknown1);
+      //  Some maps that don't have IDs cooked in will fail comparison if the IDs aren't reset
+      OsmMap::resetCounters();
+      OsmMapPtr map2(new OsmMap());
+      IoUtils::loadMap(map2, pathname2, true, Status::Unknown1);
+
+      if (mapCompare.isMatch(map1, map2))
+        result = 0;
     }
 
     return result;
   }
+
+  bool pathIsChangeset(const QString& path)
+  {
+    QFileInfo fi(path);
+    //  .osc files
+    if (fi.exists() && path.endsWith(".osc", Qt::CaseInsensitive))
+      return true;
+    //  Directories containing .osc files
+    if (fi.isDir())
+    {
+      QDir dir(path);
+      dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
+      dir.setSorting(QDir::Name | QDir::IgnoreCase);
+      QStringList filters;
+      filters << "*.osc";
+      dir.setNameFilters(filters);
+      //  As long as the directory contains at least one .osc file
+      return dir.entryInfoList().size() > 0;
+    }
+    return false;
+  }
 };
 
 HOOT_FACTORY_REGISTER(Command, DiffCmd)
Clone this wiki locally