summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2017-09-22 20:00:27 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2017-09-22 21:29:45 +0100
commitaad2e8edb2349829620050510b74452391190d67 (patch)
tree8f63e562bbb02b29e00a3ef1db0ff5e009df7f36
parentConverted Model part now handles optionality internally (cases where it do so... (diff)
downloadslicer-aad2e8edb2349829620050510b74452391190d67.tar.bz2
slicer-aad2e8edb2349829620050510b74452391190d67.tar.xz
slicer-aad2e8edb2349829620050510b74452391190d67.zip
Replace HasValue check with GetValue returning its success state when it writes a value
-rw-r--r--slicer/db/sqlInsertSerializer.cpp8
-rw-r--r--slicer/db/sqlUpdateSerializer.cpp8
-rw-r--r--slicer/json/serializer.cpp53
-rw-r--r--slicer/slicer/modelParts.cpp3
-rw-r--r--slicer/slicer/modelParts.h8
-rw-r--r--slicer/slicer/modelPartsTypes.h14
-rw-r--r--slicer/slicer/modelPartsTypes.impl.h51
-rw-r--r--slicer/test/conversions.cpp20
-rw-r--r--slicer/test/conversions.h6
-rw-r--r--slicer/test/initial/optionals2.json1
-rw-r--r--slicer/test/initial/optionals3.json1
-rw-r--r--slicer/test/initial/optionals5.json1
-rw-r--r--slicer/test/optionals.ice6
-rw-r--r--slicer/test/preprocessor.cpp2
-rw-r--r--slicer/test/serializers.cpp38
-rw-r--r--slicer/tool/parser.cpp6
-rw-r--r--slicer/xml/serializer.cpp32
-rw-r--r--slicer/xml/serializer.h5
18 files changed, 177 insertions, 86 deletions
diff --git a/slicer/db/sqlInsertSerializer.cpp b/slicer/db/sqlInsertSerializer.cpp
index 04eae93..cd10366 100644
--- a/slicer/db/sqlInsertSerializer.cpp
+++ b/slicer/db/sqlInsertSerializer.cpp
@@ -96,12 +96,10 @@ namespace Slicer {
SqlInsertSerializer::bindObjectAndExecuteField(int & paramNo, DB::ModifyCommand * ins, Slicer::ModelPartPtr cmp, HookCommonPtr h) const
{
if (isBind(h)) {
- if (cmp->HasValue()) {
- cmp->GetValue(new SqlBinder(*ins, paramNo++));
- }
- else {
- ins->bindNull(paramNo++);
+ if (!cmp->GetValue(new SqlBinder(*ins, paramNo))) {
+ ins->bindNull(paramNo);
}
+ paramNo++;
}
}
diff --git a/slicer/db/sqlUpdateSerializer.cpp b/slicer/db/sqlUpdateSerializer.cpp
index f07c421..394c660 100644
--- a/slicer/db/sqlUpdateSerializer.cpp
+++ b/slicer/db/sqlUpdateSerializer.cpp
@@ -51,12 +51,10 @@ namespace Slicer {
int paramNo = 0;
cmp->OnEachChild([&upd, &paramNo](const std::string &, ModelPartPtr cmp, HookCommonPtr h) {
if (isValue(h)) {
- if (cmp->HasValue()) {
- cmp->GetValue(new SqlBinder(*upd, paramNo++));
- }
- else {
- upd->bindNull(paramNo++);
+ if (!cmp->GetValue(new SqlBinder(*upd, paramNo))) {
+ upd->bindNull(paramNo);
}
+ paramNo++;
}
});
cmp->OnEachChild([&upd, &paramNo](const std::string &, ModelPartPtr cmp, HookCommonPtr h) {
diff --git a/slicer/json/serializer.cpp b/slicer/json/serializer.cpp
index 5402cbf..9429b9e 100644
--- a/slicer/json/serializer.cpp
+++ b/slicer/json/serializer.cpp
@@ -218,41 +218,48 @@ namespace Slicer {
void
JsonSerializer::ModelTreeIterate(json::Value * n, const std::string & name, ModelPartPtr mp)
{
- if (name.empty() || !n) {
+ if (name.empty() || !n || !mp) {
return;
}
- if (mp && mp->HasValue()) {
- switch (mp->GetType()) {
- case mpt_Null:
- boost::get<json::Object>(*n).insert({name, json::ValuePtr(new json::Value())});
- return;
- case mpt_Simple:
- mp->GetValue(new JsonValueTarget(*boost::get<json::Object>(*n).insert({name, json::ValuePtr(new json::Value())}).first->second));
+ switch (mp->GetType()) {
+ case mpt_Null:
+ boost::get<json::Object>(*n).insert({name, json::ValuePtr(new json::Value())});
+ return;
+ case mpt_Simple:
+ {
+ json::Value v;
+ if (mp->GetValue(new JsonValueTarget(v))) {
+ boost::get<json::Object>(*n).insert({ name, json::ValuePtr(new json::Value(v)) });
+ }
break;
- case mpt_Complex:
- {
- auto nn = json::ValuePtr(new json::Value(json::Object()));
- if (auto typeIdName = mp->GetTypeIdProperty()) {
- if (auto typeId = mp->GetTypeId()) {
- boost::get<json::Object>(*nn).insert({*typeIdName, json::ValuePtr(new json::Value(*typeId))});
- mp = mp->GetSubclassModelPart(*typeId);
- }
+ }
+ case mpt_Complex:
+ if (mp->HasValue()) {
+ auto nn = json::ValuePtr(new json::Value(json::Object()));
+ if (auto typeIdName = mp->GetTypeIdProperty()) {
+ if (auto typeId = mp->GetTypeId()) {
+ boost::get<json::Object>(*nn).insert({*typeIdName, json::ValuePtr(new json::Value(*typeId))});
+ mp = mp->GetSubclassModelPart(*typeId);
}
- mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterate, boost::get<json::Object>(*n).insert({name, nn}).first->second.get(), _1, _2));
- break;
}
- case mpt_Sequence:
+ mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterate, boost::get<json::Object>(*n).insert({name, nn}).first->second.get(), _1, _2));
+ }
+ break;
+ case mpt_Sequence:
+ if (mp->HasValue()) {
mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterateSeq, boost::get<json::Object>(*n).insert({name, json::ValuePtr(new json::Value(json::Array()))}).first->second.get(), _2));
- break;
- case mpt_Dictionary:
+ }
+ break;
+ case mpt_Dictionary:
+ if (mp->HasValue()) {
if (metaDataFlagSet(mp->GetMetadata(), md_object)) {
mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterateDictObj, boost::get<json::Object>(*n).insert({name, json::ValuePtr(new json::Value(json::Object()))}).first->second.get(), _2));
}
else {
mp->OnEachChild(boost::bind(&JsonSerializer::ModelTreeIterateSeq, boost::get<json::Object>(*n).insert({name, json::ValuePtr(new json::Value(json::Array()))}).first->second.get(), _2));
}
- break;
- }
+ }
+ break;
}
}
diff --git a/slicer/slicer/modelParts.cpp b/slicer/slicer/modelParts.cpp
index e33d110..6b26fe7 100644
--- a/slicer/slicer/modelParts.cpp
+++ b/slicer/slicer/modelParts.cpp
@@ -87,9 +87,10 @@ namespace Slicer {
{
}
- void
+ bool
ModelPart::GetValue(ValueTargetPtr)
{
+ return false;
}
const Metadata &
diff --git a/slicer/slicer/modelParts.h b/slicer/slicer/modelParts.h
index e0f49c4..611d370 100644
--- a/slicer/slicer/modelParts.h
+++ b/slicer/slicer/modelParts.h
@@ -103,6 +103,12 @@ namespace Slicer {
mpt_Dictionary,
};
+ enum TryConvertResult {
+ tcr_NoAction = 0,
+ tcr_NoValue,
+ tcr_Value,
+ };
+
class ChildRef : virtual public IceUtil::Shared {
public:
virtual ModelPartPtr Child() const = 0;
@@ -169,7 +175,7 @@ namespace Slicer {
virtual void Create();
virtual void Complete();
virtual void SetValue(ValueSourcePtr);
- virtual void GetValue(ValueTargetPtr);
+ virtual bool GetValue(ValueTargetPtr);
virtual bool HasValue() const = 0;
virtual const Metadata & GetMetadata() const;
virtual bool IsOptional() const;
diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h
index 52b7c62..62280cc 100644
--- a/slicer/slicer/modelPartsTypes.h
+++ b/slicer/slicer/modelPartsTypes.h
@@ -44,7 +44,7 @@ namespace Slicer {
ModelPartForSimple(T * h);
virtual void SetValue(ValueSourcePtr s) override;
- virtual void GetValue(ValueTargetPtr s) override;
+ virtual bool GetValue(ValueTargetPtr s) override;
};
class DLL_PUBLIC ModelPartForConvertedBase : public ModelPart {
@@ -62,9 +62,9 @@ namespace Slicer {
template<typename ET, typename MT>
inline static bool tryConvertFrom(const ValueSourcePtr & vsp, MT * model);
template<typename ET, typename MT, typename Conv>
- inline static bool tryConvertTo(const ValueTargetPtr & vsp, const MT * model, const Conv & conv);
+ inline static TryConvertResult tryConvertTo(const ValueTargetPtr & vsp, const MT * model, const Conv & conv);
template<typename ET, typename MT>
- inline static bool tryConvertTo(const ValueTargetPtr & vsp, const MT * model);
+ inline static TryConvertResult tryConvertTo(const ValueTargetPtr & vsp, const MT * model);
};
template<typename T, typename M, T M::* MV>
@@ -75,7 +75,7 @@ namespace Slicer {
ModelPartForConverted(T * h);
virtual void SetValue(ValueSourcePtr s) override;
- virtual void GetValue(ValueTargetPtr s) override;
+ virtual bool GetValue(ValueTargetPtr s) override;
};
template<typename T, typename M, IceUtil::Optional<T> M::* MV>
@@ -86,7 +86,7 @@ namespace Slicer {
ModelPartForConverted(IceUtil::Optional<T> * h);
virtual void SetValue(ValueSourcePtr s) override;
- virtual void GetValue(ValueTargetPtr s) override;
+ virtual bool GetValue(ValueTargetPtr s) override;
virtual bool HasValue() const override;
};
@@ -111,7 +111,7 @@ namespace Slicer {
public:
ModelPartForOptional(IceUtil::Optional< typename T::element_type > * h);
virtual void Create() override;
- virtual void GetValue(ValueTargetPtr s) override;
+ virtual bool GetValue(ValueTargetPtr s) override;
virtual ModelPartType GetType() const override;
protected:
@@ -248,7 +248,7 @@ namespace Slicer {
virtual void SetValue(ValueSourcePtr s) override;
- virtual void GetValue(ValueTargetPtr s) override;
+ virtual bool GetValue(ValueTargetPtr s) override;
static const Metadata metadata;
static const Enumerations enumerations;
diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h
index 2d6d169..2fe6401 100644
--- a/slicer/slicer/modelPartsTypes.impl.h
+++ b/slicer/slicer/modelPartsTypes.impl.h
@@ -156,10 +156,11 @@ namespace Slicer {
}
template<typename T>
- void ModelPartForSimple<T>::GetValue(ValueTargetPtr s)
+ bool ModelPartForSimple<T>::GetValue(ValueTargetPtr s)
{
BOOST_ASSERT(this->Model);
s->get(*this->Model);
+ return true;
}
// ModelPartForConverted
@@ -202,6 +203,8 @@ namespace Slicer {
T & operator()(IceUtil::Optional<Y> & x) const { if (!x) x = Y(); return *x; }
template <typename Y>
const T & operator()(const IceUtil::Optional<Y> & x) const { return *x; }
+ static bool valueExists(const T &) { return true; }
+ static bool valueExists(const IceUtil::Optional<T> & y) { return y; }
};
template <typename X>
struct Coerce<IceUtil::Optional<X>> {
@@ -211,16 +214,9 @@ namespace Slicer {
const IceUtil::Optional<T> & operator()(const IceUtil::Optional<T> & x) const { return x; }
template <typename Y>
IceUtil::Optional<T> operator()(Y & y) const { return y; }
+ static bool valueExists(const T &) { return true; }
};
- // Value exists check
- template <typename X, typename Y>
- typename std::enable_if<std::is_constructible<X, Y>::value, bool>::type
- valueExists(const Y &) { return true; }
- template <typename X, typename Y>
- typename std::enable_if<std::is_constructible<X, Y>::value, bool>::type
- valueExists(const IceUtil::Optional<Y> & y) { return y; }
-
template<typename ET, typename MT, typename Conv>
inline
bool ModelPartForConvertedBase::tryConvertFrom(const ValueSourcePtr & vsp, MT * model, const Conv & conv)
@@ -230,7 +226,7 @@ namespace Slicer {
ET tmp;
vspt->set(tmp);
auto converted = conv(Coerce<CA>()(tmp));
- if (valueExists<MT>(converted)) {
+ if (Coerce<MT>::valueExists(converted)) {
*model = Coerce<MT>()(converted);
}
return true;
@@ -243,7 +239,7 @@ namespace Slicer {
bool ModelPartForConvertedBase::tryConvertFrom(const ValueSourcePtr & vsp, MT * model)
{
if (auto vspt = dynamic_cast<TValueSource<ET> *>(vsp.get())) {
- if (valueExists<ET>(*model)) {
+ if (Coerce<ET>::valueExists(*model)) {
vspt->set(Coerce<ET>()(*model));
}
return true;
@@ -253,32 +249,35 @@ namespace Slicer {
template<typename ET, typename MT, typename Conv>
inline
- bool ModelPartForConvertedBase::tryConvertTo(const ValueTargetPtr & vsp, const MT * model, const Conv & conv)
+ TryConvertResult ModelPartForConvertedBase::tryConvertTo(const ValueTargetPtr & vsp, const MT * model, const Conv & conv)
{
if (auto vspt = dynamic_cast<TValueTarget<ET> *>(vsp.get())) {
typedef typename callable_traits<Conv>::template arg<0>::type CA;
- if (valueExists<CA>(*model)) {
+ typedef typename std::remove_const<typename std::remove_reference<CA>::type>::type CAR;
+ if (Coerce<CAR>::valueExists(*model)) {
auto converted = conv(Coerce<CA>()(*model));
- if (valueExists<ET>(converted)) {
+ if (Coerce<ET>::valueExists(converted)) {
vspt->get(Coerce<ET>()(converted));
+ return tcr_Value;
}
}
- return true;
+ return tcr_NoValue;
}
- return false;
+ return tcr_NoAction;
}
template<typename ET, typename MT>
inline
- bool ModelPartForConvertedBase::tryConvertTo(const ValueTargetPtr & vsp, const MT * model)
+ TryConvertResult ModelPartForConvertedBase::tryConvertTo(const ValueTargetPtr & vsp, const MT * model)
{
if (auto vspt = dynamic_cast<TValueTarget<ET> *>(vsp.get())) {
- if (valueExists<ET>(*model)) {
+ if (Coerce<ET>::valueExists(*model)) {
vspt->get(Coerce<ET>()(*model));
+ return tcr_Value;
}
- return true;
+ return tcr_NoValue;
}
- return false;
+ return tcr_NoAction;
}
// ModelPartForOptional
@@ -310,14 +309,13 @@ namespace Slicer {
}
template<typename T>
- void ModelPartForOptional<T>::GetValue(ValueTargetPtr s)
+ bool ModelPartForOptional<T>::GetValue(ValueTargetPtr s)
{
BOOST_ASSERT(this->Model);
- if (!*this->Model) {
- *this->Model = typename T::element_type();
- modelPart = new T(&**this->Model);
+ if (*this->Model) {
+ return modelPart->GetValue(s);
}
- modelPart->GetValue(s);
+ return false;
}
template<typename T>
@@ -556,10 +554,11 @@ namespace Slicer {
}
template<typename T>
- void ModelPartForEnum<T>::GetValue(ValueTargetPtr s)
+ bool ModelPartForEnum<T>::GetValue(ValueTargetPtr s)
{
BOOST_ASSERT(this->Model);
s->get(lookup(*this->Model));
+ return true;
}
// ModelPartForSequence
diff --git a/slicer/test/conversions.cpp b/slicer/test/conversions.cpp
index 2d1ef2c..9ac43e3 100644
--- a/slicer/test/conversions.cpp
+++ b/slicer/test/conversions.cpp
@@ -104,6 +104,26 @@ namespace Slicer {
{
return boost::posix_time::time_duration((ts->days * 24) + ts->hours, ts->minutes, ts->seconds);
}
+
+ DLL_PUBLIC
+ IceUtil::Optional<Ice::Int>
+ str2int(const std::string & s)
+ {
+ if (s.empty()) {
+ return IceUtil::None;
+ }
+ return boost::lexical_cast<Ice::Int>(s);
+ }
+
+ DLL_PUBLIC
+ std::string
+ int2str(const IceUtil::Optional<Ice::Int> & i)
+ {
+ if (!i) {
+ return std::string();
+ }
+ return boost::lexical_cast<std::string>(*i);
+ }
}
namespace TestModule {
diff --git a/slicer/test/conversions.h b/slicer/test/conversions.h
index 76dcd97..dfc76c6 100644
--- a/slicer/test/conversions.h
+++ b/slicer/test/conversions.h
@@ -30,6 +30,12 @@ namespace Slicer {
DLL_PUBLIC
std::string
dateTimeToString(const ::TestModule::DateTime & in);
+ DLL_PUBLIC
+ IceUtil::Optional<Ice::Int>
+ str2int(const std::string &);
+ DLL_PUBLIC
+ std::string
+ int2str(const IceUtil::Optional<Ice::Int> &);
}
#endif
diff --git a/slicer/test/initial/optionals2.json b/slicer/test/initial/optionals2.json
new file mode 100644
index 0000000..7bc047b
--- /dev/null
+++ b/slicer/test/initial/optionals2.json
@@ -0,0 +1 @@
+{"nonOptConverted":"4","optConverted":""}
diff --git a/slicer/test/initial/optionals3.json b/slicer/test/initial/optionals3.json
new file mode 100644
index 0000000..1c9dccf
--- /dev/null
+++ b/slicer/test/initial/optionals3.json
@@ -0,0 +1 @@
+{"nonOptConverted":"4","optConverted":"10"}
diff --git a/slicer/test/initial/optionals5.json b/slicer/test/initial/optionals5.json
new file mode 100644
index 0000000..1e0d3fc
--- /dev/null
+++ b/slicer/test/initial/optionals5.json
@@ -0,0 +1 @@
+{"nonOptConverted":"4"}
diff --git a/slicer/test/optionals.ice b/slicer/test/optionals.ice
index d037e67..c4c7436 100644
--- a/slicer/test/optionals.ice
+++ b/slicer/test/optionals.ice
@@ -15,6 +15,12 @@ module TestModule {
[ "slicer:conversion:boost.posix_time.ptime:boost.posix_time.to_iso_extended_string:boost.posix_time.time_from_string:nodeclare" ]
optional(5) string optConverted;
};
+ class Optionals2 {
+ [ "slicer:conversion:std.string:Slicer.str2int:Slicer.int2str:nodeclare" ]
+ optional(0) int optConverted;
+ [ "slicer:conversion:std.string:Slicer.str2int:Slicer.int2str:nodeclare" ]
+ int nonOptConverted;
+ };
};
#endif
diff --git a/slicer/test/preprocessor.cpp b/slicer/test/preprocessor.cpp
index 869c2a0..7d81f5e 100644
--- a/slicer/test/preprocessor.cpp
+++ b/slicer/test/preprocessor.cpp
@@ -20,7 +20,7 @@ ComponentsCount COMPONENTS_IN_TEST_ICE = {
{ "interfaces.ice", 0 },
{ "json.ice", 2 },
{ "locals.ice", 7 },
- { "optionals.ice", 1 },
+ { "optionals.ice", 2 },
{ "structs.ice", 4 },
{ "types.ice", 3 },
{ "xml.ice", 5 }
diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp
index cfbe794..8fee506 100644
--- a/slicer/test/serializers.cpp
+++ b/slicer/test/serializers.cpp
@@ -33,7 +33,15 @@ class FileBased {
void
verifyByFile(const fs::path & infile, const boost::function<void(const T &)> & check = NULL)
{
+ verifyByFile<T, DeserializerIn>(infile, infile, check);
+ }
+
+ template<typename T, typename DeserializerIn>
+ void
+ verifyByFile(const fs::path & infile, const fs::path & expOutFile, const boost::function<void(const T &)> & check = NULL)
+ {
const fs::path input = rootDir / "initial" / infile;
+ const fs::path expected = rootDir / "initial" / expOutFile;
const fs::path tmpf = binDir / "byFile";
fs::create_directory(tmpf);
const fs::path output = tmpf / infile;
@@ -60,7 +68,7 @@ class FileBased {
}
BOOST_TEST_CHECKPOINT("Checksum: " << input << " === " << output);
- diff(input, output);
+ diff(expected, output);
}
template<typename T, typename Deserializer, typename Serializer, typename Internal>
@@ -521,6 +529,34 @@ BOOST_AUTO_TEST_CASE( xml_simpleArray )
verifyByFile<TestModule::SimpleSeq, Slicer::XmlFileDeserializer>("simpleArray2.xml");
}
+BOOST_AUTO_TEST_CASE( json_emptyToNull )
+{
+ verifyByFile<TestModule::Optionals2Ptr, Slicer::JsonFileDeserializer>("optionals2.json", [](const auto & o) {
+ BOOST_REQUIRE(o);
+ BOOST_REQUIRE(!o->optConverted);
+ BOOST_REQUIRE_EQUAL(o->nonOptConverted, 4);
+ });
+}
+
+BOOST_AUTO_TEST_CASE( json_emptyToNull_withValue )
+{
+ verifyByFile<TestModule::Optionals2Ptr, Slicer::JsonFileDeserializer>("optionals3.json", [](const auto & o) {
+ BOOST_REQUIRE(o);
+ BOOST_REQUIRE(o->optConverted);
+ BOOST_REQUIRE_EQUAL(*o->optConverted, 10);
+ BOOST_REQUIRE_EQUAL(o->nonOptConverted, 4);
+ });
+}
+
+BOOST_AUTO_TEST_CASE( json_emptyToNull_omitted )
+{
+ verifyByFile<TestModule::Optionals2Ptr, Slicer::JsonFileDeserializer>("optionals5.json", "optionals2.json", [](const auto & o) {
+ BOOST_REQUIRE(o);
+ BOOST_REQUIRE(!o->optConverted);
+ BOOST_REQUIRE_EQUAL(o->nonOptConverted, 4);
+ });
+}
+
BOOST_AUTO_TEST_CASE( json_streams )
{
const auto tmpf = binDir / "byStream";
diff --git a/slicer/tool/parser.cpp b/slicer/tool/parser.cpp
index de3f699..fbe86d4 100644
--- a/slicer/tool/parser.cpp
+++ b/slicer/tool/parser.cpp
@@ -70,19 +70,19 @@ namespace Slicer {
Slice::typeToString(type));
fprintbf(cpp, "}\n\n");
- fprintbf(cpp, "template<> DLL_PUBLIC\nvoid\n");
+ fprintbf(cpp, "template<> DLL_PUBLIC\nbool\n");
createModelPartForConverted(type, c->scoped(), dm);
fprintbf(cpp, "::GetValue(ValueTargetPtr vtp)\n{\n");
fprintbf(cpp, "\tBOOST_ASSERT(Model);\n");
for (const auto & conversion : conversions) {
- fprintbf(cpp, "\tif (tryConvertTo< %s >(vtp, Model, &%s)) return;\n",
+ fprintbf(cpp, "\tif (auto r = tryConvertTo< %s >(vtp, Model, &%s)) return (r == tcr_Value);\n",
conversion.ExchangeType,
conversion.ConvertToExchangeFunc);
}
// Default conversion
if (!dm->hasMetaData("slicer:nodefaultconversion")) {
- fprintbf(cpp, "\tif (tryConvertTo< %s >(vtp, Model)) return;\n",
+ fprintbf(cpp, "\tif (auto r = tryConvertTo< %s >(vtp, Model)) return (r == tcr_Value);\n",
Slice::typeToString(type));
}
// Failed to convert
diff --git a/slicer/xml/serializer.cpp b/slicer/xml/serializer.cpp
index 899b789..8aa9552 100644
--- a/slicer/xml/serializer.cpp
+++ b/slicer/xml/serializer.cpp
@@ -172,6 +172,11 @@ namespace Slicer {
XmlValueTarget(boost::bind(&xmlpp::Element::set_first_child_text, p, _1))
{
}
+
+ XmlContentValueTarget(const CurrentElementCreator & cec) :
+ XmlValueTarget(boost::bind(&xmlpp::Element::set_first_child_text, boost::bind(&CurrentElementCreator::deref, &cec), _1))
+ {
+ }
};
void
@@ -294,7 +299,7 @@ namespace Slicer {
void
XmlSerializer::ModelTreeIterate(xmlpp::Element * n, const std::string & name, ModelPartPtr mp, HookCommonPtr hp, const ElementCreator & ec)
{
- if (!mp->HasValue() || name.empty()) {
+ if (name.empty()) {
return;
}
if (hp && metaDataFlagSet(hp->GetMetadata(), md_attribute)) {
@@ -314,7 +319,8 @@ namespace Slicer {
ModelTreeProcessElement(n, mp, boost::bind(&xmlpp::Element::add_child_element, _1, name, Glib::ustring()));
}
else {
- ModelTreeProcessElement(ec(n, name), mp, defaultElementCreator);
+ CurrentElementCreator cec(boost::bind(ec, n, name));
+ ModelTreeProcessElement(cec, mp, defaultElementCreator);
}
}
}
@@ -337,25 +343,27 @@ namespace Slicer {
dict->OnEachChild([element](const auto &, const auto & mp, const auto &) {
if (mp->HasValue()) {
mp->GetChild(keyName)->GetValue(new XmlValueTarget([&mp,element](const auto & name) {
- ModelTreeProcessElement(element->add_child_element(name), mp->GetChild(valueName), defaultElementCreator);
+ CurrentElementCreator cec([&element, &name]() { return element->add_child_element(name); });
+ ModelTreeProcessElement(cec, mp->GetChild(valueName), defaultElementCreator);
}));
}
});
}
void
- XmlSerializer::ModelTreeProcessElement(xmlpp::Element * element, ModelPartPtr mp, const ElementCreator & ec)
+ XmlSerializer::ModelTreeProcessElement(const CurrentElementCreator & cec, ModelPartPtr mp, const ElementCreator & ec)
{
- auto typeIdPropName = mp->GetTypeIdProperty();
- auto typeId = mp->GetTypeId();
- if (typeId && typeIdPropName) {
- element->set_attribute(*typeIdPropName, *typeId);
- mp = mp->GetSubclassModelPart(*typeId);
- }
if (mp->GetType() == mpt_Simple) {
- mp->GetValue(new XmlContentValueTarget(element));
+ mp->GetValue(new XmlContentValueTarget(cec));
}
- else {
+ else if (mp->HasValue()) {
+ auto typeIdPropName = mp->GetTypeIdProperty();
+ auto typeId = mp->GetTypeId();
+ auto element = cec.get();
+ if (typeId && typeIdPropName) {
+ element->set_attribute(*typeIdPropName, *typeId);
+ mp = mp->GetSubclassModelPart(*typeId);
+ }
mp->OnEachChild(boost::bind(&XmlSerializer::ModelTreeIterate, element, _1, _2, _3, ec));
}
}
diff --git a/slicer/xml/serializer.h b/slicer/xml/serializer.h
index 5521dc4..e13b5b5 100644
--- a/slicer/xml/serializer.h
+++ b/slicer/xml/serializer.h
@@ -5,8 +5,11 @@
#include <libxml++/document.h>
#include <libxml++/nodes/element.h>
#include <visibility.h>
+#include <lazyPointer.h>
namespace Slicer {
+ typedef ::AdHoc::LazyPointer<xmlpp::Element, xmlpp::Element *> CurrentElementCreator;
+
class DLL_PUBLIC XmlSerializer : public Serializer {
protected:
typedef boost::function<xmlpp::Element *(xmlpp::Element *, const Glib::ustring &)> ElementCreator;
@@ -14,7 +17,7 @@ namespace Slicer {
static void ModelTreeIterateRoot(xmlpp::Document *, const std::string &, ModelPartPtr mp);
protected:
- static void ModelTreeProcessElement(xmlpp::Element * n, ModelPartPtr mp, const ElementCreator &);
+ static void ModelTreeProcessElement(const CurrentElementCreator &, ModelPartPtr mp, const ElementCreator &);
static void ModelTreeIterateDictAttrs(xmlpp::Element * element, ModelPartPtr dict);
static void ModelTreeIterateDictElements(xmlpp::Element * element, ModelPartPtr dict);
};