From d94bf911b56d37b7432b0f464e6f56dbe974e114 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Thu, 10 Feb 2022 17:11:49 +0100
Subject: [PATCH] move rwBaseClass to Serialize

---
 GUI/Model/Device/AxesItems.cpp             |   2 +-
 GUI/Model/Device/BeamItems.cpp             |   2 +-
 GUI/Model/Device/InstrumentItems.cpp       |   6 +-
 GUI/Model/Device/PointwiseAxisItem.cpp     |   2 +-
 GUI/Model/Sample/LayerItem.cpp             |   2 +-
 GUI/Model/Sample/ParticleCoreShellItem.cpp |   4 +-
 GUI/Model/XML/Streamer.h                   | 100 ++++++++-------------
 7 files changed, 48 insertions(+), 70 deletions(-)

diff --git a/GUI/Model/Device/AxesItems.cpp b/GUI/Model/Device/AxesItems.cpp
index 3f33055eea9..d63429908c8 100644
--- a/GUI/Model/Device/AxesItems.cpp
+++ b/GUI/Model/Device/AxesItems.cpp
@@ -170,7 +170,7 @@ AmplitudeAxisItem::AmplitudeAxisItem()
 void AmplitudeAxisItem::serialize(Streamer& s)
 {
     s.assertVersion(0);
-    s.rwBaseClass<BasicAxisItem>("base", this);
+    Serialize::rwBaseClass<BasicAxisItem>(s, "base", this);
     s.rwSI<bool>("lockMinMax", getItem(P_LOCK_MIN_MAX));
     s.rwSI<bool>("log", getItem(P_IS_LOGSCALE));
 }
diff --git a/GUI/Model/Device/BeamItems.cpp b/GUI/Model/Device/BeamItems.cpp
index 1d738be3cc4..1f3a9130edb 100644
--- a/GUI/Model/Device/BeamItems.cpp
+++ b/GUI/Model/Device/BeamItems.cpp
@@ -132,7 +132,7 @@ SpecularBeamItem::SpecularBeamItem(const InstrumentItem* owningInstrument)
 void SpecularBeamItem::serialize(Streamer& s)
 {
     s.assertVersion(0);
-    s.rwBaseClass<BeamItem>("BeamItem", this);
+    Serialize::rwBaseClass<BeamItem>(s, "BeamItem", this);
     Serialize::rwSelected<FootprintItemCatalog>(s, m_footprint);
 }
 
diff --git a/GUI/Model/Device/InstrumentItems.cpp b/GUI/Model/Device/InstrumentItems.cpp
index b1b778a12b7..453a93890c5 100644
--- a/GUI/Model/Device/InstrumentItems.cpp
+++ b/GUI/Model/Device/InstrumentItems.cpp
@@ -263,7 +263,7 @@ DepthProbeInstrumentItem::DepthProbeInstrumentItem()
 void DepthProbeInstrumentItem::serialize(Streamer& s)
 {
     s.assertVersion(0);
-    s.rwBaseClass<InstrumentItem>("InstrumentItem", this);
+    Serialize::rwBaseClass<InstrumentItem>(s, "InstrumentItem", this);
     m_zAxis.rwXML(s, "zAxis");
 }
 
@@ -332,7 +332,7 @@ Instrument2DItem::Instrument2DItem()
 void Instrument2DItem::serialize(Streamer& s)
 {
     s.assertVersion(0);
-    s.rwBaseClass<InstrumentItem>("InstrumentItem", this);
+    Serialize::rwBaseClass<InstrumentItem>(s, "InstrumentItem", this);
     Serialize::rwSelected<DetectorItemCatalog>(s, m_detector);
 }
 
@@ -423,7 +423,7 @@ OffSpecularInstrumentItem::OffSpecularInstrumentItem()
 void OffSpecularInstrumentItem::serialize(Streamer& s)
 {
     s.assertVersion(0);
-    s.rwBaseClass<Instrument2DItem>("Instrument2DItem", this);
+    Serialize::rwBaseClass<Instrument2DItem>(s, "Instrument2DItem", this);
     m_alphaAxis.rwXML(s, "alphaAxis");
 }
 
diff --git a/GUI/Model/Device/PointwiseAxisItem.cpp b/GUI/Model/Device/PointwiseAxisItem.cpp
index 1a35daac107..fce199f0240 100644
--- a/GUI/Model/Device/PointwiseAxisItem.cpp
+++ b/GUI/Model/Device/PointwiseAxisItem.cpp
@@ -40,7 +40,7 @@ void PointwiseAxisItem::serialize(Streamer& s)
         a = serializeBinaryData();
 
     s.assertVersion(0);
-    s.rwBaseClass<BasicAxisItem>("base", this);
+    Serialize::rwBaseClass<BasicAxisItem>(s, "base", this);
     s.rwSI<QString>("nativeUnits", getItem(P_NATIVE_AXIS_UNITS));
     Serialize::rwValue(s, "axisData", a);
 
diff --git a/GUI/Model/Sample/LayerItem.cpp b/GUI/Model/Sample/LayerItem.cpp
index ec8a9bda91c..f07ca382e4c 100644
--- a/GUI/Model/Sample/LayerItem.cpp
+++ b/GUI/Model/Sample/LayerItem.cpp
@@ -188,6 +188,6 @@ void LayerItem::serialize(Streamer& s)
     Serialize::rwValue(s, "MaterialIdentifier", m_materialIdentifier);
     Serialize::rwProperty(s, m_numSlices);
     Serialize::rwProperty(s, m_thickness);
-    s.rwIC2("Roughness", m_topRoughness);
+    Serialize::rwOptional(s, "Roughness", m_topRoughness);
     Serialize::rwVector(s, "Layouts", m_layouts, m_materialItems);
 }
diff --git a/GUI/Model/Sample/ParticleCoreShellItem.cpp b/GUI/Model/Sample/ParticleCoreShellItem.cpp
index 5562733b342..68142109a8d 100644
--- a/GUI/Model/Sample/ParticleCoreShellItem.cpp
+++ b/GUI/Model/Sample/ParticleCoreShellItem.cpp
@@ -43,8 +43,8 @@ void ParticleCoreShellItem::serialize(Streamer& s)
     s.assertVersion(0);
     Serialize::rwProperty(s, m_abundance);
     Serialize::rwProperty(s, m_position);
-    s.rwIC2("core", m_core, m_materials);
-    s.rwIC2("shell", m_shell, m_materials);
+    Serialize::rwOptional(s, "core", m_core, m_materials);
+    Serialize::rwOptional(s, "shell", m_shell, m_materials);
 }
 
 std::unique_ptr<ParticleCoreShell> ParticleCoreShellItem::createParticleCoreShell() const
diff --git a/GUI/Model/XML/Streamer.h b/GUI/Model/XML/Streamer.h
index d52e4344724..7556eac0b91 100644
--- a/GUI/Model/XML/Streamer.h
+++ b/GUI/Model/XML/Streamer.h
@@ -54,25 +54,11 @@ public:
     //! As writer, does nothing.
     void assertVersion(unsigned expectedVersion) const;
 
-    //! serialize item which has only one exact class, and can be present or not
-    template <typename ItemClass>
-    void rwIC(const QString& tag, ItemClass*& p);
-
-    //! serialize item which has only one exact class, and can be present or not.
-    //!
-    //! argsForConstructor will be handed to the constructor when creating ItemClass.
-    template <typename ItemClass, typename... ArgsForConstructor>
-    void rwIC2(const QString& tag, std::unique_ptr<ItemClass>& up,
-            ArgsForConstructor... argsForConstructor);
-
     //! Only for migration
     // #bamigration Remove once the SessionItem migration is done
     template <typename type>
     void rwSI(const QString& tag, SessionItem* property);
 
-    template <typename BaseClass>
-    void rwBaseClass(const QString& tag, BaseClass* p);
-
     //! serialize item which has only one exact class, and can be present or not.
     //!
     //! The given initializer will be called after creation and before de-serialization
@@ -117,26 +103,37 @@ void rwValue(Streamer& s, const QString& tag, QColor& col);
 void rwValue(Streamer& s, const QString& tag, QByteArray& val);
 void rwValue(Streamer& s, const QString& tag, R3& val);
 
-//! Serializes a class which provides the function `void serialize(Streamer&)`.
+//! Serializes an item from a class that provides the function `void serialize(Streamer&)`.
 template <typename T>
 void rwClass(Streamer& s, const QString& tag, T& t);
 
-//! Serializes a list with a known and fixed type.
+//! Serializes part of an items that belongs to a given base class.
+template <typename BaseClass>
+void rwBaseClass(Streamer& s, const QString& tag, BaseClass* p);
+
+//! Serializes a list of items of known and fixed type.
+//! Passes optional arguments to the constructor.
 template <typename T, typename... Args>
 void rwVector(Streamer& s, const QString& tag, QVector<T>& vec, Args... argsForConstructor);
 
-//! Serializes a list with a base class type, which can contain derived types. For this we need
-//! the catalog of possible classes/types to identify the current type and to re-create this
-//! type after serialization.
+//! Serializes a list of items from a class hierarchy described by a catalog.
+//! Passes optional arguments to the constructor.
 template <typename Catalog, typename... Args>
 void rwCatalogized(Streamer& s, const QString& tag, QVector<typename Catalog::CatalogedType*>& vec,
                    Args... argsForConstructor);
 
-//! Serializes one item selected from a catalog.
+//! Serializes an item from a catalog.
+//! Passes optional arguments to the constructor.
 template <typename Catalog, typename... ArgsForCreation>
 void rwSelected(Streamer& s, SelectionProperty<typename Catalog::CatalogedType*>& d,
            ArgsForCreation... argsForCreation);
 
+//! Serializes an optional item of known type.
+//! Passes optional arguments to the constructor.
+template <typename ItemClass, typename... ArgsForConstructor>
+void rwOptional(Streamer& s, const QString& tag, std::unique_ptr<ItemClass>& up,
+                ArgsForConstructor... argsForConstructor);
+
 } // namespace Serialize
 
 //  ************************************************************************************************
@@ -151,6 +148,20 @@ void Serialize::rwClass(Streamer& s, const QString& tag, T& t)
     s.finish(tag);
 }
 
+template <typename BaseClass>
+void Serialize::rwBaseClass(Streamer& s, const QString& tag, BaseClass* p)
+{
+    if (QXmlStreamWriter* w = s.xmlWriter()) {
+        w->writeStartElement(tag);
+        p->BaseClass::serialize(s);
+        w->writeEndElement();
+    } else if (QXmlStreamReader* r = s.xmlReader()) {
+        s.gotoStartElementOfTag(tag);
+        p->BaseClass::serialize(s);
+        s.gotoEndElementOfTag(tag);
+    }
+}
+
 template <typename T, typename... Args>
 void Serialize::rwVector(Streamer& s, const QString& tag, QVector<T>& vec,
                          Args... argsForConstructor)
@@ -214,44 +225,25 @@ void Serialize::rwSelected(Streamer& s, SelectionProperty<typename Catalog::Cata
     }
 }
 
-template <typename ItemClass>
-void Streamer::rwIC(const QString& tag, ItemClass*& p)
-{
-    if (QXmlStreamWriter* w = xmlWriter()) {
-        w->writeStartElement(tag);
-        w->writeAttribute("valid", p ? "1" : "0");
-        if (p != nullptr)
-            p->serialize(*this);
-        w->writeEndElement();
-    } else if (QXmlStreamReader* r = xmlReader()) {
-        gotoStartElementOfTag(tag);
-        const bool valid = r->attributes().value("valid").toUInt() > 0;
-        p = valid ? new ItemClass() : nullptr;
-        if (p != nullptr)
-            p->serialize(*this);
-        gotoEndElementOfTag(tag);
-    }
-}
-
 template <typename ItemClass, typename... ArgsForConstructor>
-void Streamer::rwIC2(const QString& tag, std::unique_ptr<ItemClass>& up,
-                    ArgsForConstructor... argsForConstructor)
+void Serialize::rwOptional(Streamer& s, const QString& tag, std::unique_ptr<ItemClass>& up,
+                           ArgsForConstructor... argsForConstructor)
 {
-    if (QXmlStreamWriter* w = xmlWriter()) {
+    if (QXmlStreamWriter* w = s.xmlWriter()) {
         w->writeStartElement(tag);
         w->writeAttribute("valid", up ? "1" : "0");
         if (up)
-            up->serialize(*this);
+            up->serialize(s);
         w->writeEndElement();
-    } else if (QXmlStreamReader* r = xmlReader()) {
-        gotoStartElementOfTag(tag);
+    } else if (QXmlStreamReader* r = s.xmlReader()) {
+        s.gotoStartElementOfTag(tag);
         const bool valid = r->attributes().value("valid").toUInt() > 0;
         if (valid) {
             up.reset(new ItemClass(argsForConstructor...));
-            up->serialize(*this);
+            up->serialize(s);
         } else
             up.reset();
-        gotoEndElementOfTag(tag);
+        s.gotoEndElementOfTag(tag);
     }
 }
 
@@ -268,20 +260,6 @@ void Streamer::rwSI(const QString& tag, SessionItem* property)
     }
 }
 
-template <typename BaseClass>
-void Streamer::rwBaseClass(const QString& tag, BaseClass* p)
-{
-    if (QXmlStreamWriter* w = xmlWriter()) {
-        w->writeStartElement(tag);
-        p->BaseClass::serialize(*this);
-        w->writeEndElement();
-    } else if (QXmlStreamReader* r = xmlReader()) {
-        gotoStartElementOfTag(tag);
-        p->BaseClass::serialize(*this);
-        gotoEndElementOfTag(tag);
-    }
-}
-
 template <typename ItemClass>
 void Streamer::rwWithInit(const QString& tag, std::unique_ptr<ItemClass>& up,
                             const std::function<void(ItemClass*)>& initializer)
-- 
GitLab