#pragma once #include #include #include #include #include #include #include #ifdef RTI_DDS_AVAILABLE // Only include RTI headers if they are actually available #if __has_include() #include #define RTI_HEADER_AVAILABLE 1 #else #undef RTI_DDS_AVAILABLE #endif #endif #include "codegen_base_export.h" namespace NGL { class INGLLogger; } class QDomElement; namespace CodeGen { enum ExerciseDependency { Undefined = 0, Global = 0x1, Exercise = 0x2, GlobalAndExercise = 0x3 }; struct EnumKeyValuePair { QString key; int value = 0; }; struct EnumInformation { QString enumName; QString tableName; QString serviceName; QVector values; bool isValid() const { return !enumName.isEmpty(); } }; struct ColumnInformation { QString columnName; QString datatype; QString comment; QString defaultValue; bool isPrimaryKey = false; bool isAssignmentForPrimaryTablePk = false; bool isForeignKey = false; bool generateSelectRemove = false; bool canBeNull = true; bool hasSequence = false; bool isOptional = false; int sequenceStart = 0; int sequenceIncrement = 0; }; struct IdlColumnInformation { QString name; QString type; QString comment; bool isKey = false; bool isOptional = false; bool isTranslatable = false; }; struct ForeignKeyInformation { struct Endpoint { QString service; QString serviceAbbr; QString schema; QString tableName; QString columnName; }; QString name; Endpoint source; Endpoint destination; enum class OnDeleteAction { NoAction, Cascade, Restrict, SetNull, SetDefault } deleteAction = OnDeleteAction::Cascade; }; struct CustomServiceFunctionInformation { QString methodName; QString returnValue; QString signature; bool isConst = false; QVector paramTypes; QVector paramNames; enum class Type { Db, DbNotify, Dtc } type = Type::Db; }; struct DbNotifcationInformation : public CustomServiceFunctionInformation { DbNotifcationInformation() = default; explicit DbNotifcationInformation(const CustomServiceFunctionInformation& d) : CustomServiceFunctionInformation(d) { } enum class NotificationType { BeforeInsert, AfterInsert, BeforeUpdate, AfterUpdate, BeforeDelete, AfterDelete }; QVector notificationType; }; struct ConstraintInformation { enum struct Type { unknown = 0x00, unique = 0x01, index = 0x02 } type = Type::unknown; QString name; QStringList affectedColumns; }; struct TableInformation { QString name; QString structName; QString comment; QVector plainColumns; QVector> foreignKeys; QVector constraints; ExerciseDependency exerciseDependency = ExerciseDependency::Undefined; QSharedPointer fkInformationForColumn(const QString& tableName, const QString& columnName) const { for (const QSharedPointer& fki : foreignKeys) { if (fki->source.columnName == columnName && fki->source.tableName == tableName) return fki; } return QSharedPointer(); } }; struct ViewInformation { QString name; QString comment; QString structName; QString baseTable; QString baseSchema; QString filter; ExerciseDependency exerciseDependency = ExerciseDependency::Undefined; }; struct ServiceStructInformation { QString name; QString primaryTable; bool hasStaticContent = false; bool operator<(const ServiceStructInformation& o) const { if (hasStaticContent != o.hasStaticContent) return hasStaticContent < o.hasStaticContent; if (name != o.name) return name < o.name; return primaryTable < o.primaryTable; } QVector dbNotifications; }; struct TopicTypeInformationBase { TopicTypeInformationBase() = default; virtual ~TopicTypeInformationBase() = default; QString name; QString baseValueType; QString comment; bool isDataObject = false; bool dtsAutogen = true; bool dtcAutogen = true; bool recordTopic = false; bool routeToClient = true; bool routeToServer = false; bool routeInReplay = true; bool autosubscribe = true; #ifdef RTI_DDS_AVAILABLE dds::core::xtypes::ExtensibilityKind extensibility = dds::core::xtypes::ExtensibilityKind::EXTENSIBLE; #else int extensibility = 0; // Placeholder when RTI DDS is not available #endif virtual bool isValid() const { return !name.isEmpty(); } bool operator<(const TopicTypeInformationBase& o) const { if (name != o.name) return name < o.name; return baseValueType < o.baseValueType; } }; struct TopicTypeInformation : public TopicTypeInformationBase { QVector columns; }; struct FunctionTopic { QString name; QString requestTopicType; QString replyTopicType; QString requestTopicName; QString replyTopicName; bool routeInReplay = false; }; class CODEGEN_BASE_EXPORT XmlReader final { public: XmlReader(); bool readServiceFile(const QString& svcFile, const QString& idlServiceInfoFile = QString(), const XmlReader* parent = nullptr); QString errorString() const { return m_errorString; } QString getServiceNamespace() const { return m_svcNamespace; } QString getServiceAbbr() const { return m_svcAbbr; } QStringList getGroupNames() const { return m_groupNames; } int getPrio() const { return m_prio; } QStringList getProcNames() const { return m_svcProcNames; } bool hasCustomRecordReplayPlugin() const { return m_customRecordReplay; } bool getDevMode() const { return m_svcDevMode; } bool isServiceExerciseIndependent() const { return m_exerciseDependency == ExerciseDependency::Global; } ExerciseDependency defaultExerciseDependency() const { return m_exerciseDependency; } QMap> getDbClass2TableMapping() const { return m_dbClassTables; } QMap getStruct2BaseClassRelations() const { return m_struct2BaseClass; } QVector getStructToGenerate() const { return m_structsToGenerate; } QMap getIdlStructInformation() const { return m_idlStructsToGenerate; } QVector getIdlStructToGenerate() const { QVector res; res.reserve(m_idlStructsToGenerate.size()); auto it = m_idlStructsToGenerate.constBegin(); while (it != m_idlStructsToGenerate.constEnd()) { res.append(it.value()); ++it; } return res; } QMap> getTables() const { return m_tables; } QMap> getViews() const { return m_views; } QSharedPointer getTable(const QString& table) const { return m_tables.value(table); } QVector getEnumerations() const { return m_enumerations; } QVector getIdlColumns(const QString& structName) const { return m_idlStructsToGenerate.value(structName).columns; } QVector getFunctionTopics() const { return m_functionTopics; } QVector getExternalTopicTypes() const { return m_externalTopicTypes; } QString idlFileForService(const QString& serviceName) const { return getIdlFileForService(m_idlFiles, serviceName); } QString xmlFileForService(const QString& serviceName) const { return getIdlFileForService(m_xmlFiles, serviceName); } QMap usedServices() const { return m_usedServices; } QVector getCustomFunctions() const { return m_customFunctions; } TopicTypeInformation loadExternalTopicType(const QString& externalServiceName, const QString& topicTypeName); EnumInformation getExternalEnumeration(const QString& externalServiceName, const QString& enumName, bool verbose); static ExerciseDependency string2ExerciseDependency(const QString& str); XmlReader(const XmlReader&) = delete; XmlReader& operator=(const XmlReader&) = delete; private: NGL::INGLLogger& m_logger; void parseDBSserviceStructs(const QDomElement& rootElement); void parseDBTables(const QDomElement& rootElement); void parseDBViews(const QDomElement& rootElement); void parseEnumerations(const QDomElement& rootElement); void parseTopicTypes(const QDomElement& rootElement); void parseFunctionTopics(const QDomElement& rootElement); void parseCustomDtcFunctions(const QDomElement& rootElement); static QString getAttribute(const QDomElement& element, const QString& attributeName, bool bOptional = false); static bool getAttributeBool(const QDomElement& element, const QString& attributeName, bool bOptional, bool defaultValue); static int getAttributeInt(const QDomElement& element, const QString& attributeName, bool bOptional = false, int defaultValue = 0); ColumnInformation parseTableColumn(const QDomElement& column, const QString& tableName) const; IdlColumnInformation parseIdlStructColumn(const QDomElement& column) const; QSharedPointer parseForeignKey(const QDomElement& foreignKey) const; ForeignKeyInformation::Endpoint parseForeignKeyEndpoint(const QString& foreignKeyName, const QDomElement& endpoint) const; ConstraintInformation parseConstraint(const QDomElement& constraint) const; CustomServiceFunctionInformation parseCustomFunction(const QDomElement& customFunc, CustomServiceFunctionInformation::Type funcType) const; DbNotifcationInformation parseDbNotification(const QDomElement& customFunc) const; bool loadExternalService(const QString& serviceName); void loadIdlInfofile(const QString& idlServiceInfoFile); QString getIdlFileForService(const QMap& data, const QString& serviceName) const; QString serviceNameAbbreviation(const QString& serviceName) const; void getServiceNameInfoFromFilePath(const QStringList& parts); static QString serviceNamespaceFromFile(const QString& fn); QString m_svcNamespace; QString m_svcAbbr; QStringList m_svcProcNames; bool m_customRecordReplay; ExerciseDependency m_exerciseDependency{ExerciseDependency::Exercise}; QMap> m_dbClassTables; QMap m_struct2BaseClass; QVector m_structsToGenerate; QMap m_idlStructsToGenerate; QVector m_functionTopics; QVector m_externalTopicTypes; QVector m_customFunctions; QMap> m_tables; QMap> m_views; QVector m_enumerations; QString m_errorString; QMap> m_externalXmlInformations; QMap m_idlFiles; QMap m_xmlFiles; QMap m_usedServices; QMap m_fullServiceName2Abbreviation; QStringList m_groupNames; int m_prio; bool m_svcDevMode{false}; }; } // namespace CodeGen