/** * @RDE_HEADER@ * * XmlHelper - convert xml to a (dynamic) dds structure and save a dds structure as xml * $Id$ * $HeadURL$ * $Author$ */ #include "xmlhelper.h" #include #include #include "topic_tree_model.h" namespace XmlHelper { static void getPrimitiveData(const dds::core::xtypes::DynamicData &data, uint32_t member_index, const std::string &memberName, QDomDocument &doc, QDomElement ¤tNode); static void getSequenceData(const dds::core::xtypes::DynamicData &data, QDomDocument &doc, QDomElement ¤tNode); static void getContainerData(const dds::core::xtypes::DynamicData &data, QDomDocument &doc, QDomElement ¤tNode); static bool setPrimitiveData(dds::core::xtypes::DynamicData &data, uint32_t member_index, const QString &text); static void setContainerData(dds::core::xtypes::DynamicData &data, const QDomElement ¤tNode); static void setSequenceData(dds::core::xtypes::DynamicData &data, const QDomElement ¤tNode); void dds2Xml(const dds::core::xtypes::DynamicData &data, const QString &topicName, QDomDocument &doc, QDomElement ¤tNode) { QDomElement rootNode = doc.createElement(QStringLiteral("DdsData")); rootNode.setAttribute(QStringLiteral("count"), data.member_count()); rootNode.setAttribute(QStringLiteral("type"), QString::fromStdString(data.type().name())); rootNode.setAttribute(QStringLiteral("topic"), topicName); currentNode.appendChild(rootNode); getContainerData(data, doc, rootNode); } void getContainerData(const dds::core::xtypes::DynamicData &data, QDomDocument &doc, QDomElement ¤tNode) { const dds::core::xtypes::StructType &dtData = static_cast(data.type()); dds::core::xtypes::StructType dtDataCopy = dtData; for (uint32_t member_index = 1; member_index <= data.member_count(); ++member_index) { const dds::core::xtypes::Member &child = TopicDataModel::memberFromType(dtData, dtDataCopy, member_index - 1); const dds::core::xtypes::TypeKind typeKind = child.type().kind(); try { if (typeKind == dds::core::xtypes::TypeKind::ALIAS_TYPE) { const dds::core::xtypes::DynamicData inner = data.value(member_index); dds::core::xtypes::DynamicType innerType = inner.type(); dds::core::xtypes::TypeKind innerTypeKind = innerType.kind(); while (innerTypeKind == dds::core::xtypes::TypeKind::ALIAS_TYPE) { dds::core::xtypes::AliasType alias = static_cast(innerType); innerType = alias.related_type(); innerTypeKind = innerType.kind(); } if ((typeKind.underlying() & dds::core::xtypes::TypeKind::PRIMITIVE_TYPE) == dds::core::xtypes::TypeKind::PRIMITIVE_TYPE || (typeKind == dds::core::xtypes::TypeKind::STRING_TYPE) || (typeKind == dds::core::xtypes::TypeKind::ENUMERATION_TYPE)) getPrimitiveData(data, member_index, child.name(), doc, currentNode); else getContainerData(inner, doc, currentNode); continue; } if ((typeKind.underlying() & dds::core::xtypes::TypeKind::PRIMITIVE_TYPE) == dds::core::xtypes::TypeKind::PRIMITIVE_TYPE || (typeKind == dds::core::xtypes::TypeKind::STRING_TYPE) || (typeKind == dds::core::xtypes::TypeKind::ENUMERATION_TYPE)) { getPrimitiveData(data, member_index, child.name(), doc, currentNode); continue; } if (typeKind == dds::core::xtypes::TypeKind::SEQUENCE_TYPE || typeKind == dds::core::xtypes::TypeKind::ARRAY_TYPE) { const dds::core::xtypes::DynamicData inner = data.value(member_index); QDomElement fieldNode = doc.createElement(QString::fromStdString(child.name())); fieldNode.setAttribute(QStringLiteral("count"), inner.member_count()); currentNode.appendChild(fieldNode); if (inner.member_count() > 0) getSequenceData(inner, doc, fieldNode); // does not work continue; } if ((typeKind.underlying() & dds::core::xtypes::TypeKind::AGGREGATION_TYPE) == dds::core::xtypes::TypeKind::AGGREGATION_TYPE) { dds::core::xtypes::DynamicData inner = data.value(member_index); QDomElement fieldNode = doc.createElement(QString::fromStdString(child.name())); fieldNode.setAttribute(QStringLiteral("count"), inner.member_count()); fieldNode.setAttribute(QStringLiteral("type"), QString::fromStdString(inner.type().name())); currentNode.appendChild(fieldNode); getContainerData(inner, doc, fieldNode); continue; } qWarning("unhandled parameter at idx: %d, name: %s, type: %x", member_index, child.name().c_str(), typeKind.underlying()); } catch (const dds::core::Exception &e) { qWarning("got exception while getting container data: %s", e.what()); continue; } } } void getPrimitiveData(const dds::core::xtypes::DynamicData &data, uint32_t member_index, const std::string &memberName, QDomDocument &doc, QDomElement ¤tNode) { QDomElement primNode = doc.createElement(QString::fromStdString(memberName)); currentNode.appendChild(primNode); QString retString; switch (data.member_info(member_index).member_kind().underlying()) { case dds::core::xtypes::TypeKind::CHAR_8_TYPE: retString = QString::number(data.value(member_index)); break; #if RTI_DDS_VERSION_MAJOR < 6 case dds::core::xtypes::TypeKind::CHAR_32_TYPE: #else case dds::core::xtypes::TypeKind::CHAR_16_TYPE: #endif retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::UINT_8_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::INT_16_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::UINT_16_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::INT_32_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::UINT_32_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::INT_64_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::UINT_64_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::FLOAT_32_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::FLOAT_64_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::BOOLEAN_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::ENUMERATION_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::STRING_TYPE: { const dds::core::string tmp = data.value(member_index); if (tmp.c_str()) // unset -> nullptr retString = QString::fromUtf8(tmp.c_str()); break; } default: retString = QStringLiteral("?-Unknown Primitive Type-?"); break; } if (!retString.isEmpty()) primNode.appendChild(doc.createTextNode(retString)); } void getPrimSeqData(const dds::core::xtypes::DynamicData &data, uint32_t member_index, QDomDocument &doc, QDomElement elemNode ) { QString retString; switch (data.member_info(member_index).member_kind().underlying()) { case dds::core::xtypes::TypeKind::CHAR_8_TYPE: retString = QString::number(data.value(member_index)); break; #if RTI_DDS_VERSION_MAJOR < 6 case dds::core::xtypes::TypeKind::CHAR_32_TYPE: #else case dds::core::xtypes::TypeKind::CHAR_16_TYPE: #endif retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::UINT_8_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::INT_16_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::UINT_16_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::INT_32_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::UINT_32_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::INT_64_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::UINT_64_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::FLOAT_32_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::FLOAT_64_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::BOOLEAN_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::ENUMERATION_TYPE: retString = QString::number(data.value(member_index)); break; case dds::core::xtypes::TypeKind::STRING_TYPE: { const dds::core::string tmp = data.value(member_index); if (tmp.c_str()) // unset -> nullptr retString = QString::fromUtf8(tmp.c_str()); break; } default: retString = QStringLiteral("?-Unknown Primitive Type-?"); break; } elemNode.appendChild(doc.createTextNode(retString)); } void getSequenceData(const dds::core::xtypes::DynamicData &data, QDomDocument &doc, QDomElement ¤tNode) { for (uint32_t member_index = 1; member_index <= data.member_count(); ++member_index) { QDomElement elemNode = doc.createElement(currentNode.tagName() + QLatin1Char('.') + QString::number(member_index)); currentNode.appendChild(elemNode); const rti::core::xtypes::DynamicDataMemberInfo info = data.member_info(member_index); switch (info.member_kind().underlying()) { case dds::core::xtypes::TypeKind::STRUCTURE_TYPE: case dds::core::xtypes::TypeKind::SEQUENCE_TYPE: case dds::core::xtypes::TypeKind::ARRAY_TYPE: case dds::core::xtypes::TypeKind::ALIAS_TYPE: case dds::core::xtypes::TypeKind::AGGREGATION_TYPE: { const dds::core::xtypes::DynamicData inner = data.value(member_index); getContainerData(inner, doc, elemNode); break; } default: getPrimSeqData(data, member_index, doc, elemNode); break; } } } QString topicNameFromXml(const QDomElement ¤tNode) { return currentNode.attribute(QStringLiteral("topic")); } dds::core::xtypes::DynamicData xml2Dds(const QDomElement ¤tNode, const DDSGeneric::TopicDescription &td) { static const dds::core::xtypes::StructType s_unknown("Unknown"); QString typeName = currentNode.attribute(QStringLiteral("type")); if (td.name.empty()) return dds::core::xtypes::DynamicData(s_unknown); const dds::core::xtypes::StructType &tc = typeName.compare(QString::fromStdString(td.typeName), Qt::CaseInsensitive) == 0 ? td.type : s_unknown; dds::core::xtypes::DynamicData data(tc); setContainerData(data, currentNode); return data; } void setContainerData(dds::core::xtypes::DynamicData &data, const QDomElement ¤tNode) { QDomNodeList dnl = currentNode.childNodes(); for (int i = 0; i < dnl.size(); ++i) { const QDomNode dn = dnl.at(i); if (!dn.isElement()) continue; const QDomElement de = dn.toElement(); try { rti::core::xtypes::DynamicDataMemberInfo info = data.member_info(de.nodeName().toStdString()); const dds::core::xtypes::TypeKind typeKind = info.member_kind(); if ((typeKind.underlying() & dds::core::xtypes::TypeKind::AGGREGATION_TYPE) == dds::core::xtypes::TypeKind::AGGREGATION_TYPE) { rti::core::xtypes::LoanedDynamicData loanedData = data.loan_value(info.member_index()); dds::core::xtypes::DynamicData &innerData = loanedData.get(); setContainerData(innerData, de); } else if((typeKind.underlying() & dds::core::xtypes::TypeKind::SEQUENCE_TYPE) == dds::core::xtypes::TypeKind::SEQUENCE_TYPE) { rti::core::xtypes::LoanedDynamicData loanedData = data.loan_value(info.member_index()); dds::core::xtypes::DynamicData &innerData = loanedData.get(); setSequenceData(innerData, de); } else { if (!setPrimitiveData(data, info.member_index(), de.text())) return; } } catch (dds::core::Exception &e) { qWarning("got exception while setting container data: %s", e.what()); return; } } } void setSequenceData(dds::core::xtypes::DynamicData &data, const QDomElement ¤tNode) { QDomNodeList dnl = currentNode.childNodes(); for (int i = 0; i < dnl.size(); ++i) { const QDomNode dn = dnl.at(i); if (!dn.isElement()) continue; const QDomElement de = dn.toElement(); try { if(true) //if(dds::core::xtypes::is_primitive_type(data.type().kind().underlying())) // find out the type! { if (!setPrimitiveData(data, i+1, de.text())) return; } else { rti::core::xtypes::LoanedDynamicData loanedData = data.loan_value(i+1); dds::core::xtypes::DynamicData &innerData = loanedData.get(); setContainerData(innerData, de); } } catch (dds::core::Exception &e) { qWarning("got exception while setting container data: %s", e.what()); return; } } } bool setPrimitiveData(dds::core::xtypes::DynamicData &data, uint32_t member_index, const QString &text) { bool bOk; switch (data.member_info(member_index).member_kind().underlying()) { case dds::core::xtypes::TypeKind::CHAR_8_TYPE: { char val = text.toUInt(&bOk); if (!bOk) return false; data.value(member_index, val); break; } #if RTI_DDS_VERSION_MAJOR < 6 case dds::core::xtypes::TypeKind::CHAR_32_TYPE: #else case dds::core::xtypes::TypeKind::CHAR_16_TYPE: #endif { DDS_Wchar val = text.toUInt(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::UINT_8_TYPE: { uint8_t val = text.toUInt(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::INT_16_TYPE: { int16_t val = text.toInt(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::UINT_16_TYPE: { uint16_t val = text.toUInt(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::INT_32_TYPE: { int32_t val = text.toInt(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::UINT_32_TYPE: { uint32_t val = text.toUInt(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::INT_64_TYPE: { int64_t val = text.toLongLong(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::UINT_64_TYPE: { uint64_t val = text.toULongLong(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::FLOAT_32_TYPE: { float val = text.toFloat(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::FLOAT_64_TYPE: { double val = text.toDouble(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::BOOLEAN_TYPE: { bool val = text.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0 ? true : false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::ENUMERATION_TYPE: { DDS_UnsignedLong val = text.toULong(&bOk); if (!bOk) return false; data.value(member_index, val); break; } case dds::core::xtypes::TypeKind::STRING_TYPE: { data.value(member_index, text.toStdString()); break; } default: return false; } return true; } } // namespace XmlHelper