diff --git a/GeoModelExamples/CMakeLists.txt b/GeoModelExamples/CMakeLists.txt
index 0484346f4ef61f7fecfdd6c38ac9fcccf27b2cbc..4f322aa26a3cb5b1d88345c6fe778b7deba9129f 100644
--- a/GeoModelExamples/CMakeLists.txt
+++ b/GeoModelExamples/CMakeLists.txt
@@ -11,10 +11,14 @@ project( "GeoModelExamples" VERSION 4.1.0 LANGUAGES CXX )
 
 # Getting-started examples
 add_subdirectory( KitchenSinkPlugin )
+add_subdirectory( MinimalPlugin )
 
 add_subdirectory( HelloGeo )
 add_subdirectory( HelloGeoWrite )
-#add_subdirectory( HelloGeoRead )
+add_subdirectory( HelloGeoWriteReadWrite )
+add_subdirectory( HelloGeoRead )
+add_subdirectory( HelloGeoReadNodeAction )
+
 #add_subdirectory( HelloDummyMaterial )
 #add_subdirectory( HelloToy )
 #add_subdirectory( HelloToyDetectorFactory )
diff --git a/GeoModelExamples/HelloGeoRead/main.cpp b/GeoModelExamples/HelloGeoRead/main.cpp
index afd8567165d297ab23f7ae4780c57f38c028ce17..00765ec207682ef11689d1d56d713b07442c1636 100644
--- a/GeoModelExamples/HelloGeoRead/main.cpp
+++ b/GeoModelExamples/HelloGeoRead/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
 
 /*
  * HelloGeo.cpp
@@ -66,25 +66,35 @@ GeoPhysVol* createTheWorld(GeoPhysVol* world)
 
 int main(int argc, char *argv[])
 {
-  // QCoreApplication app(argc, argv);
 
-  // GET GEOMETRY FROM LOCAL DB
-  // Set valid db path before first run
-  const std::string path = "geometry.db";
-  std::cout << "Using this DB file:" << path << std::endl;
+    if(argc != 2)
+    {
+        fprintf(stderr, "\nERROR!\nusage: %s input.db\n\n", argv[0]);
+        return 1;
+    }
+    // Get the input SQLite '.db' file containing the geometry
+    std::string line;
+    std::string fileName;
+    fileName = argv[1];
+    std::cout << "Using this SQLite '.db' file:" << fileName << std::endl;
+
 
   // check if DB file exists. If not, return.
   // FIXME: TODO: this check should go in the 'GMDBManager' constructor.
-  std::ifstream infile(path.c_str());
+  std::ifstream infile(fileName.c_str());
     if ( ! infile.good() ) {
-      std::cout << "\n\tERROR!! A '" << path << "' file does not exist!! Please, check the path of the input file before running this program. Exiting...";
+      std::cout << "\n\tERROR!! A '" << fileName << "' file does not exist!! Please, check the path of the input file before running this program. Exiting...";
       exit(EXIT_FAILURE);
   }
   infile.close();
+  
+
+  // GET GEOMETRY FROM LOCAL DB
+
 
 
   // open the DB
-  GMDBManager* db = new GMDBManager(path);
+  GMDBManager* db = new GMDBManager(fileName);
   /* Open database */
   if (db->checkIsDBOpen()) {
     std::cout << "OK! Database is open!\n";
diff --git a/GeoModelExamples/HelloGeoReadNodeAction/CMakeLists.txt b/GeoModelExamples/HelloGeoReadNodeAction/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..68ce5cafcd820bc195654e8f1747a7969ed43ee3
--- /dev/null
+++ b/GeoModelExamples/HelloGeoReadNodeAction/CMakeLists.txt
@@ -0,0 +1,35 @@
+# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+
+################################################################################
+# Package: HelloGeoReadNodeAction
+# author: Riccardo Maria BIANCHI @ CERN - May, 2022
+################################################################################
+
+cmake_minimum_required(VERSION 3.1.0)
+
+#project(HelloGeoRead)
+
+# Compile with C++17
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS ON)
+
+# Find the needed dependencies, when building individually
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) 
+  find_package( GeoModelCore REQUIRED ) 
+  find_package( GeoModelIO REQUIRED )
+endif()
+
+# Find includes in current dir
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+# Populate a CMake variable with the sources
+FILE(GLOB SRCS *.cxx)
+FILE(GLOB HEADERS *.h)
+
+
+# Tell CMake to create the helloworld executable
+add_executable( hellogeoReadNodeAction ${HEADERS} ${SRCS} )
+
+# Link all needed libraries
+target_link_libraries( hellogeoReadNodeAction GeoModelIO::GeoModelRead GeoModelCore::GeoModelKernel)
diff --git a/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.cxx b/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7852fe2c352a5688b491458e98fc6d026db28e16
--- /dev/null
+++ b/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.cxx
@@ -0,0 +1,115 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeoInventoryGraphAction.h"
+
+GeoInventoryGraphAction::GeoInventoryGraphAction (std::ostream &o)
+  : m_nameTag(nullptr)
+  , m_serialDenominator(nullptr)
+  , m_idTag(nullptr)
+  , m_transformState(true)
+  , m_volumeState(true)
+  , m_nametagState(true)
+  , m_serialDenominatorState(true)
+  , m_serialTransformerState(true)
+  , m_identifierState(true)
+  , m_o(o)
+  , m_indented(false)
+{
+}
+
+GeoInventoryGraphAction::~GeoInventoryGraphAction()
+{
+}
+
+void GeoInventoryGraphAction::handleTransform (const GeoTransform *xform)
+{
+  m_pendingTransformList.push_back(xform);
+  if (m_transformState) {
+    indent();
+    m_o << "XF(" << xform << ")";
+  }
+}
+
+void GeoInventoryGraphAction::handlePhysVol (const GeoPhysVol *vol)
+{
+  if (m_volumeState) {
+    indent();
+    m_o << "PV(" << vol << "),LV(" << vol->getLogVol()<< "),lvname=" << vol->getLogVol()->getName() << std::endl;
+  }
+  m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end());
+  m_indented=false;
+}
+
+void GeoInventoryGraphAction::handleFullPhysVol (const GeoFullPhysVol *vol)
+{
+  if (m_volumeState) {
+    indent();
+    m_o << "FPV(" << vol << "),LV(" << vol->getLogVol()<< "),lvname=" << vol->getLogVol()->getName() << std::endl;
+  }
+  m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end());
+  m_indented=false;
+}
+
+void GeoInventoryGraphAction::handleNameTag (const GeoNameTag *nameTag)
+{
+  if (m_nametagState) {
+    indent();
+    m_o << "NT("<<nameTag <<")" << nameTag->getName() << "+";
+  }
+}
+
+void GeoInventoryGraphAction::handleSerialDenominator (const GeoSerialDenominator *sD)
+{
+  if (m_nametagState) {
+    indent();
+    m_o << "SD("<< sD <<")" << sD->getBaseName() << "+";
+  }
+}
+
+void GeoInventoryGraphAction::handleSerialTransformer (const GeoSerialTransformer  *sT)
+{
+  if (m_volumeState) {
+    indent();
+    m_o << sT->getNCopies() << " PARAMETERIZED VOLUMES(" << sT->getVolume()->getLogVol()->getName() << ")" << std::endl;
+  }
+  m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end());
+  m_indented=false;
+}
+
+void GeoInventoryGraphAction::handleIdentifierTag (const GeoIdentifierTag *idTag)
+{
+  if (m_identifierState) {
+    indent();
+    m_o << "ID(" << idTag <<")" << idTag->getIdentifier() << "+";
+  }
+}
+
+void GeoInventoryGraphAction::setNotification (Type type, bool state)
+{
+  if (type==TRANSFORM) {
+    m_transformState=state;
+  }
+  else if (type==VOLUME) {
+    m_volumeState=state; 
+  }
+  else if (type==NAMETAG) {
+    m_nametagState=state;
+  }
+  else if (type==IDENTIFIERTAG) {
+    m_identifierState=state;
+  }
+}
+
+void GeoInventoryGraphAction::indent ()
+{
+  if (!m_indented) {
+    m_indented=true;
+    for (size_t i=0;i<getPath()->getLength(); i++) {
+      m_o << "   ";
+    }
+  }
+}
+
+
diff --git a/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.h b/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.h
new file mode 100644
index 0000000000000000000000000000000000000000..e960fdce279ca7ba9fbe8dce92ccc37a5c8bb876
--- /dev/null
+++ b/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.h
@@ -0,0 +1,102 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GEOMODELKERNEL_GEOPRINTGRAPHACTION_H
+#define GEOMODELKERNEL_GEOPRINTGRAPHACTION_H
+
+/**
+ * @class GeoInventoryGraphAction
+ * 
+ * @brief This action prints the node tree.  It can be configured
+ * to print a message on the following types of nodes:
+ *      * Transforms
+ *      * Physical Volumes and Full Physical Volumes
+ *      * SerialDenominators
+ *      * SerialTransforms 
+ *      * IdentifierTag
+ */
+
+#include "GeoModelKernel/GeoNodeAction.h"
+#include <iostream>
+
+class GeoInventoryGraphAction : public GeoNodeAction
+{
+  enum Type { TRANSFORM,
+	      VOLUME,
+	      NAMETAG,
+	      IDENTIFIERTAG};
+ public:
+  GeoInventoryGraphAction (std::ostream &o);
+  virtual ~GeoInventoryGraphAction();
+
+  //	Handles a Transform.
+  virtual void handleTransform (const GeoTransform *xform);
+  
+  //	Handles a physical volume.
+  virtual void handlePhysVol (const GeoPhysVol *vol);
+  
+  //	Handles a physical volume.
+  virtual void handleFullPhysVol (const GeoFullPhysVol *vol);
+  
+  //	Handles a Name Tag.
+  virtual void handleNameTag (const GeoNameTag *nameTag);
+  
+  //	Handles a Serial Denominator.
+  virtual void handleSerialDenominator (const GeoSerialDenominator *sD);
+  
+  //	Handles a Serial Transformer
+  virtual void handleSerialTransformer (const GeoSerialTransformer  *sT);
+  
+  //	Handles an Identifier Tag.
+  virtual void handleIdentifierTag (const GeoIdentifierTag *idTag);
+  
+  //	Sets the notification state.  Default: everything on.
+  void setNotification (Type type, bool state);
+  
+ private:
+  GeoInventoryGraphAction(const GeoInventoryGraphAction &right);
+  GeoInventoryGraphAction & operator=(const GeoInventoryGraphAction &right);
+  
+  //	Indent the print.
+  void indent ();
+  
+  //	A pointer to a name tag.  If the volume is named.
+  const GeoNameTag *m_nameTag;
+
+  //	A pointer to a serial denominator.  If one exists.
+  const GeoSerialDenominator *m_serialDenominator;
+
+  //	A pointer to an identifier tag.  If the volume is
+  //	identified.
+  const GeoIdentifierTag *m_idTag;
+
+  //	List of Pending Transformations.
+  std::vector<const GeoTransform *>  m_pendingTransformList;
+
+  //	On/off flag for transforms.
+  bool m_transformState;
+
+  //	On/off flag for physical volumes.
+  bool m_volumeState;
+
+  //	On/off flag for name tags.
+  bool m_nametagState;
+
+  //	On/off flag for serial denominators.
+  bool m_serialDenominatorState;
+  
+  //	On/off flag for serial transformers.
+  bool m_serialTransformerState;
+
+  //	On/off flag for identifier tags.
+  bool m_identifierState;
+
+  std::ostream &m_o;
+
+  //	Flag for indent (intially 0)
+  mutable bool m_indented;
+};
+
+
+#endif
diff --git a/GeoModelExamples/HelloGeoReadNodeAction/README.md b/GeoModelExamples/HelloGeoReadNodeAction/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8bfbbf64e13d6c6c767c9eb9193ec744f5ff8e7e
--- /dev/null
+++ b/GeoModelExamples/HelloGeoReadNodeAction/README.md
@@ -0,0 +1,82 @@
+# The 'helloGeoRead' GeoModel example
+
+The `helloGeoRead` example shows you how to read persistified GeoModel data in a standalone program.
+
+The example program:
+
+ 1. loads the geometry from the `.db` file
+ 2. prints all GeoMaterial entries found in the `.db`
+ 3. builds the GeoModel tree, storing it in memory
+ 4. gets the RootVolume of the GeoModel tree and it prints out the number of its children
+ 5. loops over all the RootVolume's children volumes (GeoPhysVol and GeoFullPhysVol instances), printing the name of the GeoLogVol associated to them
+
+ The example program uses many of the GeoModel packages.
+
+
+## Dependencies
+
+### Install Qt5
+
+To build and run GeoModel libraries, you must have a working Qt5 installation on your computer.
+If you are not sure how to install it, please take a look at the Appendix on Qt5, below.
+
+### Build GeoModelCore
+
+```bash
+git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git
+mkdir build_gmcore
+cd build_gmcore
+cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore
+make -j 4
+make install
+```
+
+### Build GeoModelIO
+
+```bash
+git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelIO.git
+mkdir build_gmio
+cd build_gmio
+cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelIO
+make -j 4
+make install
+```
+
+## Build
+
+From your work folder:
+
+```bash
+git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git
+mkdir build_hellogeoRead
+cd build_hellogeoRead
+cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelExamples/HelloGeoRead
+make -j4
+make install
+```
+
+## Run
+
+Get sample geometry data to play with:
+
+```bash
+wget https://atlas-vp1.web.cern.ch/atlas-vp1/doc_new/sample_datafiles/geometry/geometry-ATLAS-R2-2015-03-01-00.db
+ln -s $PWD/geometry-ATLAS-R2-2015-03-01-00.db ../geometry.db
+```
+
+Now, you can run the example by typing:
+
+```bash
+./hellogeoRead
+```
+
+
+ ----
+
+## Appendix
+
+### Notes on Qt5
+
+To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging.
+
+If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md).
diff --git a/GeoModelExamples/HelloGeoReadNodeAction/main.cxx b/GeoModelExamples/HelloGeoReadNodeAction/main.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0107074b3c99c1ba1307d02b45a43cc8d141a0db
--- /dev/null
+++ b/GeoModelExamples/HelloGeoReadNodeAction/main.cxx
@@ -0,0 +1,191 @@
+// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+
+/*
+ * HelloGeo.cpp
+ *
+ *  Author:     Riccardo Maria BIANCHI @ CERN
+ *  Created on: May, 2022
+ *
+ */
+
+// local includes
+#include "GeoInventoryGraphAction.h"
+
+// GeoModel includes
+#include "GeoModelDBManager/GMDBManager.h"
+#include "GeoModelRead/ReadGeoModel.h"
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoFullPhysVol.h"
+#include "GeoModelKernel/GeoNameTag.h"
+
+// C++ includes
+#include <iostream>
+#include <fstream>
+#include <cstdlib> // EXIT_FAILURE
+
+
+// Units
+#include "GeoModelKernel/Units.h"
+#define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm'
+
+
+GeoPhysVol* createTheWorld(GeoPhysVol* world)
+{
+  if (world == nullptr)
+  {
+  	//-----------------------------------------------------------------------------------//
+    // Define the materials that we shall use.                                              //
+    // ----------------------------------------------------------------------------------//
+
+    // Define the units
+    #define gr   SYSTEM_OF_UNITS::gram
+    #define mole SYSTEM_OF_UNITS::mole
+    #define cm3  SYSTEM_OF_UNITS::cm3
+
+    // Define the chemical elements
+    GeoElement*  Nitrogen = new GeoElement ("Nitrogen" ,"N"  ,  7.0 ,  14.0067 *gr/mole);
+    GeoElement*  Oxygen   = new GeoElement ("Oxygen"   ,"O"  ,  8.0 ,  15.9995 *gr/mole);
+    GeoElement*  Argon    = new GeoElement ("Argon"    ,"Ar" , 18.0 ,  39.948  *gr/mole);
+    GeoElement*  Hydrogen = new GeoElement ("Hydrogen" ,"H"  ,  1.0 ,  1.00797 *gr/mole);
+
+    // Define the materials
+    double densityOfAir=0.001214 *gr/cm3;
+    GeoMaterial *air = new GeoMaterial("Air", densityOfAir);
+    air->add(Nitrogen  , 0.7494);
+    air->add(Oxygen, 0.2369);
+    air->add(Argon, 0.0129);
+    air->add(Hydrogen, 0.0008);
+    air->lock();
+
+  	const GeoBox* worldBox = new GeoBox(1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm);
+  	const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air);
+  	world = new GeoPhysVol(worldLog);
+  }
+  return world;
+}
+
+
+
+int main(int argc, char *argv[])
+{
+
+    if(argc != 2)
+    {
+        fprintf(stderr, "\nERROR!\nusage: %s input.db\n\n", argv[0]);
+        return 1;
+    }
+    // Get the input SQLite '.db' file containing the geometry
+    std::string line;
+    std::string fileName;
+    fileName = argv[1];
+    std::cout << "Using this SQLite '.db' file:" << fileName << std::endl;
+
+
+  // check if DB file exists. If not, return.
+  // FIXME: TODO: this check should go in the 'GMDBManager' constructor.
+  std::ifstream infile(fileName.c_str());
+    if ( ! infile.good() ) {
+      std::cout << "\n\tERROR!! A '" << fileName << "' file does not exist!! Please, check the path of the input file before running this program. Exiting...";
+      exit(EXIT_FAILURE);
+  }
+  infile.close();
+  
+
+  // GET GEOMETRY FROM LOCAL DB
+
+
+
+  // open the DB
+  GMDBManager* db = new GMDBManager(fileName);
+  /* Open database */
+  if (db->checkIsDBOpen()) {
+    std::cout << "OK! Database is open!\n";
+  }
+  else {
+    std::cout << "Database is not open!\n";
+    // return;
+    throw;
+  }
+
+  // -- testing the input database
+//  std::cout << "Printing the list of all GeoMaterial nodes" << std::endl;
+//  db->printAllMaterials();
+//  std::cout << "Printing the list of all GeoElement nodes" << std::endl;
+//  db->printAllElements();
+
+  /* setup the GeoModel reader */
+  GeoModelIO::ReadGeoModel geoReader = GeoModelIO::ReadGeoModel(db);
+  std::cout << "OK! ReadGeoModel is set." << std::endl;
+
+
+  /* build the GeoModel geometry */
+  GeoPhysVol* dbPhys = geoReader.buildGeoModel(); // builds the whole GeoModel tree in memory
+  std::cout << "ReadGeoModel::buildGeoModel() done." << std::endl;
+
+  std::cout << "Reading records from the imported geometry DB file..." << std::endl;
+  geoReader.printDBTable("SerialIdentifiers");
+  geoReader.printDBTable("IdentifierTags");
+
+
+  // create the world volume container and
+  // get the 'world' volume, i.e. the root volume of the GeoModel tree
+  std::cout << "Getting the 'world' GeoPhysVol, i.e. the root volume of the GeoModel tree" << std::endl;
+  GeoPhysVol* world = createTheWorld(dbPhys);
+  std::cout << "Getting the GeoLogVol used by the 'world' volume" << std::endl;
+  const GeoLogVol* logVol = world->getLogVol();
+  std::cout << "'world' GeoLogVol name: " << logVol->getName() << std::endl;
+  std::cout << "'world' GeoMaterial name: " << logVol->getMaterial()->getName() << std::endl;
+
+
+  // --- testing the imported Geometry
+
+  // get number of children volumes
+  unsigned int nChil = world->getNChildVols();
+  std:: cout << "'world' number of children: " << nChil << std::endl;
+
+  // loop over all children nodes
+  std::cout << "Looping over all 'volume' children (i.e., GeoPhysVol and GeoFullPhysVol)..." << std::endl;
+  for (unsigned int idx=0; idx<nChil; ++idx) {
+	  PVConstLink nodeLink = world->getChildVol(idx);
+
+	  if ( dynamic_cast<const GeoVPhysVol*>( &(*( nodeLink ))) ) {
+
+		  std::cout << "\t" << "the child n. " << idx << " ";
+		  const GeoVPhysVol *childVolV = &(*( nodeLink ));
+
+		  if ( dynamic_cast<const GeoPhysVol*>(childVolV) ) {
+			  const GeoPhysVol* childVol = dynamic_cast<const GeoPhysVol*>(childVolV);
+			  std::cout << "is a GeoPhysVol, whose GeoLogVol name is: " << childVol->getLogVol()->getName();
+			  std::cout<< " and it has  "<<childVol->getNChildVols()<<" child volumes" << std::endl;
+		  }
+		  else if ( dynamic_cast<const GeoFullPhysVol*>(childVolV) ) {
+			  const GeoFullPhysVol* childVol = dynamic_cast<const GeoFullPhysVol*>(childVolV);
+			  std::cout << "is a GeoFullPhysVol, whose GeoLogVol name is: " << childVol->getLogVol()->getName();
+			  std::cout<< " and it has  "<<childVol->getNChildVols()<<" child volumes" << std::endl;
+		  }
+	  }
+	  else if ( dynamic_cast<const GeoNameTag*>( &(*( nodeLink ))) ) {
+		  std::cout << "\t" << "the child n. " << idx << " is a GeoNameTag" << std::endl;
+		  const GeoNameTag *childVol = dynamic_cast<const GeoNameTag*>(&(*( nodeLink )));
+		  std::cout << "\t\t GeoNameTag's name: " << childVol->getName() << std::endl;
+	  }
+	  else if ( dynamic_cast<const GeoMaterial*>( &(*( nodeLink ))) ) {
+		  std::cout << "\t" << "the child n. " << idx << " is a GeoMaterial" << std::endl;
+		  const GeoMaterial *childVol = dynamic_cast<const GeoMaterial*>(&(*( nodeLink )));
+		  std::cout << "\t\t GeoMaterial's name: " << childVol->getName() << std::endl;
+		  std::cout << "\t\t GeoMaterial's number of elements: " << childVol->getNumElements() << std::endl;
+	  }
+  }
+
+
+  GeoInventoryGraphAction action(std::cout);
+  world->exec(&action);
+
+
+
+  std::cout << "Everything done." << std::endl;
+
+  // return app.exec();
+  return 0;
+}
diff --git a/GeoModelExamples/HelloGeoWriteReadWrite/CMakeLists.txt b/GeoModelExamples/HelloGeoWriteReadWrite/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c10f7fc3e210175d4862acbbab7818af720fa268
--- /dev/null
+++ b/GeoModelExamples/HelloGeoWriteReadWrite/CMakeLists.txt
@@ -0,0 +1,32 @@
+# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+
+################################################################################
+# Package: HelloGeoWriteReadWrite
+# author: Riccardo Maria BIANCHI @ CERN - May, 2022
+################################################################################
+
+cmake_minimum_required(VERSION 3.1.0)
+
+#project(HelloGeoWrite)
+
+# Compile with C++17
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS ON)
+
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # when building individually
+  find_package( GeoModelCore REQUIRED ) 
+  find_package( GeoModelIO REQUIRED ) 
+endif()
+
+# Find includes in current dir
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+# Populate a CMake variable with the sources
+set(SRCS main.cpp )
+
+# Tell CMake to create the helloworld executable
+add_executable( hellogeoWriteReadWrite ${SRCS} )
+
+# Link all needed libraries
+target_link_libraries( hellogeoWriteReadWrite GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite GeoModelIO::GeoModelRead)
diff --git a/GeoModelExamples/HelloGeoWriteReadWrite/README.md b/GeoModelExamples/HelloGeoWriteReadWrite/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f9d98f364d3ae07f54458cb6e3312559e0467d33
--- /dev/null
+++ b/GeoModelExamples/HelloGeoWriteReadWrite/README.md
@@ -0,0 +1,74 @@
+# The 'helloGeoWrite' GeoModel example
+
+The `helloGeoWrite` example shows you how to create a simple geometry, by using GeoModel nodes.
+
+The example program:
+
+ 1. Builds an example geometry:
+ 2. Writes the geometry to an SQLite file
+ 3. It accesses the persistent copy of the geometry, as a test
+
+
+## Dependencies
+
+### Install Qt5
+
+To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer.
+If you are not sure how to install it, please take a look at the Appendix, below.
+
+
+#### GeoModelCore
+
+```bash
+git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git
+mkdir build_gmcore
+cd build_gmcore
+cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore
+make -j 4
+make install
+cd ..
+```
+
+#### GeoModelIO
+
+```bash
+git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelIO.git
+mkdir build_gmio
+cd build_gmio
+cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelIO
+make -j 4
+make install
+```
+
+
+
+## Build
+
+From your work folder:
+
+```bash
+git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git
+mkdir build_hellogeo
+cd build_hellogeo
+cmake -DCMAKE_INSTALL_PREFIX=../install ../GeoModelExamples/HelloGeoWrite/
+make -j4
+```
+
+## Run
+
+Now, you can **run the example** by typing:
+
+```bash
+./hellogeoWrite
+```
+
+
+----
+
+## Appendix
+
+### Notes on Qt5
+
+To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging.
+
+If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md).
diff --git a/GeoModelExamples/HelloGeoWriteReadWrite/main.cpp b/GeoModelExamples/HelloGeoWriteReadWrite/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8e2051a5fb1cf9a4473aa365a94f99238607bfa4
--- /dev/null
+++ b/GeoModelExamples/HelloGeoWriteReadWrite/main.cpp
@@ -0,0 +1,233 @@
+// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+
+/*
+ * This example writes a sample geometry, reads it back in, then writes it again.
+ * It is meant to test the GeoModel I/O packages and methods.
+ *
+ *  Author:     Riccardo Maria BIANCHI @ CERN
+ *  Created on: May, 2022
+ *
+ */
+
+// GeoModel includes
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoTube.h"
+#include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoFullPhysVol.h"
+#include "GeoModelKernel/GeoNameTag.h"
+#include "GeoModelDBManager/GMDBManager.h"
+#include "GeoModelWrite/WriteGeoModel.h"
+#include "GeoModelRead/ReadGeoModel.h"
+
+// C++ includes
+#include <iostream>
+#include <fstream>
+#include <cstdlib> // EXIT_FAILURE
+
+
+// Units
+#include "GeoModelKernel/Units.h"
+#define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm'
+
+
+int main(int argc, char *argv[])
+{
+  //-----------------------------------------------------------------------------------//
+	// Define the materials that we shall use.                                              //
+	// ----------------------------------------------------------------------------------//
+
+	// Define the units
+	#define gr   SYSTEM_OF_UNITS::gram
+	#define mole SYSTEM_OF_UNITS::mole
+	#define cm3  SYSTEM_OF_UNITS::cm3
+
+	// Define the chemical elements
+	GeoElement*  Nitrogen = new GeoElement ("Nitrogen" ,"N"  ,  7.0 ,  14.0067 *gr/mole);
+	GeoElement*  Oxygen   = new GeoElement ("Oxygen"   ,"O"  ,  8.0 ,  15.9995 *gr/mole);
+	GeoElement*  Argon    = new GeoElement ("Argon"    ,"Ar" , 18.0 ,  39.948  *gr/mole);
+	GeoElement*  Hydrogen = new GeoElement ("Hydrogen" ,"H"  ,  1.0 ,  1.00797 *gr/mole);
+	GeoElement*  Iron     = new GeoElement ("Iron"     ,"Fe" , 26.0 ,  55.847  *gr/mole);
+	GeoElement*  Carbon   = new GeoElement ("Carbon"   ,"C"  ,  6.0 ,  12.0107 *gr/mole);
+	GeoElement*  Sillicon = new GeoElement ("Silicon"  ,"Si" , 14.0 ,  28.085  *gr/mole);
+
+	// Define the materials
+
+	double densityOfAir=0.001214 *gr/cm3;
+	GeoMaterial *air = new GeoMaterial("Air", densityOfAir);
+	air->add(Nitrogen  , 0.7494);
+	air->add(Oxygen, 0.2369);
+	air->add(Argon, 0.0129);
+	air->add(Hydrogen, 0.0008);
+	air->lock();
+
+
+  //-----------------------------------------------------------------------------------//
+  // create the world volume container and
+  // get the 'world' volume, i.e. the root volume of the GeoModel tree
+  std::cout << "Creating the 'world' volume, i.e. the root volume of the GeoModel tree..." << std::endl;
+  const GeoBox* worldBox = new GeoBox(1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm);
+  const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air);
+  GeoPhysVol* world = new GeoPhysVol(worldLog);
+
+
+	  const double degree=M_PI/180.0;
+
+  // Define elements used in this example:
+  GeoElement  *aluminium     = new GeoElement("Aluminium", "Al", 13,  26 * gr/mole );
+
+  // Define materials:
+  // Define Aluminium
+  double densityOfAluminium=2.7;                  // g/cm^3
+  GeoMaterial *Aluminium     = new GeoMaterial("Aluminium", densityOfAluminium);
+  Aluminium->add(aluminium,1.0);
+  Aluminium->lock();
+
+  // Some dimensions used below:
+  double platformHeight=34.5;                             // Height to the top of the flanges
+  //double flangeDiameter=3.375;                            // Diameter of the flanges
+  double flangeThickness=3.0/16.0;                        // Thickness of the flanges
+  double t1TubeLength = platformHeight-flangeThickness;   // Overall length of tube t1;
+  double innerRadius=0.75/2.0;                            // 3/4 inch (inner diameter) pipe
+  double outerRadius=(17.0/16.0)/2.0;                     // 1-1/16   (outer diameter) 
+  double leftRightLegSeparation=61.0+11.0/16.0;           // Distance between legs, in x. 
+  double frontBackLegSeparation=19.0+3.0/4.0;             // Distance between legs, in y.
+  //const double barWidth1=4.0;                             // Width of front-back primary support
+  //const double barWidth2=3.0;                             // Width of secondary aluminium support
+  //double barThickness   =1.25;                            // Thickness of Aluminium bars
+  //double cutoutDepth    = 21.5;                           // Depth of the cutout hole
+  //double cutoutWidth    = 32.375;                         // Width of the cutout hole
+
+  // Add the four legs of the kitchen sink:
+  {
+    const GeoTube      *t1Tube    = new GeoTube(innerRadius,outerRadius, t1TubeLength/2.0);
+    const GeoLogVol    *t1Log     = new  GeoLogVol("T1Log", t1Tube, Aluminium);
+    const GeoLogVol    *t2Log     = new  GeoLogVol("T2Log", t1Tube, Aluminium);
+    GeoPhysVol         *t1Phys    = new GeoPhysVol(t1Log);
+    GeoPhysVol         *t2Phys    = new GeoPhysVol(t2Log);
+    //GeoPhysVol         *t3Phys    = new GeoPhysVol(t1Log);
+    GeoTransform  *xform1         = new GeoTransform(GeoTrf::Translate3D(leftRightLegSeparation/2.0, frontBackLegSeparation/2.0, 0));
+    GeoTransform  *xform2         = new GeoTransform(GeoTrf::Translate3D(leftRightLegSeparation/2.0, -frontBackLegSeparation/2.0, 0));
+    GeoTransform  *xform3         = new GeoTransform(GeoTrf::Translate3D(-leftRightLegSeparation/2.0, -frontBackLegSeparation/2.0, 0));
+    //GeoTransform  *xform4         = new GeoTransform(GeoTrf::Translate3D(-leftRightLegSeparation/2.0, frontBackLegSeparation/2.0, 0));
+    world->add(xform1);
+    
+    world->add(t1Phys);
+    
+    world->add(xform2);
+    world->add(t2Phys);
+    
+    world->add(xform3); 
+    world->add(t2Phys);
+    world->add(t2Phys);
+    world->add(t2Phys);
+  }
+
+
+
+
+
+
+	//------------------------------------------------------------------------------------//
+	// 1 -- Writing the geometry to file
+	//------------------------------------------------------------------------------------//
+  std::string path = "geometry_1.db";
+
+	// check if DB file exists. If not, return.
+  // FIXME: TODO: this check should go in the 'GMDBManager' constructor.
+  std::ifstream infile(path.c_str());
+    if ( infile.good() ) {
+      std::cout << "\n\tERROR!! A '" << path << "' file exists already!! Please, remove, move, or rename it before running this program. Exiting...";
+        exit(EXIT_FAILURE);
+  }
+  infile.close();
+
+	// open the DB connection
+  GMDBManager db(path);
+
+  // check the DB connection
+  if (db.checkIsDBOpen()) {
+    std::cout << "OK! Database is open!" << std::endl;
+  } else {
+    std::cout << "Database ERROR!! Exiting..." << std::endl;
+    exit(EXIT_FAILURE);
+  }
+
+  // Dump the tree volumes to a local file
+	std::cout << "Dumping the GeoModel geometry to the DB file..." << std::endl;
+  GeoModelIO::WriteGeoModel dumpGeoModelGraph(db); // init the GeoModel node action
+  world->exec(&dumpGeoModelGraph); // visit all GeoModel nodes
+  dumpGeoModelGraph.saveToDB(); // save to the SQlite DB file
+  std::cout << "DONE. Geometry saved." <<std::endl;
+
+
+
+  //std::cout << "\nTest - list of all the GeoMaterial nodes in the persistified geometry:" << std::endl;
+  //db.printAllMaterials();
+  //std::cout << "\nTest - list of all the GeoElement nodes in the persistified geometry:" << std::endl;
+  //db.printAllElements();
+
+	//------------------------------------------------------------------------------------//
+	// 2 -- Reading back the geometry from file
+	//------------------------------------------------------------------------------------//
+
+  std::ifstream infile2(path.c_str());
+    if ( ! infile2.good() ) {
+      std::cout << "\n\tERROR!! A '" << path << "' file does not exist!! Please, check the path of the input file before running this program. Exiting...";
+      exit(EXIT_FAILURE);
+  }
+  infile2.close();
+  // open the DB
+  GMDBManager* db2 = new GMDBManager(path);
+  /* Open database */
+  if (db2->checkIsDBOpen()) {
+    std::cout << "OK! Database is open!\n";
+  }
+  else {
+    std::cout << "Database is not open!\n";
+    // return;
+    throw;
+  }
+  /* setup the GeoModel reader */
+  GeoModelIO::ReadGeoModel geoReader = GeoModelIO::ReadGeoModel(db2);
+  std::cout << "OK! ReadGeoModel is set." << std::endl;
+  /* build the GeoModel geometry */
+  GeoPhysVol* dbPhys = geoReader.buildGeoModel(); // builds the whole GeoModel tree in memory
+  std::cout << "ReadGeoModel::buildGeoModel() done." << std::endl;
+
+
+	//------------------------------------------------------------------------------------//
+	// 3 -- Writing the geometry to file
+	//------------------------------------------------------------------------------------//
+  path = "geometry_2.db";
+
+	// check if DB file exists. If not, return.
+  // FIXME: TODO: this check should go in the 'GMDBManager' constructor.
+  std::ifstream infile3(path.c_str());
+    if ( infile3.good() ) {
+      std::cout << "\n\tERROR!! A '" << path << "' file exists already!! Please, remove, move, or rename it before running this program. Exiting...";
+        exit(EXIT_FAILURE);
+  }
+  infile3.close();
+
+	// open the DB connection
+  GMDBManager db3(path);
+
+  // check the DB connection
+  if (db.checkIsDBOpen()) {
+    std::cout << "OK! Database is open!" << std::endl;
+  } else {
+    std::cout << "Database ERROR!! Exiting..." << std::endl;
+    exit(EXIT_FAILURE);
+  }
+
+  // Dump the tree volumes to a local file
+	std::cout << "Dumping the GeoModel geometry to the DB file..." << std::endl;
+  GeoModelIO::WriteGeoModel dumpGeoModelGraph3(db3); // init the GeoModel node action
+  //world->exec(&dumpGeoModelGraph3); // visit all GeoModel nodes
+  dbPhys->exec(&dumpGeoModelGraph3); // visit all GeoModel nodes
+  dumpGeoModelGraph3.saveToDB(); // save to the SQlite DB file
+  std::cout << "DONE. Geometry saved." <<std::endl;
+
+
+  return 0;
+}
diff --git a/GeoModelExamples/MinimalPlugin/CMakeLists.txt b/GeoModelExamples/MinimalPlugin/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3b35d67b5339ae27a73cec14021d1fe0f8044987
--- /dev/null
+++ b/GeoModelExamples/MinimalPlugin/CMakeLists.txt
@@ -0,0 +1,47 @@
+# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+
+################################################################################
+# Package: MinimalPlugin
+# author: Riccardo Maria BIANCHI @ CERN - May, 2022
+################################################################################
+
+cmake_minimum_required(VERSION 3.1.0)
+
+# Compile with C++17
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS ON)
+
+
+# Find the needed dependencies, when building individually
+  message (${CMAKE_SOURCE_DIR}) 
+  message (${PROJECT_SOURCE_DIR})
+  
+if ( CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR ) # when buildingindividually
+   find_package( GeoModelCore REQUIRED  ) 
+endif()
+
+
+# Find the header and source files.
+file( GLOB SOURCES src/*.cxx )
+
+add_library( MinimalPlugin SHARED ${SOURCES} )
+target_link_libraries( MinimalPlugin PUBLIC GeoModelCore::GeoModelKernel)
+
+target_include_directories( MinimalPlugin PUBLIC
+   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+   $<INSTALL_INTERFACE:include> )
+
+source_group( "src" FILES ${SOURCES} )
+
+set_target_properties( MinimalPlugin PROPERTIES
+   VERSION ${PROJECT_VERSION}
+   SOVERSION ${PROJECT_VERSION_MAJOR} )
+
+# Install the library.
+install( TARGETS MinimalPlugin
+   EXPORT ${PROJECT_NAME}-export
+   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+   COMPONENT Runtime
+   NAMELINK_SKIP )
+
diff --git a/GeoModelExamples/MinimalPlugin/src/MinimalPlugin.cxx b/GeoModelExamples/MinimalPlugin/src/MinimalPlugin.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2bde380f4ea6b642bcecf1feb2ade1cbb32cee5d
--- /dev/null
+++ b/GeoModelExamples/MinimalPlugin/src/MinimalPlugin.cxx
@@ -0,0 +1,139 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+// -------------------------------------------------------------------
+//
+// Minimal Plugin
+// Riccardo Maria BIANCHI, 2022 May 6 
+//
+// This is an example plugin. It compiles to a shared library 
+// (with .so or .dylib extension) which can be viewed with gmex.
+// In this example there is no "envelope", all the components of
+// the minimal example geometry are placed into the world.  
+//
+// This example illustrates the use of:
+//
+//    --the plugin mechanism.
+//    --simple shapes, logical volumes, physical volumes
+//    --chemical elements and pure materials (aluminium)
+//
+// --------------------------------------------------------------------
+
+#include "GeoModelKernel/GeoVGeometryPlugin.h"
+#include "GeoModelKernel/GeoDefinitions.h"
+#include "GeoModelKernel/GeoMaterial.h"
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoTube.h"
+#include "GeoModelKernel/GeoLogVol.h"
+#include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoTransform.h"
+#include "GeoModelKernel/GeoShapeSubtraction.h"
+#include "GeoModelKernel/GeoShapeShift.h"
+
+// Class Declaration
+
+class MinimalPlugin : public GeoVGeometryPlugin  {
+
+ public:
+
+  // Constructor:
+  MinimalPlugin();
+
+  // Destructor:
+  ~MinimalPlugin();
+
+  // Creation of geometry:
+  virtual void create(GeoPhysVol *world, bool publish=false);
+
+ private:
+
+  // Illegal operations:
+  const MinimalPlugin & operator=(const MinimalPlugin &right)=delete;
+  MinimalPlugin(const MinimalPlugin &right) = delete;
+
+};
+
+
+// Class definition:
+
+// Constructor
+MinimalPlugin::MinimalPlugin()
+{
+}
+
+// Destructor
+MinimalPlugin::~MinimalPlugin()
+{
+}
+
+// The create algorithm creates a tree of physical volumes rooted under the
+// "world" physical volume. The optional flag publish is not used in this
+// example (normally one may "publish" a list of FullPhysVol's and Alignable
+// transforms, but this example has none such).
+//
+void MinimalPlugin::create(GeoPhysVol *world, bool /*publish*/)
+{
+  const double degree=M_PI/180.0;
+
+  // Define elements used in this example:
+  GeoElement  *aluminium     = new GeoElement("Aluminium", "Al", 13,  26 * GeoModelKernelUnits::g/GeoModelKernelUnits::mole);
+
+  // Define materials:
+  // Define Aluminium
+  double densityOfAluminium=2.7;                  // g/cm^3
+  GeoMaterial *Aluminium     = new GeoMaterial("Aluminium", densityOfAluminium);
+  Aluminium->add(aluminium,1.0);
+  Aluminium->lock();
+
+  // Some dimensions used below:
+  double platformHeight=34.5;                             // Height to the top of the flanges
+  //double flangeDiameter=3.375;                            // Diameter of the flanges
+  double flangeThickness=3.0/16.0;                        // Thickness of the flanges
+  double t1TubeLength = platformHeight-flangeThickness;   // Overall length of tube t1;
+  double innerRadius=0.75/2.0;                            // 3/4 inch (inner diameter) pipe
+  double outerRadius=(17.0/16.0)/2.0;                     // 1-1/16   (outer diameter) 
+  double leftRightLegSeparation=61.0+11.0/16.0;           // Distance between legs, in x. 
+  double frontBackLegSeparation=19.0+3.0/4.0;             // Distance between legs, in y.
+  //const double barWidth1=4.0;                             // Width of front-back primary support
+  //const double barWidth2=3.0;                             // Width of secondary aluminium support
+  //double barThickness   =1.25;                            // Thickness of Aluminium bars
+  //double cutoutDepth    = 21.5;                           // Depth of the cutout hole
+  //double cutoutWidth    = 32.375;                         // Width of the cutout hole
+
+  // Add the four legs of the kitchen sink:
+  {
+    const GeoTube      *t1Tube    = new GeoTube(innerRadius,outerRadius, t1TubeLength/2.0);
+    const GeoLogVol    *t1Log     = new  GeoLogVol("T1Log", t1Tube, Aluminium);
+    const GeoLogVol    *t2Log     = new  GeoLogVol("T2Log", t1Tube, Aluminium);
+    GeoPhysVol         *t1Phys    = new GeoPhysVol(t1Log);
+    GeoPhysVol         *t2Phys    = new GeoPhysVol(t2Log);
+    //GeoPhysVol         *t3Phys    = new GeoPhysVol(t1Log);
+    GeoTransform  *xform1         = new GeoTransform(GeoTrf::Translate3D(leftRightLegSeparation/2.0, frontBackLegSeparation/2.0, 0));
+    GeoTransform  *xform2         = new GeoTransform(GeoTrf::Translate3D(leftRightLegSeparation/2.0, -frontBackLegSeparation/2.0, 0));
+    GeoTransform  *xform3         = new GeoTransform(GeoTrf::Translate3D(-leftRightLegSeparation/2.0, -frontBackLegSeparation/2.0, 0));
+    //GeoTransform  *xform4         = new GeoTransform(GeoTrf::Translate3D(-leftRightLegSeparation/2.0, frontBackLegSeparation/2.0, 0));
+    world->add(xform1);
+    
+    world->add(t1Phys);
+    
+    world->add(xform2);
+    world->add(t2Phys);
+    
+    world->add(xform3); 
+    world->add(t2Phys);
+    world->add(t2Phys);
+    world->add(t2Phys);
+
+  }
+    
+  
+  //--------------------------------------//
+}
+
+// The name of this routine must correspond to the name of the class,
+// and also to the name of the source code file (this file)
+
+extern "C" MinimalPlugin *createMinimalPlugin() {
+  return new MinimalPlugin;
+}
diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
index e612722f23ad72e3c9ad6f99a76eb72e41e1d7d8..403138e1c1b59edeccd611b34bfdf076711c79c0 100644
--- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
+++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h
@@ -1,3 +1,8 @@
+
+/*
+  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+*/
+
 /*
  * ReadGeoModel.h
  *
@@ -9,6 +14,11 @@
  * - 2020 May, R.M.Bianchi - Added parallel read
  * - 2020 Aug, R.M.Bianchi - Added support for reading back published nodes
  * - 2021 Aug, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> - Added support GeoIdentifierTag and GeoSerialIdentifier nodes
+ * - Jun 2022, R.M.Bianchi <riccardo.maria.bianchi@cern.ch>
+ *              Fixed the duplication of VPhysVol instances due to a wrong key used for caching volumes that were built already 
+ *              The copyNumber was wrongly used together with tableID and volID
+ *              For details, see: https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39
+ *
  */
 
 #ifndef GeoModelRead_ReadGeoModel_H_
@@ -166,8 +176,10 @@ private:
   void storeBuiltAlignableTransform(GeoAlignableTransform* node);
   GeoAlignableTransform* getBuiltAlignableTransform(const unsigned int id);
 
-  void storeVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber, GeoGraphNode* node);
-  GeoGraphNode* getVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber);
+  //void storeVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber, GeoGraphNode* node);
+  //GeoGraphNode* getVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber);
+  void storeVPhysVol(const unsigned int id, const unsigned int tableId, GeoGraphNode* node);
+  GeoGraphNode* getVPhysVol(const unsigned int id, const unsigned int tableId);
 
   bool isBuiltLog(const unsigned int id);
   void storeBuiltLog(GeoLogVol* nodePtr);
diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp
index c62ef478f101911ea6766b1650c3ae8b8450f15b..9e6d1ec7013528725f036c5377537a6faadd4dac 100644
--- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp
+++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp
@@ -38,13 +38,9 @@ namespace GeoModelIO {
             std::string volID   = record[2];
             if(0==ii) keyType   = record[3];//this is the same for all records. TODO: it should be stored in a metadata table
             ++ii;
-            
-            //std::cout << "keyStr: " << keyStr << ", volID: " << volID 
-            //          << ", keyType: " << keyType << std::endl; // debug msg
-
             N volPtr = nullptr;
             if constexpr ( std::is_same_v<GeoFullPhysVol*, N> ) {
-                volPtr = dynamic_cast<GeoFullPhysVol*>( getVPhysVol(std::stoul(volID), 2, 1) ); //always table=2, copyN=1 (because FullPhysVols are not sharable 
+                volPtr = dynamic_cast<GeoFullPhysVol*>( getVPhysVol(std::stoul(volID), 2) ); //always table=2, and we should have copyN=1 because FullPhysVols are not sharable 
             } else if constexpr ( std::is_same_v<GeoAlignableTransform*, N> ) {
                 volPtr = getBuiltAlignableTransform(std::stoul(volID));
             } else {
diff --git a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
index b909a4f78528ba626e089a2c36fbab737d067ccf..768e4706a1a734dbd04bf1e6eb6368799f23c2c1 100644
--- a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
+++ b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp
@@ -15,6 +15,10 @@
  *  - May 2020, R.M.Bianchi
  *  - Aug 2020, R.M.Bianchi - Added support to read published FullPhysVols and AlignableTransforms back in
  *  - Aug 2021, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> - Added support for GeoSerialIdentifier and GeoIdentifierTag
+ *  - Jun 2022, R.M.Bianchi <riccardo.maria.bianchi@cern.ch>
+ *              Fixed the duplication of VPhysVol instances due to a wrong key used for caching volumes that were built already 
+ *              The copyNumber was wrongly used together with tableID and volID
+ *              For details, see: https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39
  */
 
 
@@ -325,7 +329,7 @@ GeoPhysVol* ReadGeoModel::buildGeoModelPrivate()
 
   if (m_debug || m_deepDebug) {
     muxCout.lock();
-    std::cout << "Thread " << std::this_thread::get_id() << " - processing " << nChildrenRecords << " keys..." << std::endl;
+    std::cout << "\nReadGeoModel::loopOverAllChildrenRecords -- Thread " << std::this_thread::get_id() << " - processing " << nChildrenRecords << " keys..." << std::endl;
     muxCout.unlock();
   }
 
@@ -664,6 +668,14 @@ void ReadGeoModel::loopOverAllChildrenInBunches()
 
   void ReadGeoModel::processParentChild(const std::vector<std::string> &parentchild)
   {
+      if (m_deepDebug) {
+          muxCout.lock();
+          std::cout << "\nReadGeoModel::processParentChild()..." << std::endl; 
+          for (auto& rec : parentchild) std::cout << rec << "-";
+          std::cout << std::endl;
+          muxCout.unlock();
+      }
+
     // safety check
     if (parentchild.size() < 8) {
       std::cout <<  "ERROR!!! Probably you are using an old geometry file. Please, get a new one. Exiting..." << std::endl;
@@ -687,7 +699,7 @@ void ReadGeoModel::loopOverAllChildrenInBunches()
     std::string childNodeType = m_tableID_toTableName[childTableId];
 
     if ( "" == childNodeType || 0 == childNodeType.size()) {
-      std::cout << "ERROR!!! childNodeType is empty!!! Aborting..." << std::endl;
+      std::cout << "ReadGeoModel -- ERROR!!! childNodeType is empty!!! Aborting..." << std::endl;
       exit(EXIT_FAILURE);
     }
 
@@ -695,6 +707,7 @@ void ReadGeoModel::loopOverAllChildrenInBunches()
 
     // build or get parent volume.
     // Using the parentCopyNumber here, to get a given instance of the parent volume
+    if (m_deepDebug) { muxCout.lock(); std::cout << "build/get parent volume...\n"; muxCout.unlock(); }
     parentVol = dynamic_cast<GeoVPhysVol*>( buildVPhysVolInstance(parentId, parentTableId, parentCopyN) );
     std::string parentName = parentVol->getLogVol()->getName();
 
@@ -723,6 +736,7 @@ void ReadGeoModel::loopOverAllChildrenInBunches()
 		volAddHelper(parentVol, childNode);
 	}
 	else if (childNodeType == "GeoTransform") {
+    if (m_deepDebug) { muxCout.lock(); std::cout << "get transform child...\n"; muxCout.unlock(); }
     GeoTransform* childNode = getBuiltTransform(childId);
 		volAddHelper(parentVol, childNode);
 	}
@@ -779,20 +793,24 @@ GeoVPhysVol* ReadGeoModel::buildVPhysVolInstance(const unsigned int id, const un
 {
 	if (m_deepDebug) {
     muxCout.lock();
-    std::cout << "ReadGeoModel::buildVPhysVolInstance() - " << id << ", " << tableId << ", " << copyN << std::endl;
+    std::cout << "ReadGeoModel::buildVPhysVolInstance() - id: " << id 
+              << ", tableId: " << tableId 
+              << ", copyN: " << copyN << std::endl;
     muxCout.unlock();
   }
 
-	// A - if the instance has been previously built, return that
-  if ( nullptr != getVPhysVol(id, tableId, copyN)) {
-//  if (isVPhysVolBuilt(id, tableId, copyN)) {
-		if (m_deepDebug) {
-      muxCout.lock();
-      std::cout << "getting the instance volume from memory..." << std::endl;
-      muxCout.unlock();
+    // A - if the instance has been previously built, return that
+    //if ( nullptr != getVPhysVol(id, tableId, copyN)) {
+    if ( nullptr != getVPhysVol(id, tableId)) {
+        if (m_deepDebug) {
+            muxCout.lock();
+            //std::cout << "getting the instance volume from memory... Returning: [" << getVPhysVol(id, tableId, copyN) << "] -- logvol: " << ((GeoVPhysVol*)getVPhysVol(id, tableId, copyN))->getLogVol()->getName() << std::endl;
+            std::cout << "getting the instance volume from memory... Returning: [" << getVPhysVol(id, tableId) << "] -- logvol: " << ((GeoVPhysVol*)getVPhysVol(id, tableId))->getLogVol()->getName() << std::endl;
+            muxCout.unlock();
+        }
+        //return dynamic_cast<GeoVPhysVol*>(getVPhysVol(id, tableId, copyN));
+        return dynamic_cast<GeoVPhysVol*>(getVPhysVol(id, tableId));
     }
-		return dynamic_cast<GeoVPhysVol*>(getVPhysVol(id, tableId, copyN));
-	}
 
   // B - if not built already, then get the actual volume,
   // which should be already built by now,
@@ -802,8 +820,14 @@ GeoVPhysVol* ReadGeoModel::buildVPhysVolInstance(const unsigned int id, const un
   GeoVPhysVol* vol = nullptr;
   bool volFound = true;
   if (1==tableId) {
-    if(isBuiltPhysVol(id))
+    if(isBuiltPhysVol(id)) {
       vol = new GeoPhysVol( getBuiltPhysVol(id)->getLogVol() );
+      if (m_deepDebug) {
+          muxCout.lock();
+          std::cout << "PhysVol not instanced yet, building the instance now [" << vol << "] -- logvol: " << vol->getLogVol()->getName() << std::endl;
+          muxCout.unlock();
+      }
+    }
     else
       volFound = false;
   }
@@ -817,7 +841,8 @@ GeoVPhysVol* ReadGeoModel::buildVPhysVolInstance(const unsigned int id, const un
     std::cout << "ERROR! VPhysVol not found! It should be already built, by now. Exiting...\n";
     exit(EXIT_FAILURE);
   }
-  storeVPhysVol(id, tableId, copyN, vol);
+  //storeVPhysVol(id, tableId, copyN, vol);
+  storeVPhysVol(id, tableId, vol);
 
 	return vol;
 }
@@ -862,6 +887,7 @@ GeoVPhysVol* ReadGeoModel::buildVPhysVol(const unsigned int id, const unsigned i
     std::cout << "ERROR!!! LogVol is NULL!" << std::endl;
 //    exit(EXIT_FAILURE);
   }
+    if (m_deepDebug) { muxCout.lock(); std::cout << "using the cached LogVol [" << logVol_ID << "] w/ address: " << logVol << "...\n"; ; muxCout.unlock(); }
 
 	// a pointer to the VPhysVol
 	GeoVPhysVol* vol = nullptr;
@@ -2533,7 +2559,10 @@ GeoBox* ReadGeoModel::buildDummyShape() {
 GeoLogVol* ReadGeoModel::buildLogVol(const unsigned int id)
 {
 
+    if (m_deepDebug) { muxCout.lock(); std::cout << "buildLogVol(), testing LogVol id: " << id << "...\n"; ; muxCout.unlock(); }
+
   if (isBuiltLog(id)) {
+    if (m_deepDebug) { muxCout.lock(); std::cout << "getting the LogVol from cache...\n"; ; muxCout.unlock(); }
     return getBuiltLog(id);
   }
 
@@ -2570,9 +2599,14 @@ GeoLogVol* ReadGeoModel::buildLogVol(const unsigned int id)
     exit(EXIT_FAILURE);
   }
 
-	GeoLogVol* logPtr = new GeoLogVol(logVolName, shape, mat);
+  GeoLogVol* logPtr = new GeoLogVol(logVolName, shape, mat);
   storeBuiltLog(logPtr);
-	return logPtr;
+  if (m_deepDebug) {
+      muxCout.lock();
+      std::cout << "buildLogVol() - address of the stored LogVol:" << logPtr << std::endl;
+      muxCout.unlock();
+  }	
+  return logPtr;
 }
 
 
@@ -2985,21 +3019,30 @@ GeoSerialTransformer* ReadGeoModel::getBuiltSerialTransformer(const unsigned int
 */
 
 // --- methods for caching GeoPhysVol/GeoFullPhysVol nodes ---
-std::string getVPhysVolKey(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber)
+//std::string getVPhysVolKey(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber)
+//{
+  //std::string key = std::to_string(id) + ":" + std::to_string(tableId) + ":" + std::to_string(copyNumber);
+  //return key;
+//}
+std::string getVPhysVolKey(const unsigned int id, const unsigned int tableId)
 {
-  std::string key = std::to_string(id) + ":" + std::to_string(tableId) + ":" + std::to_string(copyNumber);
+  std::string key = std::to_string(id) + ":" + std::to_string(tableId);
   return key;
 }
-void ReadGeoModel::storeVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyN, GeoGraphNode* nodePtr)
+//void ReadGeoModel::storeVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyN, GeoGraphNode* nodePtr)
+void ReadGeoModel::storeVPhysVol(const unsigned int id, const unsigned int tableId, GeoGraphNode* nodePtr)
 {
   std::lock_guard<std::mutex> lk(muxVPhysVol);
-  std::string key = getVPhysVolKey(id, tableId, copyN);
+  //std::string key = getVPhysVolKey(id, tableId, copyN);
+  std::string key = getVPhysVolKey(id, tableId);
   m_memMap[key] = nodePtr;
 }
-GeoGraphNode* ReadGeoModel::getVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyN)
+//GeoGraphNode* ReadGeoModel::getVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyN)
+GeoGraphNode* ReadGeoModel::getVPhysVol(const unsigned int id, const unsigned int tableId)
 {
-	std::lock_guard<std::mutex> lk(muxVPhysVol);
-  std::string key = getVPhysVolKey(id, tableId, copyN);
+    std::lock_guard<std::mutex> lk(muxVPhysVol);
+  //std::string key = getVPhysVolKey(id, tableId, copyN);
+  std::string key = getVPhysVolKey(id, tableId);
   if (m_memMap.find(key) == m_memMap.end()) {
     return nullptr; // if volume is not found in cache
   }
diff --git a/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp b/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp
index a35ede516272f13ba69a01ae835d421c83c55202..1341cce946b5b598222f8a8838d6c890dbd6dc64 100644
--- a/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp
+++ b/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
 */
 
 // author: Riccardo.Maria.Bianchi@cern.ch, 2017
@@ -148,6 +148,8 @@ void WriteGeoModel::handleFullPhysVol (const GeoFullPhysVol *vol)
 
 void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol)
 {
+    //std::cout << "WriteGeoModel::handleVPhysVolObjects() -- visiting... " << vol << std::endl; // debug msg
+
 	// get the address string for the current volume
   std::string address = getAddressStringFromPointer( vol );
 
@@ -270,7 +272,7 @@ void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol)
 
 		// LOGVOL
 		const GeoLogVol* logVol = vol->getLogVol();
-    const std::string logName = logVol->getName();
+        const std::string logName = logVol->getName();
 
 		// MATERIAL
 		const GeoMaterial * mat = vol->getLogVol()->getMaterial();
@@ -300,27 +302,29 @@ void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol)
 			const GeoPhysVol* physVol = dynamic_cast<const GeoPhysVol*>(vol);
 			// store the PhysVol volume into the DB
 			physId = storeObj(physVol, logvolId, parentId, storeRootVolume); // with parent info
-      volTypeStr = "GeoPhysVol";
+            volTypeStr = "GeoPhysVol";
 		}
 		else if (dynamic_cast<const GeoFullPhysVol*>(vol)) {
 			const GeoFullPhysVol* fullVol = dynamic_cast<const GeoFullPhysVol*>(vol);
 			physId = storeObj(fullVol, logvolId, parentId, storeRootVolume); // with parent info
-      volTypeStr = "GeoFullPhysVol";
+            volTypeStr = "GeoFullPhysVol";
 		} else {
-      std::cout << "WARNING!! Unknown GeoVPhysVol type!! Exiting..." << std::endl;
-      exit(EXIT_FAILURE);
+            std::cout << "GeoModelWrite -- WARNING!! Unknown GeoVPhysVol type!! Exiting..." << std::endl;
+            exit(EXIT_FAILURE);
 		}
 
 	} else {
 		physId = getStoredIdFromAddress(address);
-    volTypeStr = getGeoTypeFromVPhysVol(vol);
+        volTypeStr = getGeoTypeFromVPhysVol(vol);
 	}
 
     // Now we get the 'copy number' for this volume,
     // to distinguish this volume from the other volumes created from the same shared node (if any)
-  if (volTypeStr == "NULL") std::cout << "ERROR!! volTypeStr is 'NULL'!!!\n";
+    if (volTypeStr == "NULL") std::cout << "ERROR!! volTypeStr is 'NULL'!!!\n";
     const unsigned int volCopyN = setVolumeCopyNumber(physId, volTypeStr);
-    //JFB Commented out: qDebug() << "physId: " << physId << "- volume copy number: " << volCopyN;
+
+    // debug msg
+    //std::cout << "WriteGeoModel -- physId: " << physId << "- volume copy number: " << volCopyN << std::endl;
 
     if ( isRootVolume || parentId == 0) {
         //qDebug() << "This is the RootVolume or the volume has 'NULL' parent (unconnected subtree?) - So, we do not store the child position for this volume!";
@@ -347,7 +351,7 @@ void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol)
 	else if (dynamic_cast<const GeoFullPhysVol*>(vol)) {
 		geoType = "GeoFullPhysVol";
 	} else {
-    std::cout << "WARNING!! Unknown GeoVPhysVol type!!" << std::endl;
+    std::cout << "GeoModelWrite -- WARNING!! Unknown GeoVPhysVol type!!" << std::endl;
 	}
 	return geoType;
 }
@@ -498,7 +502,7 @@ void WriteGeoModel::handleSerialTransformer (const GeoSerialTransformer *node)
         try {
             persistifier.persistify(*func);
         } catch (const std::runtime_error & error) {
-            std::cout << "SEVERE WARNING!! Handling std::runtime_error! -->" << error.what() << std::endl;
+            std::cout << "GeoModelWrite -- SEVERE WARNING!! Handling std::runtime_error! -->" << error.what() << std::endl;
         }
     std::string expression = persistifier.getCodedString();
 
@@ -652,7 +656,7 @@ void WriteGeoModel::handleNameTag(const GeoNameTag* node)
 			}
 		}
 		else{
-      std::cout << "WARNING!! Len == 0, but this cannot be the Root volume!" << std::endl;
+      std::cout << "GeoModelWrite -- WARNING!! Len == 0, but this cannot be the Root volume!" << std::endl;
 		}
 
   std::vector<std::string> parentList;
@@ -1124,7 +1128,7 @@ std::string WriteGeoModel::getShapeParameters(const GeoShape* shape)
   //   shapePars=pars.join(";");
   // }
   else {
-    std::cout << "\n\tWARNING!!! - Shape '" << shapeType << "' needs to be persistified!!\n\n";
+    std::cout << "\n\tGeoModelWrite -- WARNING!!! - Shape '" << shapeType << "' needs to be persistified!!\n\n";
     printStdVectorStrings(m_objectsNotPersistified);
   }
                      
@@ -1702,7 +1706,7 @@ void WriteGeoModel::saveToDB( std::vector<GeoPublisher*>& publishers )
 
 
 	if ( !m_objectsNotPersistified.empty() ) {
-        std::cout << "\n\tWARNING!! There are shapes/nodes which need to be persistified! --> ";
+        std::cout << "\n\tGeoModelWrite -- WARNING!! There are shapes/nodes which need to be persistified! --> ";
         printStdVectorStrings(m_objectsNotPersistified);
         std::cout << "\n\n";
 	}
@@ -1741,12 +1745,12 @@ void WriteGeoModel::storePublishedNodes(GeoPublisher* store)
     if (mapAXF.size() > 0) {
         m_dbManager->addListOfPublishedAlignableTransforms(m_publishedAlignableTransforms_String, storeName); 
     } else {
-        std::cout << "\nWARNING! A pointer to a GeoPublisher was provided, but no GeoAlignableTransform nodes have been published. Please, check if that was intended. (If in doubt, please ask to 'geomodel-developers@cern.ch')\n" << std::endl;
+        std::cout << "\nGeoModelWrite -- WARNING! A pointer to a GeoPublisher was provided, but no GeoAlignableTransform nodes have been published. Please, check if that was intended. (If in doubt, please ask to 'geomodel-developers@cern.ch')\n" << std::endl;
     }
     if (mapFPV.size() > 0) {
         m_dbManager->addListOfPublishedFullPhysVols(m_publishedFullPhysVols_String, storeName);
     } else {
-        std::cout << "\nWARNING! A pointer to a GeoPublisher was provided, but no GeoFullPhysVol nodes have been published. Please, check if that was intended. (If in doubt, please ask to 'geomodel-developers@cern.ch')\n" << std::endl;
+        std::cout << "\nGeoModelWrite -- WARNING! A pointer to a GeoPublisher was provided, but no GeoFullPhysVol nodes have been published. Please, check if that was intended. (If in doubt, please ask to 'geomodel-developers@cern.ch')\n" << std::endl;
     }
 
     // clear the caches
diff --git a/GeoModelTools/GMCAT/src/gmcat.cxx b/GeoModelTools/GMCAT/src/gmcat.cxx
index 31b4873199ce6fb252155a5f4db01a5f5e9e2a7e..c486d4ab2db40423b9dd92591b06da324a0359d6 100644
--- a/GeoModelTools/GMCAT/src/gmcat.cxx
+++ b/GeoModelTools/GMCAT/src/gmcat.cxx
@@ -1,3 +1,7 @@
+/*
+ *   Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration   
+*/
+
 #include "GeoModelKernel/GeoVGeometryPlugin.h"
 #include "GeoModelDBManager/GMDBManager.h"
 #include "GeoModelRead/ReadGeoModel.h"
@@ -84,19 +88,19 @@ 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 << "Error, cannot overwrite existing file " << outputFile << std::endl;
+	std::cerr << "gmcat -- Error, cannot overwrite existing file " << outputFile << std::endl;
 	return 3;
       }
     }
     else {
-      std::cerr << "Error, cannot overwrite existing file " << outputFile << " (permission denied)" << std::endl;
+      std::cerr << "gmcat -- Error, cannot overwrite existing file " << outputFile << " (permission denied)" << std::endl;
       return 4;
     }
   }
 
 
   //
-  // Create elements and materials:
+  // Create elements and materials for the "World" volume, which is the container:
   //
 
   const double  gr =   SYSTEM_OF_UNITS::gram;
@@ -133,7 +137,7 @@ int main(int argc, char ** argv) {
     GeoGeometryPluginLoader loader;
     GeoVGeometryPlugin *factory=loader.load(plugin);
     if (!factory) {
-      std::cerr << "Could not load plugin " << plugin << std::endl;
+      std::cerr << "gmcat -- Could not load plugin " << plugin << std::endl;
       return 5;
     }
     
@@ -155,7 +159,7 @@ int main(int argc, char ** argv) {
   for (const std::string & file : inputFiles) {
     GMDBManager* db = new GMDBManager(file);
     if (!db->checkIsDBOpen()){
-      std::cerr << "Error opening input file " << file << std::endl;
+      std::cerr << "gmcat -- Error opening the input file: " << file << std::endl;
       return 6;
     }
 
@@ -165,8 +169,10 @@ int main(int argc, char ** argv) {
     /* build the GeoModel geometry */
     GeoPhysVol* 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()) {
       GeoNameTag *nameTag=new GeoNameTag(aV.getName());
       GeoTransform *transform= new GeoTransform(aV.getTransform());
@@ -175,6 +181,7 @@ int main(int argc, char ** argv) {
       world->add((GeoVPhysVol *) &*aV.getVolume());
       aV.next();
     }
+
     delete db;
   }
   //
@@ -185,13 +192,17 @@ int main(int argc, char ** argv) {
   // check the DB connection
   //
   if (!db.checkIsDBOpen()) {
-    std::cerr << "Error opening output file " << outputFile << std::endl;
+    std::cerr << "gmcat -- Error opening the output file: " << outputFile << std::endl;
     return 7;
   }
 
   GeoModelIO::WriteGeoModel dumpGeoModelGraph(db);
   world->exec(&dumpGeoModelGraph);
-  dumpGeoModelGraph.saveToDB(vecPluginsPublishers);
+  if (vecPluginsPublishers.size() > 0) {
+      dumpGeoModelGraph.saveToDB(vecPluginsPublishers);
+  } else {
+      dumpGeoModelGraph.saveToDB();
+  }
 
   world->unref();