Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Common/CodeGen/CppTopicGeneratorGrantlee.cpp
T

331 lines
12 KiB
C++

#include "CppTopicGeneratorGrantlee.h"
#include "StructBuilder.h"
#include <NGLLogger/INGLLogger.h>
#include <QtCore/QCryptographicHash>
#include <ktexttemplate/context.h>
#ifdef RTI_HEADER_AVAILABLE
#include <dds/core/xtypes/EnumType.hpp>
#endif
using namespace CodeGen;
CppTopicGeneratorGrantlee::CppTopicGeneratorGrantlee() : GeneratorGrantleeBase("CodeGen.CppTopicGeneratorGrantlee") {}
bool CppTopicGeneratorGrantlee::init(const XmlReader* reader, StructBuilder* structBuilder)
{
m_reader = reader;
if (!GeneratorGrantleeBase::initInternal(reader, structBuilder))
return false;
addCustomFunctions(reader->getCustomFunctions());
return initDataTopics() && initFunctionTopics() && initIdlStructs();
}
bool CppTopicGeneratorGrantlee::initDataTopics()
{
DataTopicsWrapper* dataTopicsWrapper = new DataTopicsWrapper(QString(), this);
const auto dataTopics = m_reader->getIdlStructInformation();
QVector<IdlData> keyColumns;
QVector<IdlData> trColumns;
for (const CodeGen::TopicTypeInformation& tti : dataTopics)
{
if (!tti.isDataObject)
continue;
keyColumns.clear();
trColumns.clear();
const CompleteTopicTypeInformation ctti = m_structBuilder->topicTypeInformationByStructType(tti.name);
if (!ctti.isValid())
{
ERROR_LOG(m_logger) << "could not find informations for struct " << tti.name;
continue;
}
DataTopicWrapper* dtw = dataTopicsWrapper->addDataTopic(ctti);
getSpecialColumns(ctti, keyColumns, trColumns);
if (keyColumns.size() == 1)
dtw->setKeyColumnData(keyColumns.first());
dtw->setTrColumns(trColumns);
if (ctti.recordTopic)
{
const CompleteTableInformation cti(m_structBuilder->getRecordingTopicTable(ctti.name));
if (!cti.isEmpty())
dtw->setRecordTableInformation(cti);
}
else
{
if (ctti.isDataObject)
m_structBuilder->buildJSonStructureInformationFromIdlData(ctti);
}
}
m_ctx->insert(QStringLiteral("dataTopics"), dataTopicsWrapper);
QSet<QString> exportedSubTopics;
DataTopicsWrapper* subTopicsWrapper = new DataTopicsWrapper(QString(), this);
const QVector<QSharedPointer<DataTypeInfo>> serializeTopics = m_structBuilder->getSerializeFromToJsonTopics();
for (const QSharedPointer<DataTypeInfo>& dti : serializeTopics)
{
if (exportedSubTopics.contains(dti->idlType()))
continue;
if (dti->isStructure())
{
const CompleteTopicTypeInformation ctti = m_structBuilder->topicTypeInformationByStructType(dti->idlType());
if (!ctti.isValid())
{
ERROR_LOG(m_logger) << "could not find informations for struct " << dti->idlType();
continue;
}
const CompleteTableInformation cti(m_structBuilder->getRecordingTopicTable(ctti.name));
if (cti.isEmpty())
{
ERROR_LOG(m_logger) << "could not find informations for struct " << dti->idlType();
continue;
}
DEBUG_LOG(m_logger) << "Adding substruct topic " << ctti.name;
DataTopicWrapper* dtw = subTopicsWrapper->addDataTopic(ctti);
dtw->setRecordTableInformation(cti);
exportedSubTopics += dti->idlType();
}
}
m_ctx->insert(QStringLiteral("serializeTopics"), subTopicsWrapper);
QVector<MemberInformationListWrapper*> jsonTopics;
const QMap<QString, QVector<MemberInformation>> jsonExport = m_structBuilder->jsonStructureInformation();
for (auto it = jsonExport.begin(); it != jsonExport.end(); ++it)
{
MemberInformationListWrapper* mil = new MemberInformationListWrapper(it.key(), it.value(), this);
jsonTopics += mil;
}
m_ctx->insert(QStringLiteral("jsonTopics"), QVariant::fromValue(jsonTopics));
return true;
}
bool CppTopicGeneratorGrantlee::getSpecialColumns(const CompleteTopicTypeInformation& tti, QVector<IdlData>& keyColumns,
QVector<IdlData>& trColumns) const
{
DEBUG_LOG(m_logger) << "Get special columns for " << tti.name << " - base is " << tti.baseValueType;
if (!tti.isValid())
{
ERROR_LOG(m_logger) << "tti is not valid ...";
return false;
}
for (const IdlData& ci : tti.members)
{
if (ci.isKey)
keyColumns += ci;
if (ci.isTranslatable)
trColumns += ci;
}
if (tti.baseValueType.isEmpty())
return true;
return getSpecialColumns(topicTypeInformationByDerivedTopic(tti), keyColumns, trColumns);
}
bool CppTopicGeneratorGrantlee::initFunctionTopics()
{
const QVector<FunctionTopic> functionTopics = m_reader->getFunctionTopics();
FunctionTopicsWrapper* functionTopicsWrapper(new FunctionTopicsWrapper(QStringLiteral("functionTopics"), this));
for (const FunctionTopic& ft : functionTopics)
{
if (!handleStruct(ft, functionTopicsWrapper))
return false;
}
m_ctx->insert(QStringLiteral("functionTopics"), functionTopicsWrapper);
return true;
}
bool CppTopicGeneratorGrantlee::handleStruct(const FunctionTopic& ft, FunctionTopicsWrapper* functionTopicsWrapper)
{
DEBUG_LOG(m_logger) << "handling FunctionTopic: " << ft.name;
const CompleteTopicTypeInformation siRequest =
m_structBuilder->topicTypeInformationByStructType(ft.requestTopicType);
if (!siRequest.isValid())
{
WARNING_LOG(m_logger) << "Could not get topic informations about request topic " << ft.requestTopicName;
return false;
}
const CompleteTopicTypeInformation siReply = m_structBuilder->topicTypeInformationByStructType(ft.replyTopicType);
if (!siReply.isValid())
{
WARNING_LOG(m_logger) << "Could not get topic informations about reply topic " << ft.replyTopicType;
return false;
}
FunctionTopicWrapper* ftw = functionTopicsWrapper->addFunctionTopic(ft, siRequest, siReply);
const QByteArray hash =
QCryptographicHash::hash(ft.requestTopicName.toUtf8(), QCryptographicHash::Sha3_512).toHex().left(16);
ftw->setReplyHandlerHash(QStringLiteral("0x") + QString::fromLatin1(hash) + QStringLiteral("LL"));
if (!addRequesterRequestParams(ft.name, siRequest, ftw) || !addRequesterReplyParams(ft.name, siReply, ftw))
return false;
return true;
}
bool CppTopicGeneratorGrantlee::addRequesterRequestParams(const QString& request_name,
const CompleteTopicTypeInformation& request,
FunctionTopicWrapper* ftw)
{
if (request.hasBaseValue())
{
const CompleteTopicTypeInformation siBase =
m_structBuilder->topicTypeInformationByStructType(request.baseValueType);
if (!siBase.isValid())
{
WARNING_LOG(m_logger) << "Could not get topic informations about base request topic "
<< request.baseValueType;
return false;
}
if (!addRequesterRequestParams(request_name, siBase, ftw))
return false;
}
ftw->addRequestParams(request.members);
return true;
}
bool CppTopicGeneratorGrantlee::addRequesterReplyParams(const QString& request_name,
const CompleteTopicTypeInformation& reply,
FunctionTopicWrapper* ftw)
{
if (reply.hasBaseValue())
{
const CompleteTopicTypeInformation siBase =
m_structBuilder->topicTypeInformationByStructType(reply.baseValueType);
if (!siBase.isValid())
{
WARNING_LOG(m_logger) << "Could not get topic informations about base reply topic " << reply.baseValueType;
return false;
}
if (!addRequesterReplyParams(request_name, siBase, ftw))
return false;
}
ftw->addReplyParams(reply.members);
return true;
}
bool CppTopicGeneratorGrantlee::handleIdlStruct(const CompleteTopicTypeInformation& csi, QSet<QString>& idlStructNames,
QVector<IdlStructWrapper*>& idlStructs)
{
if (!csi.isValid())
return true;
if (idlStructNames.contains(csi.name))
return true;
if (csi.hasBaseValue())
{
const CompleteTopicTypeInformation ctti =
m_structBuilder->topicTypeInformationByStructType(csi.baseValueType, false);
if (ctti.isValid())
{
#ifdef RTI_HEADER_AVAILABLE
if (ctti.extensibility == dds::core::xtypes::ExtensibilityKind_def::FINAL)
{
ERROR_LOG(m_logger) << "Base struct (" << ctti.name
<< ") has final extensibility - this is not allowed";
return false;
}
#else
// RTI not available - skip extensibility check (assume EXTENSIBLE)
Q_UNUSED(ctti.extensibility);
#endif
if (!idlStructNames.contains(csi.baseValueType))
{
if (!handleIdlStruct(ctti, idlStructNames, idlStructs))
return false;
}
}
else
{
const int idx = csi.baseValueType.indexOf(QLatin1String("::"));
if (idx < 0)
{
ERROR_LOG(m_logger) << "idlStruct '" << csi.baseValueType << "' not found in idl-file";
return false;
}
}
}
for (const IdlData& idlData : csi.members)
{
QString idlType;
DEBUG_LOG(m_logger) << "member: " << idlData.type << " - " << idlData.name << " "
<< idlData.dataTypeInfo->isStructure() << " " << idlData.dataTypeInfo->isSequence();
if (idlData.dataTypeInfo->isStructure())
idlType = idlData.dataTypeInfo->idlType();
else if (idlData.dataTypeInfo->isSequence())
{
if (idlData.dataTypeInfo->innerDataType()->isStructure())
idlType = idlData.dataTypeInfo->innerDataType()->idlType();
}
if (idlType.isEmpty())
continue;
if (!handleIdlStruct(m_structBuilder->topicTypeInformationByStructType(idlType, false), idlStructNames,
idlStructs))
return false;
}
DEBUG_LOG(m_logger) << "Current structName: " << csi.name;
idlStructs += new IdlStructWrapper(csi, this);
idlStructNames.insert(csi.name);
return true;
}
bool CppTopicGeneratorGrantlee::initIdlStructs()
{
const QVector<CompleteTopicTypeInformation> csiData = m_structBuilder->topicTypeInformations();
QSet<QString> idlStructNames;
QVector<IdlStructWrapper*> idlStructs;
idlStructs.reserve(csiData.size());
for (const CompleteTopicTypeInformation& csi : csiData)
{
if (!handleIdlStruct(csi, idlStructNames, idlStructs))
return false;
}
m_ctx->insert(QStringLiteral("idl_structs"), QVariant::fromValue(idlStructs));
const QVector<EnumInformation> enumerations = m_structBuilder->enumInformations();
QVector<IdlEnumWrapper*> idlEnumerations;
idlEnumerations.reserve(enumerations.size());
for (const EnumInformation& ei : enumerations)
idlEnumerations += new IdlEnumWrapper(ei, this);
m_ctx->insert(QStringLiteral("idl_enums"), QVariant::fromValue(idlEnumerations));
exportUsedServices(m_reader);
return true;
}
CompleteTopicTypeInformation
CppTopicGeneratorGrantlee::topicTypeInformationByDerivedTopic(const CompleteTopicTypeInformation& tti) const
{
if (tti.baseValueType.isEmpty())
return CompleteTopicTypeInformation();
QString baseValueType = tti.baseValueType;
if (tti.name.contains(QLatin1String("::")) && !tti.baseValueType.contains(QLatin1String("::")))
{
const QStringList sl = tti.name.split(QStringLiteral("::"));
baseValueType = sl.at(0) + QLatin1String("::") + tti.baseValueType;
}
DEBUG_LOG(m_logger) << "topicTypeInformationByStructName(" << baseValueType << ")";
return m_structBuilder->topicTypeInformationByStructType(baseValueType);
}