#pragma once #include "dtcore/inc/dtdefinitions.h" #include "dtcore/inc/dtstring.h" #include "dtcore/inc/dtvector.h" #include "dtcore/inc/dtmap.h" #include "dtcore/inc/dtresolvable.h" #include "dtcore/inc/dttemplatedescriptor.h" #include "dtcore/inc/dtchrono.h" namespace dt { #define DT_XML_ISSUE(id, node, msg) \ do \ { \ dt::String _msg; \ _msg << msg; \ node->AddIssue(dt::XmlIssue(id, _msg)); \ } while (0) #define DT_XML_DEPRECATED_NODE(id, node, name, msg) \ do \ { \ if (node->HasChildByName(name)) \ { \ dt::String _msg; \ _msg << "Child node '" << name << "' is deprecated. " << msg; \ node->AddIssue(dt::XmlIssue(id, _msg)); \ } \ } while (0) #define DT_XML_DEPRECATED_ATTRIBUTE(id, node, attribute, msg) \ do \ { \ if (node->HasAttribute(attribute)) \ { \ dt::String _msg; \ _msg << "Attribute '" << attribute << "' is deprecated. " << msg; \ node->AddIssue(dt::XmlIssue(id, _msg)); \ } \ } while (0) enum class XmlIssueId : int { // Errors ErrorFirst = 10000, // Agency Configuration ErrorAgencyResourcePlatformEmpty = 10000, ErrorAgencyResourceNameEmpty = 10001, ErrorAgencyResourceAvailabilityInvalid = 10002, // Farm Configuration ErrorFarmDatabaseMaxStorageSizeInvalid = 11000, ErrorFarmContactNotFound = 11001, ErrorFarmContactReferenceNotFound = 11002, ErrorFarmReportTemplateLoadingFailed = 11003, ErrorFarmVersionMatcherTitleModeInvalid = 11004, ErrorFarmVersionMatcherSortingOptionInvalid = 11005, ErrorFarmVersionMatcherSortingOptionColumnInvalid = 11006, ErrorFarmVersionMatcherSortingOptionOrderInvalid = 11007, ErrorFarmCloudStorageCannotCustomizeProjectDTest = 11008, ErrorFarmShareModeUnknown = 11009, ErrorFarmJiraPasswordUnresolved = 11010, ErrorFarmCloudStoragePasswordUnresolved = 11011, // Project Configuration ErrorProjectShellCommandExitCodeInvalid = 12000, ErrorProjectShellCommandFailMessageInvalid = 12001, ErrorProjectShellCommandProgressMessageInvalid = 12002, ErrorProjectShellCommandPrerequisiteInvalid = 12003, ErrorProjectShellCommandTypeInvalid = 12004, ErrorProjectShellCommandTypeEmpty = 12005, ErrorProjectShellCommandRunModeInvalid = 12006, ErrorProjectShellCommandFailureCategoryAndExitCodeSet = 12007, ErrorProjectShellCommandFailureFailureCategoryHealthRescheduleSet = 12008, ErrorProjectShellCommandStoredArtefactMaxSizeTooLarge = 12009, ErrorProjectShellCommandCommandOverridenForGlobalCommand = 12010, ErrorProjectShellCommandGlobalCreationFailed = 12011, ErrorProjectDeploymentDefaultDuplicate = 12012, ErrorProjectTokenLoanStrategyInvalid = 12013, ErrorProjectTokenCountOutOfRange = 12014, ErrorProjectTokenCounterButNoCount = 12015, ErrorProjectTokenStartButNoCount = 12016, ErrorProjectProfileDefaultDuplicate = 12017, ErrorProjectProfileNameEmpty = 12018, ErrorProjectCustomFailureCategoryBuiltInOverride = 12019, ErrorProjectCustomFailureCategoryPriorityInvalid = 12020, ErrorProjectCustomFailureCategoryRetryInvalid = 12021, ErrorProjectCustomFailureCategoryCompletionInvalid = 12022, ErrorProjectCustomFailureCategoryResourceHealthChangeInvalid = 12023, ErrorProjectTargetDefaultShellCommandRunModeInvalid = 12024, ErrorProjectExpectedIssueAgentInvalid = 12025, ErrorProjectExpectedIssueTryInvalid = 12026, ErrorProjectExpectedIssueTypeInvalid = 12027, //ErrorProjectTestDependencyMasterOrSubTest = 12028, // deleted ErrorProjectTestPrerequisiteNotFound = 12029, ErrorProjectTestNameContainsDots = 12030, ErrorProjectTestAlreadyDefined = 12031, ErrorProjectTestElevatedInvalid = 12032, ErrorProjectTestPrerequisiteModeInvalid = 12033, ErrorProjectTestMaintainerCantBeEmpty = 12034, ErrorProjectTestDependencyTargetMapOverrideUnspecified = 12035, ErrorProjectTestExecutionModeInvalid = 12036, ErrorProjectTestTokenNameEmpty = 12037, ErrorProjectTestScriptUserMappingInvalid = 12038, ErrorProjectTestTryModeInvalid = 12039, ErrorProjectTestAgentNeedInvalid = 12040, ErrorProjectTestAgentNeedTargetInvalid = 12041, ErrorProjectTestAgentNeedExclusiveModeInvalid = 12042, ErrorProjectSemaphoreReentranceInvalid = 12043, ErrorProjectSemaphoreTypeInvalid = 12044, ErrorProjectSemaphoreNameInvalid = 12045, ErrorProjectSuiteNotFound = 12046, ErrorProjectSuiteUseOnOutterFilter = 12047, ErrorProjectSuiteDuplicate = 12048, ErrorProjectSuiteFilterNameInvalid = 12049, ErrorProjectSuiteFilterTestNoFound = 12050, ErrorProjectSuiteFilterGenericInvalid = 12051, ErrorProjectSuiteFilterGenericAvailabilityInvalid = 12052, ErrorProjectContactReferenceNotFound = 12053, ErrorProjectBatchOutcomeModeInvalid = 12054, ErrorProjectBatchOutcomeWarningModeInvalid = 12055, ErrorProjectScriptFunctionCustomVariableNotAllowed = 12056, ErrorProjectTryModeInvalid = 12057, ErrorProjectNameInvalid = 12058, ErrorProjectPrerequisiteModeInvalid = 12059, ErrorProjectExecutionModeInvalid = 12060, ErrorProjectStoredArtefactMaxSizeTooLarge = 12061, ErrorProjectScriptDeclarationSourcePathNotProvided = 12062, ErrorProjectNewFileTemplateEmpty = 12063, ErrorProjectCustomSettingDefaultValueNewLine = 12064, ErrorProjectCustomSettingIdDuplicate = 12065, ErrorProjectCustomSettingTypeInvalid = 12066, ErrorProjectCustomSettingValueOnTypeInvalid = 12067, ErrorProjectCustomSettingValueWithNewLine = 12068, ErrorProjectCustomSettingComboBoxWithNoValue = 12069, ErrorProjectCustomSettingComboBoxDefaultValueInvalid = 12070, ErrorProjectQuarantineIssueIdNotFound = 12071, ErrorProjectQuarantineReasonNotFound = 12072, ErrorProjectTestNameEmpty = 12073, ErrorProjectSuiteMultipleFilters = 12074, ErrorProjectShellCommandArtefactTypeInvalid = 12075, ErrorProjectBloombergReportTypeInvalid = 12076, // Parser ErrorParserTemplateReferenceCircular = 13000, ErrorParserAttributeNotFound = 13001, ErrorParserAttributeUnknown = 13002, ErrorParserAttributeIntegerInvalid = 13003, ErrorParserAttributeFloatInvalid = 13004, ErrorParserNodeNotFound = 13005, ErrorParserNodeUnknown = 13006, ErrorParserIncludeFileNotFound = 13007, ErrorParserIncludeNoFileFound = 13008, ErrorParserIncludeInvalid = 13009, ErrorParserTemplateNotFound = 13010, ErrorParserTemplateDuplicateFound = 13011, ErrorParserTemplateDuplicateReferer = 13012, ErrorLast = 19999, // Warnings WarningFirst = 20000, // Agency Configuration WarningAgencyResourceMandatoryCapabilityDeprecated = 20000, // Farm Configuration WarningFarmDatabaseNameDeprecated = 21000, WarningFarmMaxTestQueueInspectionCountDeprecated = 21001, WarningFarmIncrementalSchedulingCountPerFrameDeprecated = 21002, WarningFarmVersionMatcherContactDeprecated = 21003, WarningFarmStartPortDeprecated = 21004, WarningFarmTCPPortDeprecated = 21005, WarningFarmJiraPasswordExplicit = 21006, // WarningFarmJiraPasswordUnresolved = 21007,, Moved to Error WarningFarmCloudStoragePasswordExplicit = 21008, // WarningFarmCloudStoragePasswordUnresolved = 21009, Moved to Error // Project Configuration WarningProjectShellCommandDeploymentFilterDeprecated = 22000, WarningProjectShellCommandIsAffectingResourceHealthOnFailureDeprecated = 22001, WarningProjectShellCommandRescheduleOnFailureDeprecated = 22001, WarningProjectVariableDeploymentFilterDeprecated = 22002, WarningProjectTestDependencyDeprecated = 22003, WarningProjectTestAgencyReservationPlatformDeprecated = 22004, WarningProjectTestNumAgentDeprecated = 22005, WarningProjectSuiteFilterNameDeprecated = 22006, WarningProjectTargetPackageShareTrustyNameDeprecated = 22007, WarningProjectTestManagementPasswordExplicit = 22008, WarningProjectTestManagementPasswordUnresolved = 22009, WarningProjectShellCommandArtefactTypeDeprecated = 22010, WarningProjectTestAgentNeedUseAllDeprecated = 22011, WarningLast = 29999 }; enum class XmlIssueType { Unknown, Error, Warning }; class XmlIssue { public: DT_CORE_DLL_ENTRY XmlIssue(XmlIssueId type, const String& header); DT_CORE_DLL_ENTRY XmlIssueType GetType() const; DT_CORE_DLL_ENTRY XmlIssueId GetId() const { return m_Id; } DT_CORE_DLL_ENTRY const String& GetHeader() const { return m_Header; } private: String m_Header; XmlIssueId m_Id; }; class XmlNode; typedef Vector XmlNodes; typedef Map XmlAttributes; class XmlNode : public Serializable { public: DT_CORE_DLL_ENTRY virtual ~XmlNode(){} DT_CORE_DLL_ENTRY virtual const String& GetName() const = 0; DT_CORE_DLL_ENTRY virtual const XmlNodes& GetChildren() const = 0; DT_CORE_DLL_ENTRY virtual bool HasChildByName(const String& name) const = 0; DT_CORE_DLL_ENTRY virtual bool GetChildrenByName(const String& name, XmlNodes& out) const = 0; DT_CORE_DLL_ENTRY virtual bool TryGetChildrenByName(const String& name, XmlNodes& out) const = 0; DT_CORE_DLL_ENTRY virtual bool GetFirstChildByName(const String& name, XmlNode*& out) const = 0; DT_CORE_DLL_ENTRY virtual bool TryGetFirstChildByName(const String& name, XmlNode*& out) const = 0; DT_CORE_DLL_ENTRY virtual bool TryGetFirstChildByFileNameAndLine(const String& originFile, int originLine, XmlNode*& out) const = 0; DT_CORE_DLL_ENTRY virtual bool HasAttribute(const String& name) const = 0; DT_CORE_DLL_ENTRY virtual bool GetAttribute(const String& name, String& out) const = 0; DT_CORE_DLL_ENTRY virtual bool GetAttribute(const String& name, U64& out) const = 0; DT_CORE_DLL_ENTRY virtual bool GetAttribute(const String& name, S64& out) const = 0; DT_CORE_DLL_ENTRY virtual bool GetAttribute(const String& name, int& out) const = 0; DT_CORE_DLL_ENTRY virtual bool GetAttribute(const String& name, float& out) const = 0; DT_CORE_DLL_ENTRY virtual bool GetAttribute(const String& name, bool& out) const = 0; template bool GetAttribute(const String& name, std::chrono::duration& out) const; template bool GetAttribute(const String& name, StrongType& out) const; DT_CORE_DLL_ENTRY virtual bool TryGetAttribute(const String& name, String& out, const String& defaultValue = String::Blank()) const = 0; DT_CORE_DLL_ENTRY virtual bool TryGetAttribute(const String& name, U64& out, U64 defaultValue = 0) const = 0; DT_CORE_DLL_ENTRY virtual bool TryGetAttribute(const String& name, S64& out, S64 defaultValue = 0) const = 0; DT_CORE_DLL_ENTRY virtual bool TryGetAttribute(const String& name, int& out, int defaultValue = 0) const = 0; DT_CORE_DLL_ENTRY virtual bool TryGetAttribute(const String& name, float& out, float defaultValue = 0.0f) const = 0; DT_CORE_DLL_ENTRY virtual bool TryGetAttribute(const String& name, bool& out, bool defaultValue = false) const = 0; template bool TryGetAttribute(const String& name, std::chrono::duration& out, std::chrono::duration defaultValue = std::chrono::duration::zero()) const; template bool TryGetAttribute(const String& name, StrongType& out, StrongType defaultValue = StrongType(0)) const; DT_CORE_DLL_ENTRY virtual const XmlAttributes& GetAttributes() const = 0; DT_CORE_DLL_ENTRY virtual const String& GetValue() const = 0; DT_CORE_DLL_ENTRY virtual void SetValue(const String& value) = 0; DT_CORE_DLL_ENTRY virtual bool HasValue() const = 0; DT_CORE_DLL_ENTRY virtual XmlNode* Clone() const = 0; DT_CORE_DLL_ENTRY virtual void MarkAsTouched() const = 0; DT_CORE_DLL_ENTRY virtual bool IsTouched() const = 0; DT_CORE_DLL_ENTRY virtual void MarkAsTouchedRecursive() = 0; DT_CORE_DLL_ENTRY virtual bool MarkUntouchedNodesAsError() = 0; DT_CORE_DLL_ENTRY virtual void GetLastErrorStrings(Strings& errors) const = 0; DT_CORE_DLL_ENTRY virtual void AddIssue(const XmlIssue& issue) = 0; DT_CORE_DLL_ENTRY virtual void GetLastWarningStrings(Strings& warnings) const = 0; DT_CORE_DLL_ENTRY virtual String ToString() const = 0; DT_CORE_DLL_ENTRY virtual String ToStringWithLocations() const = 0; DT_CORE_DLL_ENTRY virtual int GetLine() const = 0; DT_CORE_DLL_ENTRY virtual const String& GetFilename() const = 0; }; template inline bool XmlNode::GetAttribute(const String& name, std::chrono::duration& out) const { S64 value; if (GetAttribute(name, value)) { out = std::chrono::duration(value); return true; } return false; } template inline bool XmlNode::GetAttribute(const String& name, StrongType& out) const { T value; if (GetAttribute(name, value)) { out = StrongType(value); return true; } return false; } template inline bool XmlNode::TryGetAttribute(const String& name, std::chrono::duration& out, std::chrono::duration defaultValue) const { S64 value; if (TryGetAttribute(name, value)) { out = std::chrono::duration(value); return true; } else { out = defaultValue; return false; } } template inline bool XmlNode::TryGetAttribute(const String& name, StrongType& out, StrongType defaultValue) const { T value; if (TryGetAttribute(name, value)) { out = StrongType(value); return true; } else { out = defaultValue; return false; } } class XmlDocument : public Resolvable { public: DT_CORE_DLL_ENTRY XmlDocument(XmlNode* root = nullptr); DT_CORE_DLL_ENTRY virtual ~XmlDocument(); DT_CORE_DLL_ENTRY XmlDocument(const XmlDocument& doc); DT_CORE_DLL_ENTRY XmlDocument& operator=(const XmlDocument& doc); DT_CORE_DLL_ENTRY XmlNode* GetRoot() const; DT_CORE_DLL_ENTRY void Move(XmlNode* root); DT_CORE_DLL_ENTRY void Merge(const XmlNode* rhs, bool addSourceFirst = false); DT_CORE_DLL_ENTRY void Swap(XmlDocument& other); DT_CORE_DLL_ENTRY bool Empty() const; DT_CORE_DLL_ENTRY virtual String GetDecoratedName() const override; DT_CORE_DLL_ENTRY virtual const String& GetOriginFile() const override { return m_Root ? m_Root->GetFilename() : String::Blank(); } DT_CORE_DLL_ENTRY virtual int GetOriginLine() const override { return m_Root ? m_Root->GetLine() : 0; } DT_CORE_DLL_ENTRY virtual void Serialize(U8 version, Stream& stream) override; private: XmlNode* m_Root; }; DT_CORE_DLL_ENTRY String& operator<<(String& out, const XmlDocument& doc); class XmlParserImpl; enum class XmlParserResult { FileNoFound, Failed, Success }; class XmlParser { public: DT_CORE_DLL_ENTRY XmlParser(); DT_CORE_DLL_ENTRY ~XmlParser(); // Load and parse the specific XML document. // Note: This method will resolve nodes DT_CORE_DLL_ENTRY XmlParserResult Load(const String& filename); // Parse the given XML string // Note: This method will *not* resolve nodes DT_CORE_DLL_ENTRY XmlParserResult Parse(const String& xmlStr); DT_CORE_DLL_ENTRY void Clear(); DT_CORE_DLL_ENTRY const String& GetFilename() const; DT_CORE_DLL_ENTRY const XmlDocument& GetDocument() const; DT_CORE_DLL_ENTRY void Swap(XmlDocument& other); DT_CORE_DLL_ENTRY const TemplateDescriptors& GetTemplateDeclarations() const; DT_CORE_DLL_ENTRY const TemplateDescriptors& GetTemplateReferences() const; DT_CORE_DLL_ENTRY Strings GetFileReferences() const; DT_CORE_DLL_ENTRY String GetLastErrorString() const; DT_CORE_DLL_ENTRY String GetLastWarningString() const; private: XmlParserImpl* m_Impl; XmlParserResult ValidateParsedDocument(XmlParserResult parsingResult, const XmlDocument& document); }; }