From bdf1bdee4aba75299eed090fc4f34b216ebc5d17 Mon Sep 17 00:00:00 2001
From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch>
Date: Mon, 8 Jul 2024 21:40:59 +0200
Subject: [PATCH] MetaData - Put the plugin names into the meta data of the
 database

---
 .../GeoModelKernel/GeoVGeometryPlugin.h       |  27 +--
 GeoModelTools/GMCAT/src/gmcat.cxx             |  59 +++---
 GeoModelTools/GMCAT/src/publishMetaData.cpp   | 195 +++++++-----------
 3 files changed, 123 insertions(+), 158 deletions(-)

diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVGeometryPlugin.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVGeometryPlugin.h
index ec9b5aa56..ff028c3bf 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVGeometryPlugin.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoVGeometryPlugin.h
@@ -22,29 +22,30 @@ class GeoVGeometryPlugin
 {
  public:
 
-   //! Default constructor.
-   GeoVGeometryPlugin() : m_publisher(nullptr) {}
+    //! Default constructor.
+    GeoVGeometryPlugin() = default;
      
-  //! Parametrized constructor for plugins that publish lists of nodes 
-  GeoVGeometryPlugin(std::string name) : m_publisher(std::make_unique<GeoPublisher>()), m_pluginName( name ) {  m_publisher->setName(m_pluginName); } 
+    //! Parametrized constructor for plugins that publish lists of nodes 
+    GeoVGeometryPlugin(const std::string& name) : 
+        m_pluginName{name} {  m_publisher->setName(m_pluginName); } 
     
 
-  virtual ~GeoVGeometryPlugin() {}
+    virtual ~GeoVGeometryPlugin()  = default;
 
-  //! Create the system geometry.
-  /// Note: this is a pure virtual method, so you need to implement it in your derived plugin class
-  virtual void create ( GeoVPhysVol* world, bool publish = false ) = 0;
+    //! Create the system geometry.
+    /// Note: this is a pure virtual method, so you need to implement it in your derived plugin class
+    virtual void create ( GeoVPhysVol* world, bool publish = false ) = 0;
 
-  //! Returns the plugin's name
-  std::string getName() { return m_pluginName; }
+    //! Returns the plugin's name
+    std::string getName() const { return m_pluginName; }
 
-  //! Returns the Publisher that publishes the lists of the GeoFullPhysVol and AlignableTransform nodes
-  GeoPublisher* getPublisher() { return m_publisher.get(); }
+    //! Returns the Publisher that publishes the lists of the GeoFullPhysVol and AlignableTransform nodes
+    GeoPublisher* getPublisher() { return m_publisher.get(); }
 
  protected:
 
   //! A GeoPublisher instance is used to publish lists of nodes.
-  std::unique_ptr<GeoPublisher> m_publisher;
+  std::unique_ptr<GeoPublisher> m_publisher{std::make_unique<GeoPublisher>()};
   
  private:
 
diff --git a/GeoModelTools/GMCAT/src/gmcat.cxx b/GeoModelTools/GMCAT/src/gmcat.cxx
index 301a534ac..4fa4f0973 100644
--- a/GeoModelTools/GMCAT/src/gmcat.cxx
+++ b/GeoModelTools/GMCAT/src/gmcat.cxx
@@ -35,10 +35,11 @@ const std::string shared_obj_extension=".so";
 
 
 void publishMetaData( GMDBManager & db,
-		      const std::string& repoPath,
-		      std::vector<std::string> &inputFiles,
-		      std::vector<std::string> &inputPlugins,
-		      std::string              &outputFile);
+                      const std::string& repoPath,
+                      const std::vector<std::string> &inputFiles,
+                      const std::vector<std::string> &inputPlugins,
+                      const std::vector<std::string> &pluginNames,
+                      const std::string              &outputFile);
 
 int main(int argc, char ** argv) {
 
@@ -65,8 +66,7 @@ int main(int argc, char ** argv) {
   //
   // Parse the command line:
   //
-  std::vector<std::string> inputFiles;
-  std::vector<std::string> inputPlugins;
+  std::vector<std::string> inputFiles{}, inputPlugins{};
   std::string outputFile;
   std::string gmAtlasDir{"."};
   bool outputFileSet = false;
@@ -86,7 +86,7 @@ int main(int argc, char ** argv) {
           verbose=true;
       }
       else if (argument.find("-g")!=std::string::npos) {
-	gmAtlasDir = std::string(argv[++argi]);
+          gmAtlasDir = std::string(argv[++argi]);
       }
       else if (argument.find(shared_obj_extension)!=std::string::npos) {
           inputPlugins.push_back(argument);
@@ -112,8 +112,8 @@ int main(int argc, char ** argv) {
   if (access(outputFile.c_str(),F_OK)==0) {
     if (!access(outputFile.c_str(),W_OK)) {
       if (system(("rm -f "+ outputFile).c_str())) {
-	std::cerr << "gmcat -- Error, cannot overwrite existing file " << outputFile << std::endl;
-	return 3;
+          std::cerr << "gmcat -- Error, cannot overwrite existing file " << outputFile << std::endl;
+          return 3;
       }
     }
     else {
@@ -142,6 +142,7 @@ int main(int argc, char ** argv) {
   }
   
   std::vector<GeoPublisher*> vecPluginsPublishers; // caches the stores from all plugins
+  std::vector<std::unique_ptr<GeoVGeometryPlugin>> pluginInstances{};
   for (const std::string & plugin : inputPlugins) {
     GeoGeometryPluginLoader loader;
 
@@ -151,7 +152,7 @@ int main(int argc, char ** argv) {
       std::cout.rdbuf(fileBuff);
     }
 
-    GeoVGeometryPlugin *factory=loader.load(plugin);
+    std::unique_ptr<GeoVGeometryPlugin> factory{loader.load(plugin)};
     if (!factory) {
       std::cerr << "gmcat -- Could not load plugin " << plugin << std::endl;
       return 5;
@@ -172,6 +173,7 @@ int main(int argc, char ** argv) {
       std::cout << "\t ... DONE!" << std::endl;
       std::cout.rdbuf(fileBuff);
     }
+    pluginInstances.emplace_back(std::move(factory));
   }
 
   //
@@ -184,41 +186,35 @@ int main(int argc, char ** argv) {
       std::cout.rdbuf(fileBuff);
     }
 
-    GMDBManager* db = new GMDBManager(file);
+    auto db = std::make_unique<GMDBManager>(file);
     if (!db->checkIsDBOpen()){
       std::cerr << "gmcat -- Error opening the input file: " << file << std::endl;
       return 6;
     }
 
     /* set the GeoModel reader */
-    GeoModelIO::ReadGeoModel readInGeo = GeoModelIO::ReadGeoModel(db);
+    GeoModelIO::ReadGeoModel readInGeo = GeoModelIO::ReadGeoModel(db.get());
 
     /* build the GeoModel geometry */
-    const GeoVPhysVol* dbPhys = readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory
+   PVConstLink dbPhys{readInGeo.buildGeoModel()}; // builds the whole GeoModel tree in memory
 
     /* get an handle on a Volume Cursor, to traverse the whole set of Volumes */
     GeoVolumeCursor aV(dbPhys);
 
     /* loop over the Volumes in the tree */
     while (!aV.atEnd()) {
-
-	if (aV.getName()!="ANON") {
-	  GeoNameTag *nameTag=new GeoNameTag(aV.getName());
-	  world->add(nameTag);
-	}
-	GeoTransform *transform= new GeoTransform(aV.getTransform());
-	world->add(transform);
-	world->add((GeoVPhysVol *) &*aV.getVolume());
-	aV.next();
+        if (aV.getName()!="ANON") {
+          world->add(make_intrusive<GeoNameTag>(aV.getName()));
+        }
+        world->add(make_intrusive<GeoTransform>(aV.getTransform()));
+        world->add(const_pointer_cast(aV.getVolume()));
+        aV.next();
     }
-
-    delete db;
     if(!verbose) {
       std::cout.rdbuf(coutBuff);
       std::cout << "\t ... DONE!" << std::endl;
       std::cout.rdbuf(fileBuff);
     }
-
   }
   //
   // Open a new database:
@@ -259,10 +255,17 @@ int main(int argc, char ** argv) {
     std::cout << "Writing metadata to the output database ..." << std::endl;
     std::cout.rdbuf(fileBuff);
   }
-  try {
-    publishMetaData(db,gmAtlasDir,inputFiles,inputPlugins,outputFile);
+  std::vector<std::string> systemNames{};
+  for (auto& plugin : pluginInstances) {
+    if(plugin->getName().size()){
+      systemNames.push_back(plugin->getName());
+    }
   }
-  catch(std::runtime_error& e) {
+  std::sort(systemNames.begin(), systemNames.end());
+
+  try {
+    publishMetaData(db, gmAtlasDir, inputFiles, inputPlugins, systemNames, outputFile);
+  } catch(const std::runtime_error& e) {
     std::cerr << "ERROR: " << e.what() << std::endl;
     return 1;
   }
diff --git a/GeoModelTools/GMCAT/src/publishMetaData.cpp b/GeoModelTools/GMCAT/src/publishMetaData.cpp
index edce9cb89..5b973046e 100644
--- a/GeoModelTools/GMCAT/src/publishMetaData.cpp
+++ b/GeoModelTools/GMCAT/src/publishMetaData.cpp
@@ -1,4 +1,5 @@
 #include "GeoModelDBManager/GMDBManager.h"
+#include <GeoModelHelpers/StringUtils.h>
 #include <string>
 #include <iostream>
 #include <unistd.h>
@@ -10,11 +11,12 @@
 #define STR_VALUE(arg) #arg
 #define STR_NAME(name) STR_VALUE(name)
 
-std::string resolveVariable(const std::string& varName) {
-   const char* var = std::getenv(varName.c_str());
-   if (!var) return std::string{};
-   return std::string(var);
+namespace{
+    static const std::string tableName{"AAHEADER"};
 }
+
+using tableVariant = std::variant<int,long,float,double,std::string>;
+
 std::string getCommandOutput(const std::string & cmd, bool firstLineOnly=false)
 {
   std::string response;
@@ -33,19 +35,20 @@ std::string getCommandOutput(const std::string & cmd, bool firstLineOnly=false)
 }
 
 void publishMetaData( GMDBManager & db,
-		      const std::string& repoPath,
-		      std::vector<std::string> &inputFiles,
-		      std::vector<std::string> &inputPlugins,
-		      std::string              &outputFile) {
+                      const std::string& repoPath,
+                      const std::vector<std::string> &inputFiles,
+                      const std::vector<std::string> &inputPlugins,
+                      const std::vector<std::string> &pluginNames,
+                      const std::string              &outputFile) {
 
   struct Metadata {
     std::string dateString=getCommandOutput("date -Iminutes");
-    std::string username{resolveVariable("USER")};
+    std::string username{GeoStrUtils::resolveEnviromentVariables("${USER}")};
     std::string hostname{};
-    std::string os;
-    std::string wd;
+    std::string os{};
+    std::string wd{};
     std::string gmversion=STR_NAME(GMVERSION);
-    std::string outputFile;
+    std::string outputFile{};
     std::string geoModelDataBranch="Undefined";      // or overwritten below
     std::string gmdataIsClean     ="Not applicable"; // or overwritten below
     std::string gmdataCommitHash  ="Undefined";      // or overwritten below
@@ -64,7 +67,7 @@ void publishMetaData( GMDBManager & db,
   char wdbuff[1024];
   metadata.wd=std::string(getcwd(wdbuff,1024));
 #else
-  metadata.wd= resolveVariable("PWD");
+  metadata.wd= GeoStrUtils::resolveEnviromentVariables("${PWD}");
 #endif
 
   metadata.outputFile=outputFile;
@@ -78,24 +81,22 @@ void publishMetaData( GMDBManager & db,
     if (gethostname (hn,1024)==0) metadata.hostname=std::string(hn);
   }
   
-  std::string geomodel_xml_dir=resolveVariable("GEOMODEL_XML_DIR");
+  std::string geomodel_xml_dir=GeoStrUtils::resolveEnviromentVariables("${GEOMODEL_XML_DIR}");
   if (!geomodel_xml_dir.empty())  {
     {
       metadata.geoModelDataBranch=getCommandOutput("git -C "+ geomodel_xml_dir + " rev-parse --abbrev-ref HEAD");
       std::string shortGitStatus=getCommandOutput("git -C "+ geomodel_xml_dir + " status -s ");
       if (shortGitStatus!="") {
-	metadata.gmdataIsClean="no";
-      }
-      else {
-	std::string synchedToOrigin=getCommandOutput("git -C "+ std::string(geomodel_xml_dir) + " diff origin/"+metadata.geoModelDataBranch,true);
-	if (synchedToOrigin!="") {
-	  metadata.gmdataIsClean="no";
-	}
-	else {
-	  metadata.gmdataIsClean="yes";
-	  metadata.gmdataCommitHash=getCommandOutput("git -C " + std::string(geomodel_xml_dir) + " log -1 --format=format:\"%H\"");
-	  metadata.gmdataAssociatedTag=getCommandOutput("git -C " + std::string(geomodel_xml_dir) +  " describe --tag " + metadata.gmdataCommitHash+ "  2> /dev/null");
-	}
+        metadata.gmdataIsClean="no";
+      } else {
+        std::string synchedToOrigin=getCommandOutput("git -C "+ std::string(geomodel_xml_dir) + " diff origin/"+metadata.geoModelDataBranch,true);
+        if (synchedToOrigin.size()) {
+            metadata.gmdataIsClean="no";
+        }else {
+            metadata.gmdataIsClean="yes";
+            metadata.gmdataCommitHash=getCommandOutput("git -C " + std::string(geomodel_xml_dir) + " log -1 --format=format:\"%H\"");
+            metadata.gmdataAssociatedTag=getCommandOutput("git -C " + std::string(geomodel_xml_dir) +  " describe --tag " + metadata.gmdataCommitHash+ "  2> /dev/null");
+        }
       }
     }
   }
@@ -109,59 +110,46 @@ void publishMetaData( GMDBManager & db,
     }
     else {
       std::string synchedToOrigin=getCommandOutput("git -C " + repoPath + " diff origin/"+xtraMetadata.branch,true);
-      if (synchedToOrigin!="") {
-	xtraMetadata.isClean="no";
-      }
-      else {
-	xtraMetadata.isClean="yes";
-	xtraMetadata.commitHash=getCommandOutput("git -C " + repoPath + " log -1 --format=format:\"%H\"");
-	xtraMetadata.associatedTag=getCommandOutput("git -C " + repoPath + " describe --tag " + xtraMetadata.commitHash+ "  2> /dev/null");
+      xtraMetadata.isClean = synchedToOrigin.empty() ? "yes" : "no";
+      if (synchedToOrigin.empty()){
+        xtraMetadata.commitHash=getCommandOutput("git -C " + repoPath + " log -1 --format=format:\"%H\"");
+        xtraMetadata.associatedTag=getCommandOutput("git -C " + repoPath + " describe --tag " + xtraMetadata.commitHash+ "  2> /dev/null");
       }
     }
-  }
-  else {
+  } else {
     std::cerr << std::endl << "WARNING: no information on User repository will be written to metadata. " << std::endl;
   }
 
   //
   // Fill the header file with metadata
   //
-  std::vector<std::string>                                                   gmcatColNames={"Date",
-											    "GeoModelDataBranch",
-											    "Username",
-											    "Hostname",
-											    "OS",
-											    "WorkingDirectory",
-											    "GeoModelVersion",
-											    "OutputFile",
-											    "GeoModelDataIsClean",
-											    "GeoModelDataCommitHash",
-											    "GeoModelDataAssociatedTag"
-  };
-  std::vector<std::string>                                                   gmcatColTypes={"STRING",
-											    "STRING" ,
-											    "STRING",
-											    "STRING",
-											    "STRING",
-											    "STRING",
-											    "STRING",
-											    "STRING",
-											    "STRING",
-											    "STRING",
-											    "STRING"
-  };
-  
+  std::vector<std::string> gmcatColNames={"Date",
+                                          "GeoModelDataBranch",
+                                          "Username",
+                                          "Hostname",
+                                          "OS",
+                                          "WorkingDirectory",
+                                          "GeoModelVersion",
+                                          "OutputFile",
+                                          "PluginNames",
+                                          "PluginLibs",
+                                          "DataBaseFiles",
+                                          "GeoModelDataIsClean",
+                                          "GeoModelDataCommitHash",
+                                          "GeoModelDataAssociatedTag",
+                                          tableName + "_DATA_ID"
+                                           };
+  std::vector<std::string>  gmcatColTypes(gmcatColNames.size(), "STRING");
+  gmcatColTypes[gmcatColTypes.size() - 1] = "INT";
   // Strip extraneous \n
-  for (std::string * s : {
-      &metadata.geoModelDataBranch,
-      &metadata.dateString,
-      &metadata.gmdataAssociatedTag}) { 
-    s->erase(std::remove(s->begin(), s->end(), '\n'), s->end());
+  for (std::string * s : {&metadata.geoModelDataBranch,  &metadata.dateString, 
+                          &metadata.gmdataAssociatedTag, &xtraMetadata.repo, &xtraMetadata.branch}) { 
+       s->erase(std::remove(s->begin(), s->end(), '\n'), s->end());
   }
-	
-	
+    
+    
   
-  std::vector<std::vector<std::variant<int,long,float,double,std::string>>>  gmcatData    ={{
+  std::vector<std::vector<tableVariant>>  gmcatData    ={{
       metadata.dateString,
       metadata.geoModelDataBranch,
       metadata.username,
@@ -170,59 +158,32 @@ void publishMetaData( GMDBManager & db,
       metadata.wd,
       metadata.gmversion,
       metadata.outputFile,
+      GeoStrUtils::chainUp(pluginNames,";"),      
+      GeoStrUtils::chainUp(inputPlugins,";"),
+      GeoStrUtils::chainUp(inputFiles,";"),
       metadata.gmdataIsClean,
       metadata.gmdataCommitHash,
-      metadata.gmdataAssociatedTag
+      metadata.gmdataAssociatedTag,
+      0
     }};
 
-  unsigned int pcounter(0);
-  for (std::string plugin : inputPlugins) {
-    gmcatColNames.push_back("P"+std::to_string(pcounter++));
-    gmcatColTypes.push_back("STRING");
-    gmcatData[0].push_back((plugin));
-  }
-  unsigned int fcounter(0);
-  for (std::string file : inputFiles) {
-    gmcatColNames.push_back("F"+std::to_string(fcounter++));
-    gmcatColTypes.push_back("STRING");
-    gmcatData[0].push_back(file);
-  }
-  
-  // Strip extraneous \n
-  for (std::string * s : {
-      &xtraMetadata.repo,
-      &xtraMetadata.branch }) { 
-    s->erase(std::remove(s->begin(), s->end(), '\n'), s->end());
-  }
-	
-
-
   if (xtraMetadata.branch!="Undefined") {
-    std::vector<std::string>                                                   xtraColNames={
-      "UserCodeGitRepository",
-      "UserCodeGitBranch",
-      "UserCodeRepoIsClean",
-      "UserCodeRepoCommitHash",
-      "UserCodeAssociatedTag"};
-    std::vector<std::string>                                                   xtraColTypes={"STRING",
-											     "STRING",
-											     "STRING",
-											     "STRING",
-											     "STRING"};
-    std::vector<std::vector<std::variant<int,long,float,double,std::string>>>  xtraData    ={{
-	xtraMetadata.repo,
-	xtraMetadata.branch,
-	xtraMetadata.isClean,
-	xtraMetadata.commitHash,
-	xtraMetadata.associatedTag
-    }};    
-    using std::begin, std::end;
-    gmcatColNames.insert(end(gmcatColNames), begin(xtraColNames), end(xtraColNames));
-    gmcatColTypes.insert(end(gmcatColTypes), begin(xtraColTypes), end(xtraColTypes));
-    gmcatData[0].insert(end(gmcatData[0]), begin(xtraData[0]), end(xtraData[0]));
-    db.createCustomTable("AAHEADER", gmcatColNames,gmcatColTypes,gmcatData);
-  }
-  else {
-    db.createCustomTable("AAHEADER", gmcatColNames,gmcatColTypes,gmcatData); 
+    std::vector<std::string> xtraColNames={"UserCodeGitRepository",
+                                           "UserCodeGitBranch",
+                                           "UserCodeRepoIsClean",
+                                           "UserCodeRepoCommitHash",
+                                           "UserCodeAssociatedTag"};
+    std::vector<std::string> xtraColTypes(xtraColNames.size(), "STRING");
+    std::vector<std::vector<tableVariant>>  xtraData    ={{xtraMetadata.repo,
+                                                           xtraMetadata.branch,
+                                                           xtraMetadata.isClean,
+                                                           xtraMetadata.commitHash,
+                                                           xtraMetadata.associatedTag }};    
+    gmcatColNames.insert(std::end(gmcatColNames), std::begin(xtraColNames), std::end(xtraColNames));
+    gmcatColTypes.insert(std::end(gmcatColTypes), std::begin(xtraColTypes), std::end(xtraColTypes));
+    gmcatData[0].insert(std::end(gmcatData[0]), std::begin(xtraData[0]), std::end(xtraData[0]));
+   
   }
+  db.createCustomTable(tableName, gmcatColNames,gmcatColTypes,gmcatData); 
+  
 }
-- 
GitLab