/** * @RDE_HEADER@ * Read Xml service files * $Id$ * $HeadURL$ * $Author$ */ #pragma once #include #include #include #include #include #include #include #include "codegen_export.h" namespace NGL { class INGLLogger; } class QDomElement; namespace CodeGen { enum ExerciseDependency // bitfield { 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; // generate db functions 'selectByFoo()' and 'removeByFoo()' bool canBeNull = true; // currently not passed through from EA / xml bool hasSequence = false; bool isOptional = false; // when optional, than the type is a QVariant (and QVariant::null is NULL) int sequenceStart = 0; int sequenceIncrement = 0; }; struct IdlColumnInformation { QString name; QString type; //!< the idl data 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; // not yet processed - e.g. with datatype 'point_2d' 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; // parent class QString comment; bool isDataObject = false; // can be used as DWO/DRO bool dtsAutogen = true; // automatically generate DTS Impl bool dtcAutogen = true; // automatically generate DTC Impl bool recordTopic = false; // record topic for replay? bool routeToClient = true; // route Topic from server to client? bool routeToServer = false; // route Topic from client to server? bool routeInReplay = true; // route Topic in replay from exercise to replay (or vice-versa)? bool autosubscribe = true; // automatically call enableFoo() in DTC::enableAll() dds::core::xtypes::ExtensibilityKind extensibility = dds::core::xtypes::ExtensibilityKind::EXTENSIBLE; 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; } // service structs QMap getStruct2BaseClassRelations() const { return m_struct2BaseClass; } QVector getStructToGenerate() const { return m_structsToGenerate; } // idl structs 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; } // tables 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: 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 QVector &parts); static QString serviceNamespaceFromFile(const QString &fn); // The service name from the parsed xml file; QString m_svcNamespace; // Abbreviation of service name (inside xml file) QString m_svcAbbr; // Names for associated processes with this service (a single name in most cases) QStringList m_svcProcNames; // Extent the default Record/Replay plugin with own functions bool m_customRecordReplay; // depends this service on an exercise or is it a global on (or both) ExerciseDependency m_exerciseDependency{ExerciseDependency::Exercise}; // Mapping DBClass -> used tables QMap > m_dbClassTables; // structs to generate struct -> base class relation 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; // svcShortName, filename QMap m_xmlFiles; // svcShortName, filename QMap m_usedServices; QMap m_fullServiceName2Abbreviation; QStringList m_groupNames; int m_prio; bool m_svcDevMode{false}; NGL::INGLLogger &m_logger; }; } // namespace CodeGen