From a1d54b48b9702276115237f4f535243184acaafe Mon Sep 17 00:00:00 2001
From: Gerardo Tauriello <gerardo.tauriello@unibas.ch>
Date: Mon, 14 Oct 2019 16:34:35 +0200
Subject: [PATCH] SCHWED-4368: Read revision version numbers from mmCIF files.

---
 modules/io/src/mol/mmcif_reader.cc            | 23 +++++++++++--------
 modules/io/src/mol/mmcif_reader.hh            | 19 ++++++++++++++-
 modules/io/tests/test_mmcif_reader.cc         | 18 ++++++++++++++-
 .../io/tests/testfiles/mmcif/3IMJ_rev_new.cif |  2 +-
 4 files changed, 50 insertions(+), 12 deletions(-)

diff --git a/modules/io/src/mol/mmcif_reader.cc b/modules/io/src/mol/mmcif_reader.cc
index 3641b2e0d..9e8413853 100644
--- a/modules/io/src/mol/mmcif_reader.cc
+++ b/modules/io/src/mol/mmcif_reader.cc
@@ -87,7 +87,7 @@ void MMCifReader::ClearState()
   bu_assemblies_.clear();
   helix_list_.clear();
   strand_list_.clear();
-  revision_dates_.clear();
+  revisions_.clear();
   revision_types_.clear();
   database_PDB_rev_added_ = false;
 }
@@ -339,6 +339,8 @@ bool MMCifReader::OnBeginLoop(const StarLoopDesc& header)
     category_ = PDBX_AUDIT_REVISION_HISTORY;
     // mandatory items
     this->TryStoreIdx(PARH_ORDINAL, "ordinal", header);
+    this->TryStoreIdx(PARH_MAJOR, "major_revision", header);
+    this->TryStoreIdx(PARH_MINOR, "minor_revision", header);
     this->TryStoreIdx(PARH_REVISION_DATE, "revision_date", header);
     cat_available = true;
   } else if (header.GetCategory()=="pdbx_audit_revision_details") {
@@ -1423,8 +1425,12 @@ void MMCifReader::ParsePdbxAuditRevisionHistory(
   int num = this->TryGetInt(columns[indices_[PARH_ORDINAL]],
                             "pdbx_audit_revision_history.ordinal");
   StringRef date = columns[indices_[PARH_REVISION_DATE]];
+  int major = this->TryGetInt(columns[indices_[PARH_MAJOR]],
+                              "pdbx_audit_revision_history.major_revision");
+  int minor = this->TryGetInt(columns[indices_[PARH_MINOR]],
+                              "pdbx_audit_revision_history.minor_revision");
   // add to map
-  revision_dates_[num] = date.str();
+  revisions_.push_back(MMCifRevisionDesc(num, date.str(), major, minor));
 }
 
 void MMCifReader::ParsePdbxAuditRevisionDetails(
@@ -1779,17 +1785,16 @@ void MMCifReader::OnEndData()
 
   // add revision history for new style mmCIFs (only if no old data there)
   if (!database_PDB_rev_added_) {
-    std::map<int, String>::const_iterator rd_it;
-    for (rd_it = revision_dates_.begin(); rd_it != revision_dates_.end();
-         ++rd_it) {
+    std::vector<MMCifRevisionDesc>::const_iterator r_it;
+    for (r_it = revisions_.begin(); r_it != revisions_.end(); ++r_it) {
       // look for status
-      const int num = rd_it->first;
-      const String& date = rd_it->second;
+      const int num = r_it->num;
       std::map<int, String>::const_iterator rt_it = revision_types_.find(num);
       if (rt_it != revision_types_.end()) {
-        info_.AddRevision(num, date, rt_it->second);
+        info_.AddRevision(num, r_it->date, rt_it->second, r_it->major,
+                          r_it->minor);
       } else {
-        info_.AddRevision(num, date, "?");
+        info_.AddRevision(num, r_it->date, "?", r_it->major, r_it->minor);
       }
     }
   }
diff --git a/modules/io/src/mol/mmcif_reader.hh b/modules/io/src/mol/mmcif_reader.hh
index 4a58d567b..e7d0e6bcb 100644
--- a/modules/io/src/mol/mmcif_reader.hh
+++ b/modules/io/src/mol/mmcif_reader.hh
@@ -546,6 +546,8 @@ private:
   typedef enum {
     PARH_ORDINAL,         ///< unique identifier
     PARH_REVISION_DATE,   ///< revision date
+    PARH_MAJOR,           ///< major version
+    PARH_MINOR,           ///< minor version
   } PdbxAuditRevisionHistoryItems;
 
   /// \enum categories of the pdbx_audit_revision_details category
@@ -621,6 +623,21 @@ private:
   } MMCifPSAEntry;
   typedef std::map<String, MMCifPSAEntry> MMCifPSAMap;
 
+  /// \struct keeping track of revision information
+  struct MMCifRevisionDesc {
+    // silly GCC note: major() & minor() exist as macros...facepalm
+    MMCifRevisionDesc(int _num, const String& _date, int _major, int _minor)
+                     : date(_date) {
+      num = _num;
+      major = _major;
+      minor = _minor;
+    }
+    int num;      ///< unique identifier
+    String date;  ///< revision date
+    int major;    ///< major version
+    int minor;    ///< minor version
+  };
+
   // members
   MMCifCategory category_;
   int category_counts_[DONT_KNOW+1]; ///< overall no. of atom_site loops
@@ -653,7 +670,7 @@ private:
   MMCifHSVector strand_list_; ///< for storing struct_conf sec.struct. data
   MMCifInfoStructRefs struct_refs_;
   // for storing revisions 
-  std::map<int, String> revision_dates_;
+  std::vector<MMCifRevisionDesc> revisions_;
   std::map<int, String> revision_types_;
   bool database_PDB_rev_added_;
 };
diff --git a/modules/io/tests/test_mmcif_reader.cc b/modules/io/tests/test_mmcif_reader.cc
index 2711bddcf..b3c9d7c23 100644
--- a/modules/io/tests/test_mmcif_reader.cc
+++ b/modules/io/tests/test_mmcif_reader.cc
@@ -1357,20 +1357,28 @@ BOOST_AUTO_TEST_CASE(mmcif_test_revisions_old)
   const MMCifInfo& info = mmcif_p.GetInfo();
   const MMCifInfoRevisions& revs = info.GetRevisions();
   
-  // check items
+  // check items (note: version numbers only for new mmCIF versions)
   BOOST_CHECK_EQUAL(revs.GetSize(), size_t(3));
   BOOST_CHECK_EQUAL(revs.GetNum(0), 1);
   BOOST_CHECK_EQUAL(revs.GetDate(0), String("2009-11-17"));
   BOOST_CHECK_EQUAL(revs.GetStatus(0), String("full release"));
+  BOOST_CHECK_EQUAL(revs.GetMajor(0), -1);
+  BOOST_CHECK_EQUAL(revs.GetMinor(0), -1);
   BOOST_CHECK_EQUAL(revs.GetNum(1), 2);
   BOOST_CHECK_EQUAL(revs.GetDate(1), String("2011-07-13"));
   BOOST_CHECK_EQUAL(revs.GetStatus(1), String("?"));
+  BOOST_CHECK_EQUAL(revs.GetMajor(1), -1);
+  BOOST_CHECK_EQUAL(revs.GetMinor(1), -1);
   BOOST_CHECK_EQUAL(revs.GetNum(2), 3);
   BOOST_CHECK_EQUAL(revs.GetDate(2), String("2012-12-12"));
   BOOST_CHECK_EQUAL(revs.GetStatus(2), String("?"));
+  BOOST_CHECK_EQUAL(revs.GetMajor(2), -1);
+  BOOST_CHECK_EQUAL(revs.GetMinor(2), -1);
   // check rest
   BOOST_CHECK_EQUAL(revs.GetDateOriginal(), String("2009-08-10"));
   BOOST_CHECK_EQUAL(revs.GetLastDate(), String("2012-12-12"));
+  BOOST_CHECK_EQUAL(revs.GetLastMajor(), -1);
+  BOOST_CHECK_EQUAL(revs.GetLastMinor(), -1);
   BOOST_CHECK_EQUAL(revs.GetFirstRelease(), size_t(1));
 
   BOOST_TEST_MESSAGE("  done.");
@@ -1394,15 +1402,23 @@ BOOST_AUTO_TEST_CASE(mmcif_test_revisions_new)
   BOOST_CHECK_EQUAL(revs.GetNum(0), 1);
   BOOST_CHECK_EQUAL(revs.GetDate(0), String("2009-11-17"));
   BOOST_CHECK_EQUAL(revs.GetStatus(0), String("Initial release"));
+  BOOST_CHECK_EQUAL(revs.GetMajor(0), 1);
+  BOOST_CHECK_EQUAL(revs.GetMinor(0), 0);
   BOOST_CHECK_EQUAL(revs.GetNum(1), 2);
   BOOST_CHECK_EQUAL(revs.GetDate(1), String("2011-07-13"));
   BOOST_CHECK_EQUAL(revs.GetStatus(1), String("?"));
+  BOOST_CHECK_EQUAL(revs.GetMajor(1), 1);
+  BOOST_CHECK_EQUAL(revs.GetMinor(1), 1);
   BOOST_CHECK_EQUAL(revs.GetNum(2), 3);
   BOOST_CHECK_EQUAL(revs.GetDate(2), String("2012-12-12"));
   BOOST_CHECK_EQUAL(revs.GetStatus(2), String("?"));
+  BOOST_CHECK_EQUAL(revs.GetMajor(2), 2);
+  BOOST_CHECK_EQUAL(revs.GetMinor(2), 0);
   // check rest
   BOOST_CHECK_EQUAL(revs.GetDateOriginal(), String("2009-08-10"));
   BOOST_CHECK_EQUAL(revs.GetLastDate(), String("2012-12-12"));
+  BOOST_CHECK_EQUAL(revs.GetLastMajor(), 2);
+  BOOST_CHECK_EQUAL(revs.GetLastMinor(), 0);
   BOOST_CHECK_EQUAL(revs.GetFirstRelease(), size_t(1));
 
   BOOST_TEST_MESSAGE("  done.");
diff --git a/modules/io/tests/testfiles/mmcif/3IMJ_rev_new.cif b/modules/io/tests/testfiles/mmcif/3IMJ_rev_new.cif
index bbc66a301..47ca475fc 100644
--- a/modules/io/tests/testfiles/mmcif/3IMJ_rev_new.cif
+++ b/modules/io/tests/testfiles/mmcif/3IMJ_rev_new.cif
@@ -25,7 +25,7 @@ _pdbx_audit_revision_history.minor_revision
 _pdbx_audit_revision_history.revision_date 
 1 'Structure model' 1 0 2009-11-17 
 2 'Structure model' 1 1 2011-07-13 
-3 'Structure model' 1 2 2012-12-12 
+3 'Structure model' 2 0 2012-12-12 
 # 
 _pdbx_audit_revision_details.ordinal             1 
 _pdbx_audit_revision_details.revision_ordinal    1 
-- 
GitLab