2660 lines
140 KiB
C#
2660 lines
140 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Xml;
|
|
using System.Globalization;
|
|
using System.Reflection;
|
|
using System.Text.RegularExpressions;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
using C4IT.Logging;
|
|
using C4IT.XML;
|
|
using C4IT.Configuration;
|
|
using C4IT.FASD.Base;
|
|
using static C4IT.Logging.cLogManager;
|
|
|
|
namespace C4IT.DataHistoryProvider
|
|
{
|
|
public enum eDataHistoryOrigin
|
|
{
|
|
Unknown = 0,
|
|
Main = 1,
|
|
F4sdAgent = 2,
|
|
NexthinkNxql = 3,
|
|
ActiveDirectory = 4,
|
|
AzureAD = 5,
|
|
M42Wpm = 6,
|
|
Intune= 7,
|
|
Citrix = 8
|
|
}
|
|
|
|
public enum eDataHistoryTableCached { Default = 0, Yes = 1, No = 2 };
|
|
|
|
public enum eDataHistoryQueryType { Query = 0, Static = 1 }
|
|
|
|
public enum eDataHistoryAggregationType
|
|
{
|
|
Unknown = 0,
|
|
first = 1,
|
|
min = 2,
|
|
max = 3,
|
|
sum = 4,
|
|
average = 5,
|
|
count = 6,
|
|
valuecount = 7,
|
|
latestValue = 8,
|
|
latestTime = 9
|
|
}
|
|
|
|
public class cDataHistoryConfigClusters : cFasdBaseConfig
|
|
{
|
|
public static bool confUseBinValuesAsPrimaryKey = true;
|
|
|
|
public const string constFileNameF4sdConfig = "F4SD-DataClusters-Configuration.xml";
|
|
private const string constFileNameF4sdSchema = "F4SD-DataClusters-Configuration.xsd";
|
|
private const string constConfigRootElement = "F4SD-DataClusters-Configuration";
|
|
|
|
public static readonly Guid ConfigId = new Guid("28C26B80-C3E9-43E1-934E-57B7C2DBC374");
|
|
|
|
public Guid getId() { return ConfigId; }
|
|
|
|
public Dictionary<string, cDataHistoryConfigCluster> Clusters { get; private set; } = null;
|
|
|
|
public cDataHistoryConfigCluster MainCluster { get; private set; } = null;
|
|
|
|
public readonly Dictionary<string, cDataHistoryConfigTable> Tables = new Dictionary<string, cDataHistoryConfigTable>();
|
|
|
|
public readonly Dictionary<string, string> AlternateTableNames = new Dictionary<string, string>();
|
|
|
|
internal cDataHistoryConfigClusters() :
|
|
base(constFileNameF4sdConfig, constFileNameF4sdSchema, constConfigRootElement)
|
|
{
|
|
}
|
|
|
|
public override bool InstantiateProperties(XmlElement XRoot, cXmlParser Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
MainCluster = new cDataHistoryConfigClusterMain(XRoot, this, Parser);
|
|
if (MainCluster == null)
|
|
{
|
|
Parser.AddMessage(XRoot, @"No valid main cluster were found in the configuration.", LogLevels.Fatal);
|
|
return false;
|
|
}
|
|
|
|
Clusters = cDataHistoryConfigCluster.LoadFromXml(XRoot, this, Parser);
|
|
if (Clusters == null)
|
|
{
|
|
Parser.AddMessage(XRoot, @"No valid clusters were found in the configuration.", LogLevels.Fatal);
|
|
return false;
|
|
}
|
|
|
|
Clusters.Add(MainCluster.Name, MainCluster);
|
|
|
|
// resolve the references
|
|
var _IsValid = true;
|
|
foreach (var Cluster in Clusters.Values)
|
|
foreach (var Table in Cluster.Tables.Values)
|
|
IsValid &= Table.ResolveReferences(Tables, Parser);
|
|
|
|
IsValid = _IsValid;
|
|
return true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override bool DoXmlUpdates(XmlElement XmlRoot, bool withM42Config = false, bool withIntuneConfig = false, bool withMobileDeviceConfig = false, bool withCitrixConfig = false)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
|
|
var RetVal = false;
|
|
try
|
|
{
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, ""
|
|
, "DataCluster[@Name='Main-ComputerInfo']"
|
|
, "<DataCluster Name=\"Main-ComputerInfo\" Origin=\"Main\" InformationClass=\"Computer\"/>"
|
|
, "InformationClasses"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='Main-ComputerInfo']"
|
|
, "Table[@Name='main-computer-quickaction-details']"
|
|
, "<Table Name=\"main-computer-quickaction-details\" SourceName=\"main-computer-quickaction\" Type=\"Events\" Key=\"DeviceId\" EventTimeCol=\"Start\" Cached=\"Yes\" LateDelivery=\"true\"><Table-Columns><Table-Column Name=\"DeviceId\" Type=\"guid\"/><Table-Column Name=\"Start\" Type=\"datetime\"/><Table-Column Name=\"Finish\" Type=\"datetime\"/><Table-Column Name=\"QActionName\" Type=\"string\" Cardinal=\"100\"/><Table-Column Name=\"ResultType\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"ExecutionType\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"Parameters\" Type=\"string\"/><Table-Column Name=\"Result\" Type=\"string\"/><Table-Column Name=\"ErrorCode\" Type=\"int\"/><Table-Column Name=\"ErrorDescription\" Type=\"string\"/></Table-Columns><AutoCreate-Historic-Table Name=\"main-computer-quickaction-history\"/></Table>"
|
|
, ""
|
|
);
|
|
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "AD-UserInfo", "ad-user", "<Table-Column Name=\"domainDns\" SourceType =\"Static\" Type=\"string\" Cardinal=\"128\"/>", "account");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "AD-UserInfo", "ad-user", "<Table-Column Name=\"domainNB\" SourceType =\"Static\" Type=\"string\" Cardinal=\"16\"/>", "account");
|
|
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "AD-ComputerInfo", "ad-computer", "<Table-Column Name=\"domainDns\" SourceType =\"Static\" Type=\"string\" Cardinal=\"128\"/>", "account");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "AD-ComputerInfo", "ad-computer", "<Table-Column Name=\"domainNB\" SourceType =\"Static\" Type=\"string\" Cardinal=\"16\"/>", "account");
|
|
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"DeviceActivity\" SourceName=\"Device Activity\" Type=\"bigint\" Aggregation=\"sum\"/>");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"UserActivity\" SourceName=\"User Activity\" Type=\"bigint\" Aggregation=\"sum\"/>");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"ProcessorTaskManager\" SourceName=\"Task Manager % Score\" Type=\"float\" Aggregation=\"average\" LateDelivery=\"true\" />");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"CPUSpeed\" SourceName=\"CPU Speed\" Type=\"float\" Aggregation=\"average\" LateDelivery=\"true\" />");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"CPUBaseSpeed\" SourceName=\"CPU Base Speed\" Type=\"float\" Aggregation=\"average\" LateDelivery=\"true\" />");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"ProzessorHighEvents\" SourceName=\"Prozessor High Events\" Type=\"datetime\" Aggregation=\"count\" />");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"LoginDuration\" SourceName=\"Login Duration\" Type=\"bigint\" Aggregation=\"max\" />");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-DeviceInfo", "agnt-computer-event-numerical", "<Table-Column Name=\"ExtendedLoginDuration\" SourceName=\"Extended Login Duration\" Type=\"bigint\" Aggregation=\"max\" />");
|
|
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "Agent-UserInfo", "agnt-user", "<Table-Column Name=\"accountType\" SourceType =\"Static\" Type=\"string\" Cardinal=\"16\"/>");
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot,
|
|
"DataCluster[@Name='Agent-DeviceInfo']/Table[@Name='agnt-computer-event-numerical']",
|
|
"AdditionalTableName[@Name='agnt-computer-event-numerical-latest']",
|
|
"<AdditionalTableName Name =\"agnt-computer-event-numerical-latest\"/>",
|
|
"Table-Columns");
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot,
|
|
"DataCluster[@Name='Agent-DeviceInfo']/Table[@Name='agnt-computer-event-string']",
|
|
"AdditionalTableName[@Name='agnt-computer-event-string-latest']",
|
|
"<AdditionalTableName Name =\"agnt-computer-event-string-latest\"/>",
|
|
"Table-Columns");
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='Agent-DeviceInfo']"
|
|
, "Table[@Name='agnt-computer-event-details-processorTaskManager']"
|
|
, "<Table Name=\"agnt-computer-event-details-processorTaskManager\" Type=\"Events\" Key=\"id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"id\" SourceName=\"DEVICECODE\" Type=\"int\" /><Table-Column Name=\"event\" SourceName=\"Task Manager % Score\" Type=\"string\" /><Table-Column Name=\"time\" SourceName=\"EVENTDATE\" Type=\"datetime\" /><Table-Column Name=\"Duration\" SourceName=\"DURATION\" Type=\"bigint\" /><Table-Column Name=\"Value\" SourceName=\"VALUE\" Type=\"float\" /></Table-Columns></Table>"
|
|
, "Table[@Name='agnt-computer-event-details-processorUsage']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='Agent-DeviceInfo']"
|
|
, "Table[@Name='agnt-computer-event-details-processorTaskManager']"
|
|
, "<Table Name=\"agnt-computer-event-details-processorTaskManager\" Type=\"Events\" Key=\"id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"id\" SourceName=\"DEVICECODE\" Type=\"int\" /><Table-Column Name=\"event\" SourceName=\"Task Manager % Score\" Type=\"string\" /><Table-Column Name=\"time\" SourceName=\"EVENTDATE\" Type=\"datetime\" /><Table-Column Name=\"Duration\" SourceName=\"DURATION\" Type=\"bigint\" /><Table-Column Name=\"Value\" SourceName=\"VALUE\" Type=\"float\" /></Table-Columns></Table>"
|
|
, "Table[@Name='agnt-computer-event-details-processorUsage']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='Agent-DeviceInfo']"
|
|
, "Table[@Name='agnt-computer-event-details-CPUSpeed']"
|
|
, "<Table Name=\"agnt-computer-event-details-CPUSpeed\" Type=\"Events\" Key=\"id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"id\" SourceName=\"DEVICECODE\" Type=\"int\" /><Table-Column Name=\"event\" SourceName=\"CPU Speed\" Type=\"string\" /><Table-Column Name=\"time\" SourceName=\"EVENTDATE\" Type=\"datetime\" /><Table-Column Name=\"Duration\" SourceName=\"DURATION\" Type=\"bigint\" /><Table-Column Name=\"Value\" SourceName=\"VALUE\" Type=\"float\" /></Table-Columns></Table>"
|
|
, "Table[@Name='agnt-computer-event-details-processorTaskManager']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='Agent-DeviceInfo']"
|
|
, "Table[@Name='agnt-computer-event-details-ProzessorHighEvents']"
|
|
, "<Table Name=\"agnt-computer-event-details-ProzessorHighEvents\" Type=\"Events\" Key=\"id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"id\" SourceName=\"DEVICECODE\" Type=\"int\" /><Table-Column Name=\"event\" SourceName=\"Prozessor High Events\" Type=\"string\" /><Table-Column Name=\"time\" SourceName=\"EVENTDATE\" Type=\"datetime\" /><Table-Column Name=\"Duration\" SourceName=\"DURATION\" Type=\"bigint\" /><Table-Column Name=\"Value\" SourceName=\"VALUE\" Type=\"float\" /></Table-Columns></Table>"
|
|
, "Table[@Name='agnt-computer-event-details-CPUSpeed']"
|
|
);
|
|
if (withIntuneConfig)
|
|
{
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, ""
|
|
, "DataCluster[@Name='IntuneDeviceInfo']"
|
|
, "<DataCluster Name=\"IntuneDeviceInfo\" Origin=\"Intune\" InformationClass=\"Computer\"/>"
|
|
, "DataCluster[@Name='AD-ComputerInfo']"
|
|
);
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='IntuneDeviceInfo']"
|
|
, "Table[@Name='intune-deviceInfo']"
|
|
, "<Table Name=\"intune-deviceInfo\" Type=\"Static\" Key=\"id\"><Table-Columns><Table-Column Name=\"id\" Type=\"guid\"/><Table-Column Name=\"complianceState\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"userPrincipalName\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"managementState\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"userDisplayName\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"lastSyncDateTime\" Type=\"string\" Cardinal=\"64\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, ""
|
|
, "DataCluster[@Name='IntuneUserInfo']"
|
|
, "<DataCluster Name=\"IntuneUserInfo\" Origin=\"Intune\" InformationClass=\"User\"/>"
|
|
, "DataCluster[@Name='IntuneDeviceInfo']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='IntuneUserInfo']"
|
|
, "Table[@Name='intune-userDeviceCount']"
|
|
, "<Table Name=\"intune-userDeviceCount\" Type=\"Static\" Key=\"id\"><Table-Columns><Table-Column Name=\"id\" Type=\"guid\"/><Table-Column Name=\"windows\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"iOS\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"android\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"linux\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"macOs\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"total\" Type=\"int\" Default=\"0\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='IntuneUserInfo']"
|
|
, "Table[@Name='intune-userDeviceCount-details']"
|
|
, "<Table Name=\"intune-userDeviceCount-details\" Type=\"StaticDetails\" Key=\"id\"><Table-Columns><Table-Column Name=\"id\" Type=\"guid\"/><Table-Column Name=\"deviceName\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"model\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"operatingSystem\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"serialNumber\" Type=\"string\" Cardinal=\"64\"/></Table-Columns></Table>"
|
|
);
|
|
}
|
|
|
|
if (withIntuneConfig && withMobileDeviceConfig)
|
|
{
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, ""
|
|
, "DataCluster[@Name='IntuneMobileDeviceInfo']"
|
|
, "<DataCluster Name=\"IntuneMobileDeviceInfo\" Origin=\"Intune\" InformationClass=\"MobileDevice\"/>"
|
|
, "DataCluster[@Name='IntuneUserInfo']"
|
|
);
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='IntuneMobileDeviceInfo']"
|
|
, "Table[@Name='intune-mobile-deviceInfo']"
|
|
, "<Table Name=\"intune-mobile-deviceInfo\" Type=\"Static\" Key=\"id\"><Table-Columns><Table-Column Name=\"id\" Type=\"guid\"/><Table-Column Name=\"complianceState\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"userPrincipalName\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"managementState\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"userDisplayName\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"lastSyncDateTime\" Type=\"datetime\"/><Table-Column Name=\"deviceName\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"deviceRegistrationState\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"deviceType\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"easDeviceId\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"enrolledDateTime\" Type=\"datetime\"/><Table-Column Name=\"enrollmentProfileName\" Type=\"string\" Cardinal=\"128\"/><Table-Column Name=\"freeStorageSpaceInBytes\" Type=\"bigint\"/><Table-Column Name=\"imei\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"isEncrypted\" Type=\"boolean\"/><Table-Column Name=\"isSupervised\" Type=\"boolean\"/><Table-Column Name=\"jailBroken\" Type=\"boolean\"/><Table-Column Name=\"lostModeState\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"managedDeviceOwnerType\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"managementAgent\" Type=\"string\" Cardinal=\"16\"/><Table-Column Name=\"managementCertificateExpirationDate\" Type=\"datetime\"/><Table-Column Name=\"manufacturer\" Type=\"string\" Cardinal=\"128\"/><Table-Column Name=\"model\" Type=\"string\" Cardinal=\"128\"/><Table-Column Name=\"operatingSystem\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"osVersion\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"ownerType\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"phoneNumber\" Type=\"string\" Cardinal=\"32\"/><Table-Column Name=\"physicalMemoryInBytes\" Type=\"bigint\"/><Table-Column Name=\"serialNumber\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"subscriberCarrier\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"totalStorageSpaceInBytes\" Type=\"bigint\"/><Table-Column Name=\"wiFiMacAddress\" Type=\"string\" Cardinal=\"32\"/></Table-Columns></Table>"
|
|
);
|
|
}
|
|
|
|
if (withCitrixConfig)
|
|
{
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, ""
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "<DataCluster Name=\"citrixMetrics\" Origin=\"Citrix\" InformationClass=\"VirtualSession\"/>"
|
|
, "DataCluster[@Name='AD-ComputerInfo']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session']"
|
|
, "<Table Name=\"citrix-session\" Type=\"Static\" Key=\"Id\"><Table-Columns><Table-Column Name=\"Id\" SourceName=\"SessionKey\" Type=\"guid\"/><Table-Column Name=\"StartDate\" Type=\"datetime\"/><Table-Column Name=\"EndDate\" Type=\"datetime\"/><Table-Column Name=\"LogOnDuration\" Type=\"int\"/><Table-Column Name=\"ConnectionState\" Type=\"int\" Cardinal=\"64\"/><Table-Column Name=\"EndpointName\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"IsAnonymous\" Type=\"boolean\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-metrics']"
|
|
, "<Table Name=\"citrix-session-metrics\" Type=\"History\" Key=\"Id\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"CollectedDate\" Type=\"datetime\"/><Table-Column Name=\"IcaRttMS\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"IcaLatency\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"ClientL7Latency\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"ServerL7Latency\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"ConnectionState\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"InputBandwidthUsed\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"OutputBandwidthUsed\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"OutputBandwidthAvailable\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"Fps\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"InputFps\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"OutputFps\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"WanLatency\" Type=\"int\" Aggregation=\"average\"/><Table-Column Name=\"DcLatency\" Type=\"int\" Aggregation=\"average\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-icaRttMS']"
|
|
, "<Table Name=\"citrix-session-details-icaRttMS\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"IcaRttMS\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-icaLatency']"
|
|
, "<Table Name=\"citrix-session-details-icaLatency\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"IcaLatency\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-clientL7Latency']"
|
|
, "<Table Name=\"citrix-session-details-clientL7Latency\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"ClientL7Latency\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-serverL7Latency']"
|
|
, "<Table Name=\"citrix-session-details-serverL7Latency\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"ServerL7Latency\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-inputBandwidthUsed']"
|
|
, "<Table Name=\"citrix-session-details-inputBandwidthUsed\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"InputBandwidthUsed\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-outputBandwidthAvailable']"
|
|
, "<Table Name=\"citrix-session-details-outputBandwidthAvailable\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"OutputBandwidthAvailable\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-fps']"
|
|
, "<Table Name=\"citrix-session-details-fps\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"Fps\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-inputFps']"
|
|
, "<Table Name=\"citrix-session-details-inputFps\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"InputFps\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-outputFps']"
|
|
, "<Table Name=\"citrix-session-details-outputFps\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"OutputFps\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-wanLatency']"
|
|
, "<Table Name=\"citrix-session-details-wanLatency\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"WanLatency\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-details-dcLatency']"
|
|
, "<Table Name=\"citrix-session-details-dcLatency\" Type=\"Events\" Key=\"Id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"Id\" Type=\"int\"/><Table-Column Name=\"Value\" SourceName=\"DcLatency\" Type=\"int\"/><Table-Column Name=\"time\" SourceName=\"CollectedDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-machine']"
|
|
, "<Table Name=\"citrix-session-machine\" Type=\"Static\" Key=\"Id\"><Table-Columns><Table-Column Name=\"Id\" Type=\"guid\"/><Table-Column Name=\"Name\" Type=\"string\"/><Table-Column Name=\"CatalogName\" SourceName=\"Catalog\" SourceJsonField=\"Name\" Type=\"string\" Default=\"0\"/><Table-Column Name=\"AllocationType\" SourceName=\"Catalog\" SourceJsonField=\"AllocationType\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"DesktopGroupName\" SourceName=\"DesktopGroup\" SourceJsonField=\"Name\" Type=\"string\"/><Table-Column Name=\"DnsName\" Type=\"string\"/><Table-Column Name=\"HostedMachine\" SourceName=\"HostedMachineId\" Type=\"string\"/><Table-Column Name=\"IPAddress\" Type=\"string\"/><Table-Column Name=\"WindowsConnectionSetting\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"CurrentRegistrationState\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"AgentVersion\" Type=\"string\"/><Table-Column Name=\"CurrentSessionCount\" Type=\"int\"/><Table-Column Name=\"OSType\" Type=\"string\"/><Table-Column Name=\"IsInMaintenanceMode\" Type=\"boolean\"/><Table-Column Name=\"Cpu\" SourceName=\"CurrentLoadIndex\" SourceJsonField=\"Cpu\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"Memory\" SourceName=\"CurrentLoadIndex\" SourceJsonField=\"Memory\" Type=\"int\" Default=\"0\"/><Table-Column Name=\"Disk\" SourceName=\"CurrentLoadIndex\" SourceJsonField=\"Disk\" Type=\"int\" Default=\"0\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-user']"
|
|
, "<Table Name=\"citrix-session-user\" Type=\"Static\" Key=\"Id\"><Table-Columns><Table-Column Name=\"Id\" Type=\"guid\"/><Table-Column Name=\"UserName\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"FullName\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"Domain\" Type=\"string\" Cardinal=\"64\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-connection']"
|
|
, "<Table Name=\"citrix-session-connection\" Type=\"Static\" Key=\"Id\"><Table-Columns><Table-Column Name=\"Id\" Type=\"guid\"/><Table-Column Name=\"LogOnStartDate\" Type=\"datetime\"/><Table-Column Name=\"LogOnEndDate\" Type=\"datetime\"/><Table-Column Name=\"BrokeringDuration\" Type=\"int\"/><Table-Column Name=\"VMStartStartDate\" Type=\"datetime\"/><Table-Column Name=\"VMStartEndDate\" Type=\"datetime\"/><Table-Column Name=\"HdxStartDate\" Type=\"datetime\"/><Table-Column Name=\"HdxEndDate\" Type=\"datetime\"/><Table-Column Name=\"AuthenticationDuration\" Type=\"int\"/><Table-Column Name=\"GpoStartDate\" Type=\"datetime\"/><Table-Column Name=\"GpoEndDate\" Type=\"datetime\"/><Table-Column Name=\"LogOnScriptsStartDate\" Type=\"datetime\"/><Table-Column Name=\"LogOnScriptsEndDate\" Type=\"datetime\"/><Table-Column Name=\"ProfileLoadStartDate\" Type=\"datetime\"/><Table-Column Name=\"ProfileLoadEndDate\" Type=\"datetime\"/><Table-Column Name=\"InteractiveStartDate\" Type=\"datetime\"/><Table-Column Name=\"InteractiveEndDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='citrixMetrics']"
|
|
, "Table[@Name='citrix-session-currentConnection']"
|
|
, "<Table Name=\"citrix-session-currentConnection\" Type=\"Static\" Key=\"Id\"><Table-Columns><Table-Column Name=\"Id\" Type=\"guid\"/><Table-Column Name=\"ClientName\" Type=\"string\"/><Table-Column Name=\"ClientAddress\" Type=\"string\"/><Table-Column Name=\"ClientVersion\" Type=\"string\"/><Table-Column Name=\"ClientPlatform\" Type=\"string\"/><Table-Column Name=\"ConnectedViaIPAddress\" Type=\"string\"/><Table-Column Name=\"LaunchedViaHostName\" Type=\"string\"/><Table-Column Name=\"LogOnStartDate\" Type=\"datetime\"/><Table-Column Name=\"LogOnEndDate\" Type=\"datetime\"/><Table-Column Name=\"BrokeringDuration\" Type=\"int\"/><Table-Column Name=\"VMStartStartDate\" Type=\"datetime\"/><Table-Column Name=\"VMStartEndDate\" Type=\"datetime\"/><Table-Column Name=\"HdxStartDate\" Type=\"datetime\"/><Table-Column Name=\"HdxEndDate\" Type=\"datetime\"/><Table-Column Name=\"AuthenticationDuration\" Type=\"int\"/><Table-Column Name=\"GpoStartDate\" Type=\"datetime\"/><Table-Column Name=\"GpoEndDate\" Type=\"datetime\"/><Table-Column Name=\"LogOnScriptsStartDate\" Type=\"datetime\"/><Table-Column Name=\"LogOnScriptsEndDate\" Type=\"datetime\"/><Table-Column Name=\"ProfileLoadStartDate\" Type=\"datetime\"/><Table-Column Name=\"ProfileLoadEndDate\" Type=\"datetime\"/><Table-Column Name=\"InteractiveStartDate\" Type=\"datetime\"/><Table-Column Name=\"InteractiveEndDate\" Type=\"datetime\"/><Table-Column Name=\"UserInitStartDate\" Type=\"datetime\"/><Table-Column Name=\"UserInitEndDate\" Type=\"datetime\"/><Table-Column Name=\"AppxAssociationStartDate\" Type=\"datetime\"/><Table-Column Name=\"AppxAssociationEndDate\" Type=\"datetime\"/><Table-Column Name=\"AppxLoadPackageStartDate\" Type=\"datetime\"/><Table-Column Name=\"AppxLoadPackageEndDate\" Type=\"datetime\"/></Table-Columns></Table>"
|
|
);
|
|
|
|
|
|
}
|
|
|
|
if (withM42Config)
|
|
{
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, ""
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "<DataCluster Name=\"M42Tickets\" Origin=\"M42Wpm\" InformationClass=\"Ticket\" Description=\"Ticket & incident data from Matrix42 Workplace Management\"/>"
|
|
, "DataCluster[@Name='AD-ComputerInfo']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "Table[@Name='M42Wpm-Tickets']"
|
|
, "<Table Name=\"M42Wpm-Tickets\" Type=\"Static\" Key=\"id\"><Table-Columns><Table-Column Name=\"id\" SourceName=\"TicketObjectId\" Type=\"guid\"/><Table-Column Name=\"name\" SourceName=\"Name\" Type=\"string\" Cardinal =\"10\"/><Table-Column Name=\"Summary\" Type=\"string\" Cardinal =\"1024\"/><Table-Column Name=\"Status\" Type=\"string\" Cardinal =\"64\"/><Table-Column Name=\"StatusId\" Type=\"int\"/><Table-Column Name=\"AssetCIName\" Type=\"string\" Cardinal =\"64\"/><Table-Column Name=\"AssetName\" Type=\"string\" Cardinal =\"64\"/><Table-Column Name=\"AffectedUserId\" Type=\"guid\"/><Table-Column Name=\"AssetId\" Type=\"guid\"/><Table-Column Name=\"CreationDate\" Type=\"datetime\"/><Table-Column Name=\"ClosingDate\" Type=\"datetime\"/><Table-Column Name=\"CreationSourceId\" Type=\"int\"/><Table-Column Name=\"CreationSource\" Type=\"string\" Cardinal =\"256\"/><Table-Column Name=\"Description\" Type=\"string\"/><Table-Column Name=\"DescriptionHtml\" Type=\"string\"/><Table-Column Name=\"Solution\" Type=\"string\"/><Table-Column Name=\"SolutionHtml\" Type=\"string\" IsWritable=\"true\"/><Table-Column Name=\"PriorityId\" Type=\"int\"/><Table-Column Name=\"Priority\" Type=\"string\" Cardinal =\"256\"/><Table-Column Name=\"CategoryId\" Type=\"guid\"/><Table-Column Name=\"Category\" Type=\"string\" Cardinal =\"256\"/><Table-Column Name=\"CategoryHierarchical\" Type=\"string\" Cardinal =\"1024\"/><Table-Column Name=\"CIName\" Type=\"string\" Cardinal =\"64\"/><Table-Column Name=\"DirectLinkEdit\" Type=\"string\" Cardinal =\"1024\"/><Table-Column Name=\"AssetCIId\" Type=\"guid\"/><Table-Column Name=\"AssetSKUAssetGroupId\" Type=\"int\"/><Table-Column Name=\"AssetSKUAssetGroup\" Type=\"string\" Cardinal =\"256\"/><Table-Column Name=\"AssetSKUTypeId\" Type=\"int\"/><Table-Column Name=\"AssetSKUType\" Type=\"string\" Cardinal =\"256\"/><Table-Column Name=\"DirectLinkPreview\" Type=\"string\" Cardinal =\"1024\"/><Table-Column Name=\"DirectLinkClose\" Type=\"string\" Cardinal =\"1024\"/><Table-Column Name=\"AffectedUser\" Type=\"string\" Cardinal =\"256\"/><Table-Column Name=\"Urgency\" Type=\"string\" Cardinal=\"64\" /><Table-Column Name=\"UrgencyId\" Type=\"int\" /><Table-Column Name=\"Impact\" Type=\"string\" Cardinal=\"64\" /><Table-Column Name=\"ImpactId\" Type=\"int\" /></Table-Columns></Table>"
|
|
, "-first-"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "Table[@Name='M42Wpm-Ticket-History']"
|
|
, "<Table Name=\"M42Wpm-Ticket-History\" Type=\"HistoryEvents\" Key=\"id\" EventTimeCol=\"time\"><Table-Columns><Table-Column Name=\"id\" SourceName=\"ActivityObjectId\" Type=\"guid\"/><Table-Column Name=\"time\" SourceName=\"CreationDate\" Type=\"datetime\"/><Table-Column Name=\"CreatedBy\" Type=\"string\" Cardinal=\"64\"/><Table-Column Name=\"Header\" Type=\"string\" Cardinal=\"1024\"/><Table-Column Name=\"Description\" Type=\"string\"/><Table-Column Name=\"DescriptionHtml\" Type=\"string\"/><Table-Column Name=\"IsVisibleForUser\" Type=\"boolean\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Tickets']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "Table[@Name='M42Wpm-Ticket-Services']"
|
|
, "<Table Name=\"M42Wpm-Ticket-Services\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSArticleClassBase\" EntityTypeNames=\"SPSArticleTypeService SPSArticleTypeGroup SVCServiceTypeBundle SVCServiceTypeConfigGroup\" OrderBy=\"\" WhereExpression=\"\" /><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"SysName\" SourceName=\"Sys-Name\" Type=\"string\" Cardinal=\"50\"/><Table-Column Name=\"PortalName\" Type=\"string\" Cardinal =\"300\"/><Table-Column Name=\"Name\" Type=\"string\" Cardinal =\"300\"/><Table-Column Name=\"Status\" Type=\"string\" Cardinal =\"50\"/><Table-Column Name=\"ServiceType\" Type=\"int\"/><Table-Column Name=\"Contact\" Type=\"string\" Cardinal=\"1024\"/><Table-Column Name=\"TechnicalOwner\" Type=\"string\" Cardinal=\"1024\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Ticket-History']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "Table[@Name='M42Wpm-Ticket-Assets']"
|
|
, "<Table Name=\"M42Wpm-Ticket-Assets\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSAssetClassBase\" EntityTypeNames=\"SPSComputerType SPSMonitorType SPSPrinterType SPSAssetTypeMobile SPSAssetTypeSIM SPSAssetTypeGenericPeripheralDevice SPSAssetTypeNetworkDevice SPSAssetType\" OrderBy=\"\" WhereExpression=\"\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"SysName\" SourceName=\"Sys-Name\" Type=\"string\" Cardinal=\"50\"/><Table-Column Name=\"Asset\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"AssetName\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Host\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"InventoryNumber\" Type=\"string\" Cardinal=\"100\"/><Table-Column Name=\"AssetAssignedUser\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"AssetSKUManName\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"AssetSKUModel\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"SerialNumber\" Type=\"string\" Cardinal=\"100\"/><Table-Column Name=\"CostCenter\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Location\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"OrganizationalUnit\" Type=\"string\" Cardinal=\"300\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Ticket-Services']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "Table[@Name='M42Wpm-Ticket-QuickCalls']"
|
|
, "<Table Name=\"M42Wpm-Ticket-QuickCalls\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSQuickCallClassBase\" EntityTypeNames=\"SPSQuickCallType\" OrderBy=\"\" WhereExpression=\"Restricted = 0\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"SysName\" SourceName=\"Sys-Name\" Type=\"string\" Cardinal=\"50\"/><Table-Column Name=\"Name\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Subject\" Type=\"string\" Cardinal=\"1024\"/><Table-Column Name=\"Priority\" Type=\"string\" Cardinal=\"100\"/><Table-Column Name=\"Responsible\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"ResponsibleRole\" Type=\"string\" Cardinal=\"300\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Ticket-Assets']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "Table[@Name='M42Wpm-Ticket-Categories']"
|
|
, "<Table Name=\"M42Wpm-Ticket-Categories\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSScCategoryClassBase\" EntityTypeNames=\"SPSScCategoryType\" OrderBy=\"\" WhereExpression=\"Hidden = 0\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"SysName\" SourceName=\"Sys-Name\" Type=\"string\" Cardinal=\"50\"/><Table-Column Name=\"Name\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"parent\" SourceName=\"Parent_Value\" Type=\"guid\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Ticket-QuickCalls']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "Table[@Name='M42Wpm-Ticket-SLAs']"
|
|
, "<Table Name=\"M42Wpm-Ticket-SLAs\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SVCServiceLevelAgreementClassBase\" EntityTypeNames=\"\" OrderBy=\"\" WhereExpression=\"\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"SysName\" SourceName=\"Sys-Name\" Type=\"string\" Cardinal=\"50\"/><Table-Column Name=\"ContractNumber\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Summary\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Responsible\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"EffectiveDate\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"ExpireDate\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"State\" Type=\"string\" Cardinal=\"300\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Ticket-Categories']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "Table[@Name='M42Wpm-Ticket-CloseCase-Services']"
|
|
, "<Table Name=\"M42Wpm-Ticket-CloseCase-Services\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSArticleClassBase\" EntityTypeNames=\"SPSArticleTypeService SPSArticleTypeGroup SVCServiceTypeBundle SVCServiceTypeConfigGroup\" OrderBy=\"\" WhereExpression=\"EXISTS(SUBQUERY(SVCServiceBookingClassBase AS B, B.ID, base.ID = B.Service AND B.ProvisioningStatus = 1 AND b.Uninstalled = 0 AND b.OrderType <> 20 AND B.Consumer.Accounts.T(SPSAccountClassAD).ADCn = '{0}'))\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"DisplayName\" SourceName=\"Sys-DisplayName\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Name\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"ServiceID\" SourceName=\"ArticleID\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Description\" Type=\"string\" Cardinal=\"300\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Ticket-SLAs']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "Table[@Name='M42Wpm-Ticket-Roles']"
|
|
, "<Table Name=\"M42Wpm-Ticket-Roles\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSScRoleClassBase\" EntityTypeNames=\"SPSSecurityTypeRole\" OrderBy=\"\" WhereExpression=\"T(SPSSecurityClassRole).ShowInForwardAction = 1 AND T(SPSSecurityClassRole).Queue.ID IS NULL\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"Name\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Description\" Type=\"string\" Cardinal=\"300\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Ticket-CloseCase-Services']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
, "Table[@Name='M42Wpm-Ticket-Persons']"
|
|
, "<Table Name=\"M42Wpm-Ticket-Persons\" Type=\"Selection\" Key=\"id\"><Matrix42-DataQueryItems-Template EntityClassName=\"SPSUserClassBase\" EntityTypeNames=\"\" OrderBy=\"\" WhereExpression=\"(EXISTS(SUBQUERY(SPSSecurityClassRole as Role, Role.ID, Role.ID='6167BCDB-9A7D-4736-B215-4218FB64360D' and Role.ShowInForwardAction = 1)) OR MemberOf.ShowInForwardAction = 1) AND MemberOf.Queue.ID IS NULL AND T(SPSCommonClassBase).State = 2023\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Id\" Type=\"guid\"/><Table-Column Name=\"SysObjectId\" SourceName=\"Sys-ObjectId\" Type=\"guid\"/><Table-Column Name=\"LastName\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"FirstName\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"MailAddress\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"BusinessPhone\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"MobilePhone\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"CostCenter\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Organization\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Location\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Position\" Type=\"string\" Cardinal=\"300\"/><Table-Column Name=\"Status\" Type=\"string\" Cardinal=\"300\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Ticket-Roles']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, ""
|
|
, "DataCluster[@Name='M42UserInfo']"
|
|
, "<DataCluster Name=\"M42UserInfo\" Origin=\"M42Wpm\" InformationClass=\"User\" Description=\"User related data from Matrix42 Workplace Management\"/>"
|
|
, "DataCluster[@Name='M42Tickets']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42UserInfo']"
|
|
, "Table[@Name='M42Wpm-User-NewTicket']"
|
|
, "<Table Name=\"M42Wpm-User-NewTicket\" Type=\"Static\" Key=\"id\"><Table-Columns><Table-Column Name=\"id\" Type=\"sid\"/><Table-Column Name=\"Link\" Type=\"string\" Cardinal =\"1024\"/><Table-Column Name=\"SubjectParameter\" Type=\"string\" Cardinal =\"128\"/><Table-Column Name=\"DescriptionParameter\" Type=\"string\" Cardinal =\"128\"/></Table-Columns></Table>"
|
|
, "-first-"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42UserInfo']"
|
|
, "Table[@Name='M42Wpm-Pickup-TicketStatus']"
|
|
, "<Table Name=\"M42Wpm-Pickup-TicketStatus\" Type=\"Static\" Key=\"id\"><Matrix42-Pickup-Template PickupName=\"SPSCommonPickupObjectStatus\" FilteredGroup=\"7\" Sorting=\"byPosition\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Value\" Type=\"int\"/><Table-Column Name=\"name\" SourceName=\"DisplayString\" Type=\"string\" Cardinal =\"150\"/><Table-Column Name=\"hidden\" SourceName =\"Hidden\" Type=\"boolean\"/><Table-Column Name=\"position\" SourceName =\"Position\" Type=\"int\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-User-NewTicket']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42UserInfo']"
|
|
, "Table[@Name='M42Wpm-Pickup-IncidentNotificationMode']"
|
|
, "<Table Name=\"M42Wpm-Pickup-IncidentNotificationMode\" Type=\"Static\" Key=\"id\"><Matrix42-Pickup-Template PickupName=\"SVMIncidentPickupSendNotifications\" Sorting=\"byName\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Value\" Type=\"int\"/><Table-Column Name=\"name\" SourceName=\"DisplayString\" Type=\"string\" Cardinal =\"150\"/><Table-Column Name=\"hidden\" SourceName =\"Hidden\" Type=\"boolean\"/><Table-Column Name=\"position\" SourceName =\"Position\" Type=\"int\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Pickup-TicketStatus']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42UserInfo']"
|
|
, "Table[@Name='M42Wpm-Pickup-TicketTypes']"
|
|
, "<Table Name=\"M42Wpm-Pickup-TicketTypes\" Type=\"Static\" Key=\"id\"><Matrix42-Pickup-Template PickupName=\"SPSTicketPickupType\" Sorting=\"byPosition\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Value\" Type=\"int\"/><Table-Column Name=\"name\" SourceName=\"DisplayString\" Type=\"string\" Cardinal =\"150\"/><Table-Column Name=\"hidden\" SourceName =\"Hidden\" Type=\"boolean\"/><Table-Column Name=\"position\" SourceName =\"Position\" Type=\"int\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Pickup-IncidentNotificationMode']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42UserInfo']"
|
|
, "Table[@Name='M42Wpm-Pickup-ActivityImpact']"
|
|
, "<Table Name=\"M42Wpm-Pickup-ActivityImpact\" Type=\"Static\" Key=\"id\"><Matrix42-Pickup-Template PickupName=\"SVMActivityPickupImpact\" Sorting=\"byPosition\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Value\" Type=\"int\"/><Table-Column Name=\"name\" SourceName=\"DisplayString\" Type=\"string\" Cardinal =\"150\"/><Table-Column Name=\"hidden\" SourceName =\"Hidden\" Type=\"boolean\"/><Table-Column Name=\"position\" SourceName =\"Position\" Type=\"int\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Pickup-TicketTypes']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42UserInfo']"
|
|
, "Table[@Name='M42Wpm-Pickup-IncidentEntry']"
|
|
, "<Table Name=\"M42Wpm-Pickup-IncidentEntry\" Type=\"Static\" Key=\"id\"><Matrix42-Pickup-Template PickupName=\"SPSActivityIncidentPickupEntry\" Sorting=\"byPosition\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Value\" Type=\"int\"/><Table-Column Name=\"name\" SourceName=\"DisplayString\" Type=\"string\" Cardinal =\"150\"/><Table-Column Name=\"hidden\" SourceName =\"Hidden\" Type=\"boolean\"/><Table-Column Name=\"position\" SourceName =\"Position\" Type=\"int\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Pickup-ActivityImpact']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42UserInfo']"
|
|
, "Table[@Name='M42Wpm-Pickup-ActivityUrgency']"
|
|
, "<Table Name=\"M42Wpm-Pickup-ActivityUrgency\" Type=\"Static\" Key=\"id\"><Matrix42-Pickup-Template PickupName=\"SVMActivityPickupUrgency\" Sorting=\"byPosition\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Value\" Type=\"int\"/><Table-Column Name=\"name\" SourceName=\"DisplayString\" Type=\"string\" Cardinal =\"150\"/><Table-Column Name=\"hidden\" SourceName =\"Hidden\" Type=\"boolean\"/><Table-Column Name=\"position\" SourceName =\"Position\" Type=\"int\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Pickup-IncidentEntry']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42UserInfo']"
|
|
, "Table[@Name='M42Wpm-Pickup-ActivityErrorType']"
|
|
, "<Table Name=\"M42Wpm-Pickup-ActivityErrorType\" Type=\"Static\" Key=\"id\"><Matrix42-Pickup-Template PickupName=\"SVMActivityPickupErrorType\" Sorting=\"byPosition\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Value\" Type=\"int\"/><Table-Column Name=\"name\" SourceName=\"DisplayString\" Type=\"string\" Cardinal =\"150\"/><Table-Column Name=\"hidden\" SourceName =\"Hidden\" Type=\"boolean\"/><Table-Column Name=\"position\" SourceName =\"Position\" Type=\"int\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Pickup-ActivityUrgency']"
|
|
);
|
|
|
|
RetVal |= DoXmlInsertElement(XmlRoot
|
|
, "DataCluster[@Name='M42UserInfo']"
|
|
, "Table[@Name='M42Wpm-Pickup-ObjectStateReason']"
|
|
, "<Table Name=\"M42Wpm-Pickup-ObjectStateReason\" Type=\"Static\" Key=\"id\"><Matrix42-Pickup-Template PickupName=\"SPSCommonPickupObjectStateReason\" Sorting=\"byPosition\"/><Table-Columns><Table-Column Name=\"id\" SourceName=\"Value\" Type=\"int\"/><Table-Column Name=\"name\" SourceName=\"DisplayString\" Type=\"string\" Cardinal =\"150\"/><Table-Column Name=\"hidden\" SourceName =\"Hidden\" Type=\"boolean\"/><Table-Column Name=\"position\" SourceName =\"Position\" Type=\"int\"/><Table-Column Name=\"state\" SourceName =\"State\" Type=\"int\"/><Table-Column Name=\"stategroup\" SourceName =\"StateGroup\" Type=\"int\"/></Table-Columns></Table>"
|
|
, "Table[@Name='M42Wpm-Pickup-ActivityErrorType']"
|
|
);
|
|
|
|
}
|
|
|
|
// update table 'M42Wpm-Tickets' columns
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"Urgency\" Type=\"string\" Cardinal=\"64\"/>", "AffectedUser");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"UrgencyId\" Type=\"int\"/>", "Urgency");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"Impact\" Type=\"string\" Cardinal=\"64\"/>", "UrgencyId");
|
|
RetVal |= DoXmlInsertTableRow(XmlRoot, "M42Tickets", "M42Wpm-Tickets", "<Table-Column Name=\"ImpactId\" Type=\"int\"/>", "Impact");
|
|
|
|
// correct the type attribute for the M42Wpm-Ticket-History table to Events
|
|
var M42JournalItemNode = XmlRoot.SelectSingleNode("DataCluster[@Name='M42Tickets']/Table[@Name='M42Wpm-Ticket-History' and @Type!='HistoryEvents']") as XmlElement;
|
|
if (M42JournalItemNode != null)
|
|
{
|
|
M42JournalItemNode.SetAttribute("Type", "HistoryEvents");
|
|
RetVal = true;
|
|
}
|
|
}
|
|
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
return RetVal;
|
|
}
|
|
|
|
public static enumFasdValueType ResultingAggregationType(enumFasdValueType vt, eDataHistoryAggregationType at)
|
|
{
|
|
switch (at)
|
|
{
|
|
case eDataHistoryAggregationType.count:
|
|
case eDataHistoryAggregationType.valuecount:
|
|
return enumFasdValueType.INT;
|
|
case eDataHistoryAggregationType.latestTime:
|
|
return enumFasdValueType.DATETIME;
|
|
case eDataHistoryAggregationType.sum:
|
|
if (vt == enumFasdValueType.VERSION)
|
|
return enumFasdValueType.STRING;
|
|
return vt;
|
|
}
|
|
return vt;
|
|
}
|
|
|
|
public static string GetSqlDataTypeFromHistoryType(enumFasdValueType type, int Cardinal, bool isBinaryType = false)
|
|
{
|
|
try
|
|
{
|
|
if (isBinaryType)
|
|
{
|
|
switch (type)
|
|
{
|
|
case enumFasdValueType.VERSION:
|
|
return "[varbinary](10)";
|
|
case enumFasdValueType.MD5:
|
|
return "[binary](16)";
|
|
case enumFasdValueType.SID:
|
|
return "[varbinary](68)";
|
|
case enumFasdValueType.IPV4:
|
|
return "[binary](4)";
|
|
case enumFasdValueType.IPV6:
|
|
return "[binary](16)";
|
|
}
|
|
return null;
|
|
}
|
|
switch (type)
|
|
{
|
|
case enumFasdValueType.STRING:
|
|
if (Cardinal <= 0 || Cardinal >= 4000)
|
|
return string.Format("[nvarchar](max)", Cardinal);
|
|
return string.Format("[nvarchar]({0})", Cardinal);
|
|
case enumFasdValueType.GUID:
|
|
return "[uniqueidentifier]";
|
|
case enumFasdValueType.INT:
|
|
return "[int]";
|
|
case enumFasdValueType.BIGINT:
|
|
return "[bigint]";
|
|
case enumFasdValueType.FLOAT:
|
|
return "[float]";
|
|
case enumFasdValueType.DATETIME:
|
|
return "[datetime]";
|
|
case enumFasdValueType.VERSION:
|
|
return "[nvarchar](50)";
|
|
case enumFasdValueType.MD5:
|
|
return "[nvarchar](50)";
|
|
case enumFasdValueType.SID:
|
|
return "[nvarchar](200)";
|
|
case enumFasdValueType.IPV4:
|
|
return "[nvarchar](50)";
|
|
case enumFasdValueType.IPV6:
|
|
return "[nvarchar](50)";
|
|
case enumFasdValueType.TEXT:
|
|
return "[ntext]";
|
|
case enumFasdValueType.BOOLEAN:
|
|
return "[tinyint]";
|
|
}
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static bool CheckColumnCompatibility(cDataHistoryConfigColumnBase C1, cDataHistoryConfigColumnBase C2)
|
|
{
|
|
try
|
|
{
|
|
var strC1 = C1.SqlType;
|
|
var strC2 = C2.SqlType;
|
|
if (confUseBinValuesAsPrimaryKey && C1.SqlTypeBin != null && C2.SqlTypeBin != null)
|
|
{
|
|
strC1 = C1.SqlTypeBin;
|
|
strC2 = C2.SqlTypeBin;
|
|
}
|
|
|
|
|
|
return strC1 == strC2;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public class cDataHistoryConfigCluster : IConfigNodeNamed
|
|
{
|
|
public bool IsValid { get; protected set; } = false;
|
|
public string Name { get; protected set; } = null;
|
|
public string Description { get; protected set; } = null;
|
|
|
|
[JsonIgnore]
|
|
public cDataHistoryConfigClusters ParentConfig { get; protected set; } = null;
|
|
|
|
public eDataHistoryOrigin Origin { get; protected set; } = eDataHistoryOrigin.Unknown;
|
|
|
|
public enumFasdInformationClass InformationClass { get; protected set; } = enumFasdInformationClass.Unknown;
|
|
|
|
public Dictionary<string, cDataHistoryConfigTable> Tables { get; protected set; } = null;
|
|
|
|
internal cDataHistoryConfigCluster()
|
|
{
|
|
}
|
|
|
|
internal cDataHistoryConfigCluster(XmlElement XNode, cDataHistoryConfigClusters Config, cXmlParser Parser)
|
|
{
|
|
try
|
|
{
|
|
if (Config == null)
|
|
{
|
|
var E = new Exception("No valid configuration");
|
|
LogException(E, LogLevels.Fatal);
|
|
return;
|
|
}
|
|
|
|
ParentConfig = Config;
|
|
|
|
Name = cXmlParser.GetStringFromXmlAttribute(XNode, "Name");
|
|
if (string.IsNullOrEmpty(Name))
|
|
{
|
|
Parser.AddMessage(XNode, "The <DataCluster> element has no valid Name attribute.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
Origin = cXmlParser.GetEnumFromAttribute<eDataHistoryOrigin>(XNode, "Origin", eDataHistoryOrigin.Unknown);
|
|
if (Origin == eDataHistoryOrigin.Unknown)
|
|
{
|
|
Parser.AddMessage(XNode, $"The <DataCluster> element with Name='{Name}' has no valid 'Type' attribute.", LogLevels.Error);
|
|
return;
|
|
}
|
|
|
|
InformationClass = cXmlParser.GetEnumFromAttribute<enumFasdInformationClass>(XNode, "InformationClass", enumFasdInformationClass.Unknown);
|
|
if (InformationClass == enumFasdInformationClass.Unknown)
|
|
{
|
|
Parser.AddMessage(XNode, $"The <DataCluster> element with Name='{Name}' has no valid 'InformationClass' attribute.", LogLevels.Error);
|
|
return;
|
|
}
|
|
|
|
Description = cXmlParser.GetStringFromXmlAttribute(XNode, "Description");
|
|
|
|
Tables = cDataHistoryConfigTable.LoadFromXml(XNode, this, Parser);
|
|
if (Tables == null)
|
|
{
|
|
Parser.AddMessage(XNode, $"No valid tables found in <DataCluster> element with Name='{Name}'.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
}
|
|
|
|
internal static Dictionary<string, cDataHistoryConfigCluster> LoadFromXml(XmlElement XNode, cDataHistoryConfigClusters Config, cXmlParser Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
var XDataClusters = XNode.SelectNodes("DataCluster");
|
|
if (XDataClusters == null || XDataClusters.Count <= 0)
|
|
{
|
|
Parser.AddMessage(XNode, "The <DataCluster> element could not be found in the configuration.", LogLevels.Fatal);
|
|
return null;
|
|
}
|
|
|
|
Parser.EnterElement("DataCluster");
|
|
var RetVal = new Dictionary<string, cDataHistoryConfigCluster>(XDataClusters.Count);
|
|
try
|
|
{
|
|
foreach (XmlNode XNode2 in XDataClusters)
|
|
{
|
|
if (!(XNode2 is XmlElement XDataCluster))
|
|
continue;
|
|
|
|
var DataCluster = new cDataHistoryConfigCluster(XDataCluster, Config, Parser);
|
|
if ((DataCluster != null) && (DataCluster.IsValid))
|
|
{
|
|
if (!RetVal.ContainsKey(DataCluster.Name))
|
|
RetVal.Add(DataCluster.Name, DataCluster);
|
|
else
|
|
Parser.AddMessage(XDataCluster, $"There's already an <DataCluster> element with Name='{DataCluster.Name}'", LogLevels.Warning);
|
|
}
|
|
else
|
|
{
|
|
var strN = "";
|
|
if (DataCluster != null)
|
|
strN = $" with Name='{DataCluster.Name}'";
|
|
Parser.AddMessage(XDataCluster, $"The <DataCluster> element{strN} is not valid.", LogLevels.Error);
|
|
}
|
|
Parser.SelectElementNext();
|
|
}
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
Parser.LeaveElement("DataCluster");
|
|
}
|
|
|
|
if (RetVal.Count > 0)
|
|
return RetVal;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigClusterMain : cDataHistoryConfigCluster
|
|
{
|
|
public readonly Dictionary<enumFasdInformationClass, cDataHistoryConfigMainTable> MainTables = null;
|
|
|
|
internal cDataHistoryConfigClusterMain(XmlElement XRoot, cDataHistoryConfigClusters Config, cXmlParser Parser)
|
|
{
|
|
try
|
|
{
|
|
if (Config == null)
|
|
{
|
|
var E = new Exception("No valid configuration");
|
|
LogException(E, LogLevels.Fatal);
|
|
return;
|
|
}
|
|
|
|
IsValid = true;
|
|
Name = "Main";
|
|
Origin = eDataHistoryOrigin.Main;
|
|
InformationClass = enumFasdInformationClass.Main;
|
|
|
|
ParentConfig = Config;
|
|
|
|
var XNode = XRoot.SelectSingleNode("InformationClasses") as XmlElement;
|
|
if (XNode == null)
|
|
{
|
|
Parser.AddMessage(XNode, $"No valid <InformationClasses> element found.", LogLevels.Error);
|
|
return;
|
|
}
|
|
|
|
Parser.EnterElement("InformationClasses");
|
|
try
|
|
{
|
|
Tables = cDataHistoryConfigTable.LoadFromXml(XNode, this, Parser);
|
|
if (Tables == null)
|
|
{
|
|
Parser.AddMessage(XNode, $"No valid tables found in <DataCluster> element with Name='{Name}'.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Parser.LeaveElement("InformationClasses");
|
|
}
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public class cDataHistoryConfigTable : IConfigNodeNamed
|
|
{
|
|
public bool IsValid { get; protected set; } = false;
|
|
public string Name { get; protected set; } = null;
|
|
public string SourceName { get; protected set; } = null;
|
|
public string Description { get; protected set; } = null;
|
|
|
|
public bool LateDelivery { get; set; } = false;
|
|
public bool HasLateDelivery { get; private set; } = false;
|
|
|
|
public string AutoCreateHistoryTableName { get; private set; } = null;
|
|
|
|
public bool IsBuildInTable { get; private set; } = false;
|
|
|
|
public eDataHistoryTableCached Cached { get; set; } = eDataHistoryTableCached.Default;
|
|
|
|
public bool IsVirtual { get; set; } = false;
|
|
|
|
[JsonIgnore]
|
|
public cDataHistoryConfigCluster ParentCluster { get; private set; } = null;
|
|
|
|
public eDataHistoryTableType Type { get; private set; } = eDataHistoryTableType.Unknown;
|
|
|
|
[JsonIgnore]
|
|
public readonly List<cDataHistoryConfigColumnBase> KeyColumns = null;
|
|
public readonly List<string> KeyColumnNames = null;
|
|
|
|
[JsonIgnore]
|
|
public cDataHistoryConfigColumnBase EventTimeColumn { get; private set; } = null;
|
|
public string EventTimeColumnName { get; private set; } = null;
|
|
|
|
|
|
public readonly Dictionary<string, cDataHistoryConfigSubTable> SubTables = null;
|
|
|
|
public readonly Dictionary<string, cDataHistoryConfigColumnBase> Columns = new Dictionary<string, cDataHistoryConfigColumnBase>();
|
|
|
|
public readonly Dictionary<string, cDataHistoryConfigTableIndex> Indexes = new Dictionary<string, cDataHistoryConfigTableIndex>();
|
|
|
|
public readonly Dictionary<string, cDataHistoryConfigTableReferenceInfo> References = new Dictionary<string, cDataHistoryConfigTableReferenceInfo>();
|
|
|
|
public readonly bool NoTimeRestriction = false;
|
|
|
|
public List<string> AlternateNames = null;
|
|
|
|
[JsonIgnore]
|
|
public bool HasScanId = false;
|
|
|
|
internal cDataHistoryConfigTable()
|
|
{
|
|
KeyColumns = new List<cDataHistoryConfigColumnBase>();
|
|
KeyColumnNames = new List<string>();
|
|
SubTables = new Dictionary<string, cDataHistoryConfigSubTable>();
|
|
Columns = new Dictionary<string, cDataHistoryConfigColumnBase>();
|
|
}
|
|
|
|
internal cDataHistoryConfigTable(XmlElement XNode, cDataHistoryConfigCluster Cluster, cXmlParser Parser)
|
|
{
|
|
try
|
|
{
|
|
if (Cluster == null)
|
|
{
|
|
LogException(new Exception("no valid Cluster information delivered."));
|
|
return;
|
|
}
|
|
|
|
|
|
ParentCluster = Cluster;
|
|
|
|
if (Cluster.Origin == eDataHistoryOrigin.Main && XNode.Name == "InformationClass")
|
|
IsBuildInTable = true;
|
|
|
|
if (Cluster.Origin == eDataHistoryOrigin.F4sdAgent || Cluster.Origin == eDataHistoryOrigin.M42Wpm || Cluster.Origin == eDataHistoryOrigin.Intune || Cluster.Origin == eDataHistoryOrigin.Citrix)
|
|
IsVirtual = true;
|
|
|
|
Name = cXmlParser.GetStringFromXmlAttribute(XNode, "Name");
|
|
if (string.IsNullOrEmpty(Name))
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> has no valid 'Name' attribute.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
if (IsBuildInTable)
|
|
Name = "main-" + Name.ToLowerInvariant();
|
|
|
|
SourceName = cXmlParser.GetStringFromXmlAttribute(XNode, "SourceName");
|
|
if (string.IsNullOrEmpty(SourceName))
|
|
SourceName = Name;
|
|
|
|
Cached = cXmlParser.GetEnumFromAttribute<eDataHistoryTableCached>(XNode, "Cached", eDataHistoryTableCached.Default);
|
|
|
|
string strKeyColumnNames = cXmlParser.GetStringFromXmlAttribute(XNode, "Key");
|
|
if (IsBuildInTable)
|
|
strKeyColumnNames = "id";
|
|
else
|
|
strKeyColumnNames = cXmlParser.GetStringFromXmlAttribute(XNode, "Key");
|
|
if (string.IsNullOrEmpty(strKeyColumnNames))
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> with Name='{Name}' has no valid 'Key' attribute.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
var arrKeyColumnNames = strKeyColumnNames.Split(' ');
|
|
KeyColumnNames = new List<string>();
|
|
foreach (var Entry in arrKeyColumnNames)
|
|
{
|
|
var strName = Entry.Trim();
|
|
if (!string.IsNullOrEmpty(strName))
|
|
KeyColumnNames.Add(strName);
|
|
}
|
|
if (KeyColumnNames.Count == 0)
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> with Name='{Name}' is not valid because of an empty 'Key' attribute.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
if (IsBuildInTable)
|
|
Type = eDataHistoryTableType.Static;
|
|
else
|
|
Type = cXmlParser.GetEnumFromAttribute<eDataHistoryTableType>(XNode, "Type", eDataHistoryTableType.Unknown);
|
|
|
|
if (Type == eDataHistoryTableType.Unknown)
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> with Name='{Name}' has no valid 'Type' attribute.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
EventTimeColumnName = cXmlParser.GetStringFromXmlAttribute(XNode, "EventTimeCol");
|
|
|
|
Description = cXmlParser.GetStringFromXmlAttribute(XNode, "Description");
|
|
|
|
LateDelivery = cXmlParser.GetBoolFromXmlAttribute(XNode, "LateDelivery");
|
|
|
|
var XNode2 = XNode.SelectSingleNode("AutoCreate-Historic-Table");
|
|
if (XNode2 != null)
|
|
{
|
|
Parser.EnterElement("AutoCreate-Historic-Table");
|
|
AutoCreateHistoryTableName = cXmlParser.GetStringFromXmlAttribute(XNode2, "Name");
|
|
Parser.LeaveElement("AutoCreate-Historic-Table");
|
|
}
|
|
if (XNode.Name == "JoinedTable")
|
|
{
|
|
// we have a table definition with several subtables
|
|
var XSubTables = XNode.SelectNodes("SubTable");
|
|
if ((XSubTables == null) || XSubTables.Count == 0)
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> has no valid subtables.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
SubTables = new Dictionary<string, cDataHistoryConfigSubTable>(XSubTables.Count);
|
|
Parser.EnterElement("SubTable");
|
|
try
|
|
{
|
|
foreach (XmlNode XEntry in XSubTables)
|
|
{
|
|
if (!(XEntry is XmlElement XSubTable))
|
|
continue;
|
|
|
|
var SubTable = new cDataHistoryConfigSubTable(XSubTable, this, Parser);
|
|
if ((SubTable == null) || !SubTable.IsValid || SubTables.ContainsKey(SubTable.Name))
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XSubTable.Name}> is not valid.", LogLevels.Warning);
|
|
}
|
|
else
|
|
SubTables.Add(SubTable.Name, SubTable);
|
|
|
|
Parser.SelectElementNext();
|
|
}
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
Parser.LeaveElement("SubTable");
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// we have no explicit subtable definitions
|
|
var SubTable = new cDataHistoryConfigSubTable(XNode, this, Parser);
|
|
if ((SubTable == null) || !SubTable.IsValid)
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> is not valid.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
SubTables = new Dictionary<string, cDataHistoryConfigSubTable>(1)
|
|
{
|
|
{ SubTable.Name, SubTable }
|
|
};
|
|
}
|
|
if (SubTables.Count == 0)
|
|
{
|
|
Parser.AddMessage(XNode, $"The table <{XNode.Name}> has no valid subtables.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
// get the key columns
|
|
KeyColumns = new List<cDataHistoryConfigColumnBase>();
|
|
foreach (var ColName in KeyColumnNames)
|
|
{
|
|
if (!Columns.TryGetValue(ColName, out var KeyColumn))
|
|
{
|
|
Parser.AddMessage(XNode, $"The key column name '{ColName}' within the element <{XNode.Name}> could not be found.", LogLevels.Error);
|
|
return;
|
|
}
|
|
KeyColumns.Add(KeyColumn);
|
|
}
|
|
|
|
// check if we have the key columns in each subtable with the same type
|
|
foreach (var SubTable in SubTables.Values)
|
|
{
|
|
HasLateDelivery |= SubTable.HasLateDelivery;
|
|
|
|
foreach (var KeyColumn in KeyColumns)
|
|
{
|
|
if (!SubTable.Columns.TryGetValue(KeyColumn.Name, out var Col))
|
|
{
|
|
Parser.AddMessage(XNode, $"The key column '{KeyColumn.Name}' within the element <{XNode.Name}> could not be found in subtable '{SubTable.Name}'.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
if (Col.ValueType != KeyColumn.ValueType)
|
|
{
|
|
Parser.AddMessage(XNode, $"The value type of the key column '{KeyColumn.Name}' within the element <{XNode.Name}> is not compatible to the subtable '{SubTable.Name}'.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
if (Col.Cardinal != KeyColumn.Cardinal)
|
|
{
|
|
Parser.AddMessage(XNode, $"The value cardinal of the key column '{KeyColumn.Name}' within the element <{XNode.Name}> is not compatible to the subtable '{SubTable.Name}'.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// get the event time column for event tables
|
|
if (!string.IsNullOrEmpty(EventTimeColumnName))
|
|
if (Columns.TryGetValue(EventTimeColumnName, out var _ec) && _ec.ValueType == enumFasdValueType.DATETIME)
|
|
EventTimeColumn = _ec;
|
|
|
|
if (Type == eDataHistoryTableType.Events || Type == eDataHistoryTableType.HistoryEvents)
|
|
{
|
|
if (EventTimeColumn == null)
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> with Name='{Name}' has no valid 'EventTimeCol' attribute.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
// get the alternatetable names
|
|
var XAlternates = XNode.SelectNodes("AdditionalTableName");
|
|
if (XAlternates != null && XAlternates.Count > 0)
|
|
{
|
|
Parser.EnterElement("AdditionalTableName");
|
|
foreach (XmlNode XEntry in XAlternates)
|
|
{
|
|
if (!(XEntry is XmlElement XAlternate))
|
|
continue;
|
|
|
|
try
|
|
{
|
|
var _an = cXmlParser.GetStringFromXmlAttribute(XAlternate, "Name");
|
|
if (string.IsNullOrWhiteSpace(_an))
|
|
continue;
|
|
|
|
if (AlternateNames == null)
|
|
AlternateNames = new List<string>(XAlternates.Count);
|
|
if (!AlternateNames.Contains(_an))
|
|
AlternateNames.Add(_an);
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
Parser.SelectElementNext();
|
|
}
|
|
}
|
|
Parser.LeaveElement("AdditionalTableName");
|
|
}
|
|
|
|
// get the indexes
|
|
var XIndexes = XNode.SelectNodes("Table-Index");
|
|
if (XIndexes != null && XIndexes.Count > 0)
|
|
{
|
|
Parser.EnterElement("Table-Index");
|
|
foreach (XmlNode XEntry in XIndexes)
|
|
{
|
|
if (!(XEntry is XmlElement XIndex))
|
|
continue;
|
|
|
|
try
|
|
{
|
|
var Index = new cDataHistoryConfigTableIndex
|
|
{
|
|
Name = XIndex.GetAttribute("Name")
|
|
};
|
|
if (string.IsNullOrEmpty(Index.Name))
|
|
{
|
|
Parser.AddMessage(XIndex, $"The element <{XIndex.Name}> has no valid 'Name' attribute.", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
Index.Unique = cXmlParser.GetBoolFromXmlAttribute(XIndex, "Unique");
|
|
|
|
var strColumns = XIndex.GetAttribute("Columns");
|
|
if (string.IsNullOrEmpty(strColumns))
|
|
{
|
|
Parser.AddMessage(XIndex, $"The element <{XIndex.Name}> with Name='{Index.Name}' has no valid 'Columns' attribute.", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
var arrCols = strColumns.Split(' ');
|
|
foreach (var strCol in arrCols)
|
|
{
|
|
var strCol2 = strCol.Trim();
|
|
if (strCol2 == "")
|
|
continue;
|
|
|
|
if (!Columns.TryGetValue(strCol2, out var Col))
|
|
{
|
|
Parser.AddMessage(XIndex, $"The element <{XIndex.Name}> with Name='{Index.Name}' contains a non existing element '{strCol2}' within the 'Columns' attribute.", LogLevels.Warning);
|
|
Index.Columns.Clear();
|
|
break;
|
|
}
|
|
|
|
if (Index.Columns.Contains(Col))
|
|
{
|
|
Parser.AddMessage(XIndex, $"The element <{XIndex.Name}> with Name='{Index.Name}' contains a duplicated element '{strCol2}' within the 'Columns' attribute.", LogLevels.Warning);
|
|
Index.Columns.Clear();
|
|
break;
|
|
}
|
|
|
|
Index.Columns.Add(Col);
|
|
}
|
|
|
|
if (Columns.Count == 0)
|
|
{
|
|
Parser.AddMessage(XIndex, $"The element <{XIndex.Name}> with Name='{Index.Name}' has an illegal or no valid entries in the 'Columns' attribute.", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
if (Indexes.ContainsKey(Index.Name))
|
|
{
|
|
Parser.AddMessage(XIndex, $"The element <{XIndex.Name}> with Name='{Index.Name}' is duplicated.", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
Indexes.Add(Index.Name, Index);
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
Parser.SelectElementNext();
|
|
}
|
|
}
|
|
|
|
Parser.LeaveElement("Table-Index");
|
|
}
|
|
|
|
// get the table references
|
|
var XJoins = XNode.SelectNodes("Table-Reference");
|
|
if (XJoins != null && XJoins.Count > 0)
|
|
{
|
|
Parser.EnterElement("Table-Reference");
|
|
foreach (XmlNode XEntry in XJoins)
|
|
{
|
|
if (!(XEntry is XmlElement XJoin))
|
|
continue;
|
|
|
|
try
|
|
{
|
|
var Join = new cDataHistoryConfigTableReferenceInfo(XJoin, this, Parser);
|
|
if (!Join.IsValid)
|
|
{
|
|
var strWithName = "";
|
|
if (Join.ForeignTableName != null)
|
|
strWithName = $"with Name='{Join.ForeignTableName}'";
|
|
Parser.AddMessage(XJoin, $"The <Table-Reference> element{strWithName} is not valid.", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
if (References.ContainsKey(Join.ForeignTableName))
|
|
{
|
|
Parser.AddMessage(XJoin, $"The element <{XJoin.Name}> with Table='{Join.ForeignTableName}' within table '{Name}' is duplicated.", LogLevels.Warning);
|
|
continue;
|
|
}
|
|
|
|
References.Add(Join.ForeignTableName, Join);
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
Parser.SelectElementNext();
|
|
}
|
|
}
|
|
|
|
Parser.LeaveElement("Table-Reference");
|
|
}
|
|
|
|
// resolve the columns of the computations
|
|
bool _IsValid = true;
|
|
foreach (var Column in Columns.Values)
|
|
{
|
|
if (!(Column is cDataHistoryConfigColumnComputation CP))
|
|
continue;
|
|
|
|
if (CP.Computation != null)
|
|
_IsValid &= CP.Computation.Resolve(Columns, Parser);
|
|
}
|
|
|
|
IsValid = _IsValid;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
IsValid = false;
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
}
|
|
}
|
|
|
|
internal static Dictionary<string, cDataHistoryConfigTable> LoadFromXml(XmlElement XNode, cDataHistoryConfigCluster Cluster, cXmlParser Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
var XTableList = new List<XmlNodeList>(3);
|
|
var XList = XNode.SelectNodes("Table");
|
|
if (XList != null && XList.Count > 0)
|
|
XTableList.Add(XList);
|
|
XList = XNode.SelectNodes("JoinedTable");
|
|
if (XList != null && XList.Count > 0)
|
|
XTableList.Add(XList);
|
|
XList = XNode.SelectNodes("InformationClass");
|
|
if (XList != null && XList.Count > 0)
|
|
XTableList.Add(XList);
|
|
|
|
if (XTableList.Count == 0)
|
|
return null;
|
|
|
|
var RetVal = new Dictionary<string, cDataHistoryConfigTable>();
|
|
foreach (XmlNodeList XTables in XTableList)
|
|
{
|
|
Parser.EnterElement(XTables[0].Name);
|
|
foreach (XmlNode XNode2 in XTables)
|
|
{
|
|
if (!(XNode2 is XmlElement XTable))
|
|
continue;
|
|
|
|
var Table = new cDataHistoryConfigTable(XTable, Cluster, Parser);
|
|
if ((Table != null) && Table.IsValid)
|
|
{
|
|
if (!RetVal.ContainsKey(Table.Name))
|
|
{
|
|
if (!Cluster.ParentConfig.Tables.ContainsKey(Table.Name))
|
|
{
|
|
RetVal.Add(Table.Name, Table);
|
|
if (!Cluster.ParentConfig.Tables.ContainsKey(Table.Name))
|
|
Cluster.ParentConfig.Tables.Add(Table.Name, Table);
|
|
}
|
|
else
|
|
{
|
|
Parser.AddMessage(XTable, $"There's already an <{XTable.Name}> element with Name='{Table.Name}'", LogLevels.Warning);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Parser.AddMessage(XTable, $"There's already an <{XTable.Name}> element with Name='{Table.Name}'", LogLevels.Warning);
|
|
}
|
|
|
|
if (Table.AlternateNames != null)
|
|
{
|
|
foreach (var _an in Table.AlternateNames)
|
|
Cluster.ParentConfig.AlternateTableNames[_an] = Table.Name;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var strN = "";
|
|
if (Table != null)
|
|
strN = $" with Name='{Table.Name}'";
|
|
Parser.AddMessage(XTable, $"The <{XTable.Name}> element{strN} is not valid.", LogLevels.Error);
|
|
}
|
|
Parser.SelectElementNext();
|
|
}
|
|
Parser.LeaveElement(XTables[0].Name);
|
|
}
|
|
|
|
if (RetVal.Count > 0)
|
|
{
|
|
var _lstAuto = new List<cDataHistoryConfigTable>();
|
|
foreach (var Entry in RetVal.Values)
|
|
{
|
|
if (!string.IsNullOrEmpty(Entry.AutoCreateHistoryTableName))
|
|
_lstAuto.Add(Entry);
|
|
}
|
|
foreach (var Entry in _lstAuto)
|
|
{
|
|
var _tbl = cDataHistoryConfigTable.CreateHistoricTableFromDetails(Entry);
|
|
if (_tbl != null)
|
|
{
|
|
if (!RetVal.ContainsKey(_tbl.Name))
|
|
{
|
|
RetVal.Add(_tbl.Name, _tbl);
|
|
if (!Cluster.ParentConfig.Tables.ContainsKey(_tbl.Name))
|
|
Cluster.ParentConfig.Tables.Add(_tbl.Name, _tbl);
|
|
}
|
|
}
|
|
}
|
|
return RetVal;
|
|
}
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return Name;
|
|
}
|
|
|
|
public bool IsUniqueColumn(cDataHistoryConfigColumnBase Column)
|
|
{
|
|
if (KeyColumns.Contains(Column))
|
|
return true;
|
|
if (EventTimeColumn == Column)
|
|
return true;
|
|
|
|
foreach (var Index in Indexes.Values)
|
|
{
|
|
if (!Index.Unique)
|
|
continue;
|
|
|
|
if (Index.Columns.Contains(Column))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public bool IsNullable(cDataHistoryConfigColumnBase Column)
|
|
{
|
|
return !IsUniqueColumn(Column);
|
|
}
|
|
|
|
internal bool ResolveReferences(Dictionary<string, cDataHistoryConfigTable> Tables, cXmlParser Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
var RetVal = true;
|
|
var delList = new List<cDataHistoryConfigTableReferenceInfo>();
|
|
foreach (var Ref in this.References.Values)
|
|
{
|
|
RetVal &= Ref.Resolve(this, Tables, Parser);
|
|
if (!Ref.IsValid)
|
|
delList.Add(Ref);
|
|
}
|
|
|
|
foreach (var Ref in delList)
|
|
this.References.Remove(Ref.ForeignTableName);
|
|
|
|
return RetVal;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
internal static cDataHistoryConfigTable CreateHistoricTableFromDetails(cDataHistoryConfigTable SourceTable)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
var _newTable = new cDataHistoryConfigTable()
|
|
{
|
|
IsValid = true,
|
|
Name = SourceTable.AutoCreateHistoryTableName,
|
|
SourceName = SourceTable.SourceName,
|
|
Description = SourceTable.Description,
|
|
LateDelivery = SourceTable.LateDelivery,
|
|
IsBuildInTable = SourceTable.IsBuildInTable,
|
|
Cached = SourceTable.Cached,
|
|
IsVirtual = SourceTable.IsVirtual,
|
|
ParentCluster = SourceTable.ParentCluster,
|
|
Type = eDataHistoryTableType.History
|
|
};
|
|
|
|
var _newSubTable = new cDataHistoryConfigSubTable(_newTable)
|
|
{
|
|
IsValid = true,
|
|
Name = SourceTable.AutoCreateHistoryTableName,
|
|
Description = SourceTable.Description
|
|
};
|
|
_newTable.SubTables.Add(_newSubTable.Name, _newSubTable);
|
|
|
|
foreach (var Entry in SourceTable.KeyColumns)
|
|
{
|
|
var _colId = new cDataHistoryConfigColumn(Entry.Name, _newSubTable, Entry.ValueType, Entry.Cardinal)
|
|
{
|
|
SourceName = Entry.SourceName,
|
|
AggregationType = eDataHistoryAggregationType.first
|
|
};
|
|
_newSubTable.Columns.Add(_colId.Name, _colId);
|
|
_newTable.Columns.Add(_colId.Name, _colId);
|
|
_newTable.KeyColumns.Add(_colId);
|
|
_newTable.KeyColumnNames.Add(_colId.Name);
|
|
}
|
|
|
|
var _colTime = new cDataHistoryConfigColumn(SourceTable.EventTimeColumn.Name, _newSubTable, SourceTable.EventTimeColumn.ValueType, SourceTable.EventTimeColumn.Cardinal)
|
|
{
|
|
SourceName = SourceTable.EventTimeColumn.SourceName,
|
|
AggregationType = eDataHistoryAggregationType.count
|
|
};
|
|
_newSubTable.Columns.Add(_colTime.Name, _colTime);
|
|
_newTable.Columns.Add(_colTime.Name, _colTime);
|
|
_newTable.EventTimeColumn = _colTime;
|
|
_newTable.EventTimeColumnName = _colTime.Name;
|
|
|
|
return _newTable;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigSubTable : IConfigNodeNamed
|
|
{
|
|
public bool IsValid { get; internal set; } = false;
|
|
public string Name { get; set; } = null;
|
|
public string Description { get; internal set; } = null;
|
|
public bool Aggregation { get; private set; } = false;
|
|
public bool HasLateDelivery { get; private set; } = false;
|
|
|
|
[JsonIgnore]
|
|
public readonly cDataHistoryConfigTable ParentTable = null;
|
|
|
|
public readonly cDataHistoryConfigQueryTemplate Template = null;
|
|
|
|
public readonly Dictionary<string, cDataHistoryConfigColumnBase> Columns = null;
|
|
|
|
internal cDataHistoryConfigSubTable(cDataHistoryConfigTable Table)
|
|
{
|
|
ParentTable = Table;
|
|
Columns = new Dictionary<string, cDataHistoryConfigColumnBase>();
|
|
}
|
|
|
|
internal cDataHistoryConfigSubTable(XmlElement XNode, cDataHistoryConfigTable Table, cXmlParser Parser)
|
|
{
|
|
try
|
|
{
|
|
if (Table == null)
|
|
{
|
|
LogException(new Exception("No valid Tabel parameter used."), LogLevels.Fatal);
|
|
return;
|
|
}
|
|
|
|
ParentTable = Table;
|
|
|
|
Name = cXmlParser.GetStringFromXmlAttribute(XNode, "Name");
|
|
if (string.IsNullOrEmpty(Name))
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> has no valid 'Name' attribute", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
Description = cXmlParser.GetStringFromXmlAttribute(XNode, "Description");
|
|
|
|
Template = cDataHistoryConfigQueryTemplate.LoadFromXml(XNode, Parser);
|
|
|
|
// ToDo: Check, if we need a template
|
|
/*
|
|
if (Template == null)
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> with Name='{Name}' has no valid '<Template>' element", LogLevels.Warning);
|
|
return;
|
|
}
|
|
*/
|
|
|
|
Columns = cDataHistoryConfigColumnBase.LoadFromXml(XNode, this, Parser);
|
|
if (Columns == null || Columns.Count == 0)
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> with Name='{Name}' has no valid columns", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
if (Table.Name == "agnt-computer-event-string")
|
|
{
|
|
|
|
}
|
|
foreach (var Col in Columns.Values)
|
|
{
|
|
HasLateDelivery |= Col.LateDelivery;
|
|
|
|
if (Col is cDataHistoryConfigColumn _C && _C.AggregationType != eDataHistoryAggregationType.Unknown)
|
|
Aggregation = true;
|
|
}
|
|
if (Table.IsBuildInTable && !Columns.ContainsKey("id"))
|
|
{
|
|
var _colId = new cDataHistoryConfigColumn("id", this, enumFasdValueType.GUID);
|
|
Columns.Add("id", _colId);
|
|
if (!Table.Columns.ContainsKey("id"))
|
|
Table.Columns.Add("id", _colId);
|
|
}
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public abstract class cDataHistoryConfigColumnBase : cConfigNodeNamed
|
|
{
|
|
public readonly enumFasdValueType ValueType = enumFasdValueType.Unknown;
|
|
|
|
public readonly int Cardinal = -1;
|
|
|
|
public string SqlType = null;
|
|
public string SqlTypeBin = null;
|
|
public string NameBin = null;
|
|
|
|
public string SourceName = null;
|
|
|
|
public readonly bool LateDelivery = false;
|
|
|
|
public string SourceTable = null;
|
|
|
|
public bool IsWritable { get; private set; } = false;
|
|
|
|
[JsonIgnore]
|
|
public readonly cDataHistoryConfigSubTable ParentTable = null;
|
|
|
|
internal cDataHistoryConfigColumnBase(string Name, cDataHistoryConfigSubTable SubTable, enumFasdValueType Type, int Cardinal = -1) : base(Name)
|
|
{
|
|
ParentTable = SubTable;
|
|
SourceName = Name;
|
|
ValueType = Type;
|
|
SqlType = cDataHistoryConfigClusters.GetSqlDataTypeFromHistoryType(ValueType, Cardinal, false);
|
|
SqlTypeBin = cDataHistoryConfigClusters.GetSqlDataTypeFromHistoryType(ValueType, Cardinal, true);
|
|
}
|
|
|
|
internal cDataHistoryConfigColumnBase(XmlElement XNode, cDataHistoryConfigSubTable ParentTable, cXmlParser Parser) :
|
|
base(XNode, Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
if (!IsValid)
|
|
return;
|
|
|
|
IsValid = false;
|
|
|
|
if (ParentTable == null)
|
|
{
|
|
LogException(new Exception("No valid ParentTable delivered."));
|
|
return;
|
|
}
|
|
|
|
this.ParentTable = ParentTable;
|
|
|
|
NameBin = Name;
|
|
|
|
ValueType = cXmlParser.GetEnumFromAttribute<enumFasdValueType>(XNode, "Type", enumFasdValueType.Unknown);
|
|
if (ValueType == enumFasdValueType.Unknown)
|
|
{
|
|
Parser.AddInvalidAttribute(XNode, Name, "Type");
|
|
return;
|
|
}
|
|
|
|
Cardinal = cXmlParser.GetIntegerFromXmlAttribute(XNode, "Cardinal", -1);
|
|
|
|
LateDelivery = cXmlParser.GetBoolFromXmlAttribute(XNode, "LateDelivery");
|
|
|
|
IsWritable = cXmlParser.GetBoolFromXmlAttribute(XNode, "IsWritable");
|
|
|
|
SqlType = cDataHistoryConfigClusters.GetSqlDataTypeFromHistoryType(ValueType, Cardinal, false);
|
|
if (SqlType == null)
|
|
{
|
|
Parser.AddMessage(XNode, $"The type '{ValueType}' at element <{XNode.Name}> with Name='{Name}' has no valid corresponding sql type.", LogLevels.Fatal);
|
|
return;
|
|
}
|
|
|
|
SqlTypeBin = cDataHistoryConfigClusters.GetSqlDataTypeFromHistoryType(ValueType, Cardinal, true);
|
|
if (!string.IsNullOrEmpty(SqlTypeBin))
|
|
NameBin = Name + "_bin";
|
|
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
static internal Dictionary<string, cDataHistoryConfigColumnBase> LoadFromXml(XmlElement XNode, cDataHistoryConfigSubTable ParentTable, cXmlParser Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
XmlElement XElements = XNode;
|
|
|
|
if (!ParentTable.ParentTable.IsBuildInTable)
|
|
{
|
|
var XList2 = XNode.SelectSingleNode("Table-Columns");
|
|
|
|
if (!(XList2 is XmlElement XList))
|
|
{
|
|
Parser.AddMessage(XNode, $"Illegal XML node 'Table-Columns' within element <{XNode.Name}> in table '{ParentTable.Name}' found.", LogLevels.Warning);
|
|
return null;
|
|
}
|
|
XElements = XList;
|
|
|
|
Parser.EnterElement("Table-Columns");
|
|
}
|
|
|
|
var RetVal = new Dictionary<string, cDataHistoryConfigColumnBase>();
|
|
try
|
|
{
|
|
var XColumns = XElements.ChildNodes;
|
|
if (XColumns == null || XColumns.Count == 0)
|
|
{
|
|
Parser.AddMessage(XElements, $"No valid elements found within element <{XElements.Name}> in table '{ParentTable.Name}'.", LogLevels.Warning);
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
var ColumnGroups = XColumns.Cast<XmlNode>().Where(node => node is XmlElement).GroupBy(node => node.Name);
|
|
|
|
foreach (var ColGroup in ColumnGroups)
|
|
{
|
|
Parser.EnterElement(ColGroup.Key);
|
|
foreach (XmlElement XColumn in ColGroup)
|
|
{
|
|
cDataHistoryConfigColumnBase Column = null;
|
|
switch (ColGroup.Key)
|
|
{
|
|
case "Table-Column":
|
|
case "InformationClass-Column":
|
|
Column = new cDataHistoryConfigColumn(XColumn, ParentTable, Parser);
|
|
break;
|
|
case "Table-Column-NxtCompute":
|
|
Column = new cDataHistoryConfigColumnNxtCompute(XColumn, ParentTable, Parser);
|
|
break;
|
|
case "Table-Column-NxtCategory":
|
|
Column = new cDataHistoryConfigColumnNxtCategory(XColumn, ParentTable, Parser);
|
|
break;
|
|
case "Table-Column-NxtScore":
|
|
Column = new cDataHistoryConfigColumnNxtScore(XColumn, ParentTable, Parser);
|
|
break;
|
|
case "Table-Column-NxtAction":
|
|
Column = new cDataHistoryConfigColumnNxtAction(XColumn, ParentTable, Parser);
|
|
break;
|
|
case "Table-Column-NxtCampaign":
|
|
Column = new cDataHistoryConfigColumnNxtCampaign(XColumn, ParentTable, Parser);
|
|
break;
|
|
case "Table-Column-Computation":
|
|
Column = new cDataHistoryConfigColumnComputation(XColumn, ParentTable, Parser);
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
|
|
var pTable = ParentTable.ParentTable;
|
|
if ((Column != null) && Column.IsValid)
|
|
{
|
|
if (!RetVal.ContainsKey(Column.Name))
|
|
{
|
|
if (pTable.KeyColumnNames.Contains(Column.Name) || !pTable.Columns.ContainsKey(Column.Name))
|
|
{
|
|
RetVal.Add(Column.Name, Column);
|
|
if (!pTable.Columns.ContainsKey(Column.Name))
|
|
pTable.Columns.Add(Column.Name, Column);
|
|
}
|
|
else
|
|
{
|
|
Parser.AddMessage(XColumn, $"There's already an <{XColumn.Name}> element with Name='{Column.Name}'", LogLevels.Warning);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Parser.AddMessage(XColumn, $"There's already an <{XColumn.Name}> element with Name='{Column.Name}'", LogLevels.Warning);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var strN = "";
|
|
if (Column != null)
|
|
strN = $" with Name='{Column.Name}'";
|
|
Parser.AddMessage(XColumn, $"The <{XColumn.Name}> element{strN} is not valid.", LogLevels.Error);
|
|
}
|
|
Parser.SelectElementNext();
|
|
}
|
|
Parser.LeaveElement(ColGroup.Key);
|
|
}
|
|
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (!ParentTable.ParentTable.IsBuildInTable)
|
|
Parser.LeaveElement("Table-Columns");
|
|
}
|
|
|
|
if (RetVal.Count > 0)
|
|
return RetVal;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigColumn : cDataHistoryConfigColumnBase
|
|
{
|
|
public eDataHistoryQueryType SourceType = eDataHistoryQueryType.Query;
|
|
|
|
public string SourceJsonField = null;
|
|
public int SourceJsonColumn = -1;
|
|
|
|
public eDataHistoryAggregationType AggregationType = eDataHistoryAggregationType.Unknown;
|
|
|
|
public readonly bool FillEmptyEntries = false;
|
|
|
|
internal cDataHistoryConfigColumn(string Name, cDataHistoryConfigSubTable SubTable, enumFasdValueType Type, int Cardinal = -1) : base(Name, SubTable, Type, Cardinal)
|
|
{
|
|
}
|
|
|
|
internal cDataHistoryConfigColumn(XmlElement XNode, cDataHistoryConfigSubTable ParentTable, cXmlParser Parser) :
|
|
base(XNode, ParentTable, Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
if (!IsValid)
|
|
return;
|
|
|
|
SourceName = cXmlParser.GetStringFromXmlAttribute(XNode, "SourceName", Name);
|
|
SourceTable = cXmlParser.GetStringFromXmlAttribute(XNode, "SourceTable", null);
|
|
SourceType = cXmlParser.GetEnumFromAttribute<eDataHistoryQueryType>(XNode, "SourceType", eDataHistoryQueryType.Query);
|
|
SourceJsonField = cXmlParser.GetStringFromXmlAttribute(XNode, "SourceJsonField", null);
|
|
SourceJsonColumn = cXmlParser.GetIntegerFromXmlAttribute(XNode, "SourceJsonColumn", -1);
|
|
AggregationType = cXmlParser.GetEnumFromAttribute<eDataHistoryAggregationType>(XNode, "Aggregation", eDataHistoryAggregationType.Unknown);
|
|
FillEmptyEntries = cXmlParser.GetBoolFromXmlAttribute(XNode, "FillEmptyEntries");
|
|
|
|
if (AggregationType != eDataHistoryAggregationType.Unknown)
|
|
{
|
|
var valType = cDataHistoryConfigClusters.ResultingAggregationType(this.ValueType, this.AggregationType);
|
|
SqlType = cDataHistoryConfigClusters.GetSqlDataTypeFromHistoryType(valType, Cardinal, false);
|
|
if (SqlType == null)
|
|
{
|
|
Parser.AddMessage(XNode, $"The type '{ValueType}' at element <{XNode.Name}> with Name='{Name}' has no valid corresponding sql type.", LogLevels.Fatal);
|
|
return;
|
|
}
|
|
|
|
SqlTypeBin = cDataHistoryConfigClusters.GetSqlDataTypeFromHistoryType(valType, Cardinal, true);
|
|
if (!string.IsNullOrEmpty(SqlTypeBin))
|
|
NameBin = Name + "_bin";
|
|
|
|
}
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
IsValid = false;
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigColumnNxtCompute : cDataHistoryConfigColumn
|
|
{
|
|
internal cDataHistoryConfigColumnNxtCompute(XmlElement XNode, cDataHistoryConfigSubTable ParentTable, cXmlParser Parser) :
|
|
base(XNode, ParentTable, Parser)
|
|
{
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigColumnNxtCategory : cDataHistoryConfigColumn
|
|
{
|
|
internal cDataHistoryConfigColumnNxtCategory(XmlElement XNode, cDataHistoryConfigSubTable ParentTable, cXmlParser Parser) :
|
|
base(XNode, ParentTable, Parser)
|
|
{
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigColumnNxtScore : cDataHistoryConfigColumnBase
|
|
{
|
|
public readonly string ScoreName = null;
|
|
public readonly string ValueName = null;
|
|
public readonly Guid ScoreID = Guid.Empty;
|
|
public readonly Guid ValueID = Guid.Empty;
|
|
public readonly bool IsPayload = false;
|
|
|
|
internal cDataHistoryConfigColumnNxtScore(XmlElement XNode, cDataHistoryConfigSubTable ParentTable, cXmlParser Parser) :
|
|
base(XNode, ParentTable, Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
if (!IsValid)
|
|
return;
|
|
|
|
IsValid = false;
|
|
ScoreName = cXmlParser.GetStringFromXmlAttribute(XNode, "ScoreName");
|
|
if (string.IsNullOrEmpty(ScoreName))
|
|
{
|
|
Parser.AddInvalidAttribute(XNode, Name, "ScoreName");
|
|
return;
|
|
}
|
|
|
|
ValueName = cXmlParser.GetStringFromXmlAttribute(XNode, "ValueName");
|
|
if (string.IsNullOrEmpty(ValueName))
|
|
{
|
|
Parser.AddInvalidAttribute(XNode, Name, "ValueName");
|
|
return;
|
|
}
|
|
|
|
ScoreID = cXmlParser.GetGuidFromXmlAttribute(XNode, "ScoreID");
|
|
ValueID = cXmlParser.GetGuidFromXmlAttribute(XNode, "ValueID");
|
|
IsPayload = cXmlParser.GetBoolFromXmlAttribute(XNode, "Payload");
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
IsValid = false;
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigColumnNxtAction : cDataHistoryConfigColumnBase
|
|
{
|
|
public readonly string ActionName = null;
|
|
public readonly string ValueName = null;
|
|
public readonly Guid ActionID = Guid.Empty;
|
|
public readonly Guid ValueID = Guid.Empty;
|
|
|
|
internal cDataHistoryConfigColumnNxtAction(XmlElement XNode, cDataHistoryConfigSubTable ParentTable, cXmlParser Parser) :
|
|
base(XNode, ParentTable, Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
if (!IsValid)
|
|
return;
|
|
|
|
IsValid = false;
|
|
ActionName = cXmlParser.GetStringFromXmlAttribute(XNode, "ActionName");
|
|
if (string.IsNullOrEmpty(ActionName))
|
|
{
|
|
Parser.AddInvalidAttribute(XNode, Name, "ActionName");
|
|
return;
|
|
}
|
|
|
|
ValueName = cXmlParser.GetStringFromXmlAttribute(XNode, "ValueName");
|
|
if (string.IsNullOrEmpty(ValueName))
|
|
{
|
|
Parser.AddInvalidAttribute(XNode, Name, "ValueName");
|
|
return;
|
|
}
|
|
|
|
ActionID = cXmlParser.GetGuidFromXmlAttribute(XNode, "ActionID");
|
|
ValueID = cXmlParser.GetGuidFromXmlAttribute(XNode, "ValueID");
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
IsValid = false;
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigColumnNxtCampaign : cDataHistoryConfigColumnBase
|
|
{
|
|
public readonly string CampaignName = null;
|
|
public readonly string ValueName = null;
|
|
public readonly Guid CampaignID = Guid.Empty;
|
|
public readonly int ValueID = -1;
|
|
public readonly bool AsText = false;
|
|
|
|
internal cDataHistoryConfigColumnNxtCampaign(XmlElement XNode, cDataHistoryConfigSubTable ParentTable, cXmlParser Parser) :
|
|
base(XNode, ParentTable, Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
if (!IsValid)
|
|
return;
|
|
|
|
IsValid = false;
|
|
CampaignName = cXmlParser.GetStringFromXmlAttribute(XNode, "CampaignName");
|
|
if (string.IsNullOrEmpty(CampaignName))
|
|
{
|
|
Parser.AddInvalidAttribute(XNode, Name, "CampaignName");
|
|
return;
|
|
}
|
|
|
|
ValueName = cXmlParser.GetStringFromXmlAttribute(XNode, "ValueName");
|
|
if (string.IsNullOrEmpty(ValueName))
|
|
{
|
|
Parser.AddInvalidAttribute(XNode, Name, "ValueName");
|
|
return;
|
|
}
|
|
|
|
CampaignID = cXmlParser.GetGuidFromXmlAttribute(XNode, "CampaignID");
|
|
ValueID = cXmlParser.GetIntegerFromXmlAttribute(XNode, "ValueID");
|
|
AsText = cXmlParser.GetBoolFromXmlAttribute(XNode, "AsText");
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
IsValid = false;
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigColumnComputation : cDataHistoryConfigColumnBase
|
|
{
|
|
public cDataHistoryConfigComputationBase Computation { get; set; } = null;
|
|
|
|
internal cDataHistoryConfigColumnComputation(XmlElement XNode, cDataHistoryConfigSubTable ParentTable, cXmlParser Parser) :
|
|
base(XNode, ParentTable, Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
if (!IsValid)
|
|
return;
|
|
|
|
IsValid = false;
|
|
|
|
var XList = XNode.SelectNodes("*");
|
|
foreach (XmlNode XNode2 in XList)
|
|
{
|
|
if (!(XNode2 is XmlElement XEntry))
|
|
continue;
|
|
|
|
cDataHistoryConfigComputationBase Co = null;
|
|
switch (XNode2.Name)
|
|
{
|
|
case "Computation-LinearTransform":
|
|
Parser.EnterElement("Computation-LinearTransform");
|
|
Co = new cDataHistoryConfigComputationLinearTransform(XEntry, Parser);
|
|
Parser.LeaveElement("Computation-LinearTransform");
|
|
break;
|
|
case "Computation-RegEx":
|
|
Parser.EnterElement("Computation-RegEx");
|
|
Co = new cDataHistoryConfigComputationRegEx(XEntry, Parser);
|
|
Parser.LeaveElement("Computation-RegEx");
|
|
break;
|
|
}
|
|
if (Co != null && Co.IsValid)
|
|
{
|
|
if (Computation != null)
|
|
{
|
|
Parser.AddMessage(XNode, $"The <{XNode.Name}> element with Name='{Name}' has more than one valid computation sub-node.", LogLevels.Error);
|
|
return;
|
|
}
|
|
Computation = Co;
|
|
}
|
|
}
|
|
if (Computation == null)
|
|
{
|
|
Parser.AddMessage(XNode, $"The <{XNode.Name}> element with Name='{Name}' has no valid computation sub-node.", LogLevels.Error);
|
|
return;
|
|
}
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
IsValid = false;
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public abstract class cDataHistoryConfigComputationBase : IConfigNodeValidation
|
|
{
|
|
public bool IsValid { get; internal set; } = false;
|
|
|
|
public List<string> ColumnNames { get; internal set; } = new List<string>();
|
|
|
|
[JsonIgnore]
|
|
public List<cDataHistoryConfigColumnBase> Columns = new List<cDataHistoryConfigColumnBase>();
|
|
|
|
[JsonIgnore]
|
|
private readonly int XLine = 0;
|
|
[JsonIgnore]
|
|
private readonly int XCol = 0;
|
|
[JsonIgnore]
|
|
private readonly string NodeName;
|
|
|
|
internal cDataHistoryConfigComputationBase(XmlElement XNode, cXmlParser Parser)
|
|
{
|
|
XLine = Parser.currentNode.Line;
|
|
XCol = Parser.currentNode.Column;
|
|
NodeName = XNode.Name;
|
|
}
|
|
|
|
internal bool Resolve(Dictionary<string, cDataHistoryConfigColumnBase> TableColumns, cXmlParser Parser)
|
|
{
|
|
try
|
|
{
|
|
bool _IsValid = true;
|
|
foreach (var Entry in ColumnNames)
|
|
{
|
|
if (!TableColumns.TryGetValue(Entry, out var Column))
|
|
{
|
|
Parser.AddMessage(XLine, XCol, $"The column name '{Entry}' of the element '<{NodeName}>' could not be resolved.", LogLevels.Error);
|
|
_IsValid = false;
|
|
continue;
|
|
}
|
|
Columns.Add(Column);
|
|
}
|
|
return _IsValid;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public abstract object Compute(object[] Values);
|
|
|
|
public static double? GetDouble(object o, double? Default)
|
|
{
|
|
double? RetVal = Default;
|
|
try
|
|
{
|
|
if (o is int @int)
|
|
RetVal = Convert.ToDouble(@int);
|
|
else if (o is double @double)
|
|
RetVal = @double;
|
|
else if (o is string @string)
|
|
{
|
|
if (double.TryParse(@string, NumberStyles.Any, CultureInfo.GetCultureInfo("en-US").NumberFormat, out double R))
|
|
RetVal = R;
|
|
else
|
|
RetVal = Default;
|
|
}
|
|
}
|
|
catch { }
|
|
|
|
return RetVal;
|
|
}
|
|
|
|
}
|
|
|
|
public class cDataHistoryConfigComputationLinearTransform : cDataHistoryConfigComputationBase
|
|
{
|
|
public double m { get; internal set; } = 1.0f;
|
|
public double b { get; internal set; } = 0.0f;
|
|
|
|
internal cDataHistoryConfigComputationLinearTransform(XmlElement XNode, cXmlParser Parser) :
|
|
base(XNode, Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
IsValid = false;
|
|
try
|
|
{
|
|
var Column = cXmlParser.GetStringFromXmlAttribute(XNode, "Column");
|
|
if (string.IsNullOrWhiteSpace(Column))
|
|
{
|
|
Parser.AddMessage(XNode, $"The <{XNode.Name}> element has no valid 'column' attribute", LogLevels.Warning);
|
|
return;
|
|
}
|
|
ColumnNames.Add(Column);
|
|
|
|
m = cXmlParser.GetDoubleFromXmlAttribute(XNode, "m", 1.0);
|
|
b = cXmlParser.GetDoubleFromXmlAttribute(XNode, "b", 0.0);
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
IsValid = false;
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
public override object Compute(object[] Values)
|
|
{
|
|
if (Values.Length != 1)
|
|
return null;
|
|
|
|
double? V = GetDouble(Values[0], null);
|
|
if (V == null)
|
|
return null;
|
|
|
|
return m * V + b;
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigComputationRegEx : cDataHistoryConfigComputationBase
|
|
{
|
|
public string RegExFilter { get; internal set; } = null;
|
|
public string Replacement { get; internal set; } = null;
|
|
public bool AutoTrim { get; internal set; } = false;
|
|
|
|
internal cDataHistoryConfigComputationRegEx(XmlElement XNode, cXmlParser Parser) :
|
|
base(XNode, Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
IsValid = false;
|
|
try
|
|
{
|
|
var Column = cXmlParser.GetStringFromXmlAttribute(XNode, "Column");
|
|
if (string.IsNullOrWhiteSpace(Column))
|
|
{
|
|
Parser.AddMessage(XNode, $"The <{XNode.Name}> element has no valid 'column' attribute", LogLevels.Warning);
|
|
return;
|
|
}
|
|
ColumnNames.Add(Column);
|
|
|
|
RegExFilter = cXmlParser.GetStringFromXmlAttribute(XNode, "RegExFilter");
|
|
if (string.IsNullOrWhiteSpace(RegExFilter))
|
|
{
|
|
Parser.AddInvalidAttribute(XNode, null, "RegExFilter");
|
|
return;
|
|
}
|
|
|
|
Replacement = cXmlParser.GetStringFromXmlAttribute(XNode, "Replacement");
|
|
|
|
AutoTrim = cXmlParser.GetBoolFromXmlAttribute(XNode, "AutoTrim");
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
IsValid = false;
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
public override object Compute(object[] Values)
|
|
{
|
|
try
|
|
{
|
|
if (Values.Length != 1)
|
|
return null;
|
|
|
|
if (Values[0] == null)
|
|
return null;
|
|
|
|
var RetVal = Values[0].ToString();
|
|
if (string.IsNullOrEmpty(RetVal))
|
|
return RetVal;
|
|
|
|
if (!string.IsNullOrEmpty(RegExFilter))
|
|
{
|
|
if (!string.IsNullOrEmpty(Replacement))
|
|
try
|
|
{
|
|
RetVal = Regex.Replace(RetVal, RegExFilter, Replacement, RegexOptions.CultureInvariant);
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
cLogManager.DefaultLogger.LogException(E);
|
|
}
|
|
else
|
|
try
|
|
{
|
|
var m = Regex.Match(RetVal, RegExFilter, RegexOptions.CultureInvariant);
|
|
RetVal = m.Value;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
cLogManager.DefaultLogger.LogException(E);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (AutoTrim)
|
|
RetVal = RetVal.Trim();
|
|
|
|
return RetVal;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
cLogManager.DefaultLogger.LogException(E);
|
|
return null;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public abstract class cDataHistoryConfigQueryTemplate : IConfigNodeValidation
|
|
{
|
|
public bool IsValid { get; protected set; } = false;
|
|
|
|
public string Query { get; private set; } = null;
|
|
|
|
internal cDataHistoryConfigQueryTemplate(XmlElement XNode, bool Compress, cXmlParser Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
var XContent = XNode.SelectSingleNode("text()")?.Value;
|
|
if (!string.IsNullOrEmpty(XContent))
|
|
{
|
|
Query = XContent;
|
|
if (Compress)
|
|
{
|
|
Query = Query.Replace("\r\n", " ");
|
|
Query = Query.Replace("\r", " ");
|
|
Query = Query.Replace("\n", " ");
|
|
Query = Query.Replace("\t", " ");
|
|
while (true)
|
|
{
|
|
var Q = Query.Replace(" ", " ");
|
|
if (Q == Query)
|
|
break;
|
|
Query = Q;
|
|
}
|
|
Query = Query.Trim();
|
|
}
|
|
}
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
Parser.AddMessage(XNode, $"The text content for element <{XNode.Name} is invalid.>", LogLevels.Warning);
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
}
|
|
|
|
internal static cDataHistoryConfigQueryTemplate LoadFromXml(XmlElement XNode, cXmlParser Parser)
|
|
{
|
|
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
|
|
try
|
|
{
|
|
cDataHistoryConfigQueryTemplate Template = cDataHistoryConfigQueryTemplateNxql.LoadFromXml(XNode, Parser);
|
|
if (Template?.IsValid == true)
|
|
return Template;
|
|
|
|
Template = new cDataHistoryConfigQueryTemplateM42Pickup(XNode, Parser);
|
|
if (Template?.IsValid == true)
|
|
return Template;
|
|
|
|
Template = new cDataHistoryConfigQueryTemplateM42DataQueryItems(XNode, Parser);
|
|
if (Template?.IsValid == true)
|
|
return Template;
|
|
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
if (CM != null) LogMethodEnd(CM);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigQueryTemplateNxql : cDataHistoryConfigQueryTemplate
|
|
{
|
|
public readonly uint Limit = 4294967295;
|
|
|
|
internal cDataHistoryConfigQueryTemplateNxql(XmlElement XNode, cXmlParser Parser) :
|
|
base(XNode, true, Parser)
|
|
{
|
|
if (!IsValid)
|
|
return;
|
|
|
|
Limit = cXmlParser.GetUnsignedIntegerFromXmlAttribute(XNode, "Limit", Limit);
|
|
IsValid = true;
|
|
}
|
|
|
|
new internal static cDataHistoryConfigQueryTemplateNxql LoadFromXml(XmlElement XNode, cXmlParser Parser)
|
|
{
|
|
|
|
try
|
|
{
|
|
if (XNode.SelectSingleNode("Nexthink-NXQL-Template") is XmlElement XNode2)
|
|
{
|
|
Parser.EnterElement("Nexthink-NXQL-Template");
|
|
var RetVal = new cDataHistoryConfigQueryTemplateNxql(XNode2, Parser);
|
|
Parser.LeaveElement("Nexthink-NXQL-Template");
|
|
return RetVal;
|
|
}
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigQueryTemplateM42Pickup : cDataHistoryConfigQueryTemplate
|
|
{
|
|
public enum enumSorting { unknown = 0, byPosition, byName };
|
|
|
|
public string PickupName { get; private set; } = null;
|
|
public int FilteredGroup { get; private set; } = -1;
|
|
public enumSorting Sorting { get; private set; } = enumSorting.unknown;
|
|
|
|
internal cDataHistoryConfigQueryTemplateM42Pickup(XmlElement XNode, cXmlParser Parser) :
|
|
base(XNode, true, Parser)
|
|
{
|
|
if (!IsValid)
|
|
return;
|
|
IsValid = false;
|
|
|
|
if (XNode.SelectSingleNode("Matrix42-Pickup-Template") is XmlElement XNode2)
|
|
{
|
|
Parser.EnterElement("Matrix42-Pickup-Template");
|
|
|
|
PickupName = cXmlParser.GetStringFromXmlAttribute(XNode2, "PickupName");
|
|
if (string.IsNullOrEmpty(PickupName))
|
|
return;
|
|
|
|
FilteredGroup = cXmlParser.GetIntegerFromXmlAttribute(XNode2, "FilteredGroup", -1);
|
|
Sorting = cXmlParser.GetEnumFromAttribute<enumSorting>(XNode2, "Sorting", enumSorting.unknown);
|
|
|
|
Parser.LeaveElement("Matrix42-Pickup-Template");
|
|
|
|
IsValid = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public class cDataHistoryConfigQueryTemplateM42DataQueryItems : cDataHistoryConfigQueryTemplate
|
|
{
|
|
public string EntityClassName { get; private set; } = null;
|
|
public List<string> EntityTypeNames { get; private set; } = null;
|
|
public string OrderBy { get; private set; } = null;
|
|
public string WhereExpression { get; private set; } = null;
|
|
|
|
|
|
internal cDataHistoryConfigQueryTemplateM42DataQueryItems(XmlElement XNode, cXmlParser Parser) :
|
|
base(XNode, true, Parser)
|
|
{
|
|
if (!IsValid)
|
|
return;
|
|
IsValid = false;
|
|
|
|
if (XNode.SelectSingleNode("Matrix42-DataQueryItems-Template") is XmlElement XNode2)
|
|
{
|
|
Parser.EnterElement("Matrix42-DataQueryItems-Template");
|
|
|
|
EntityClassName = cXmlParser.GetStringFromXmlAttribute(XNode2, "EntityClassName");
|
|
if (string.IsNullOrEmpty(EntityClassName))
|
|
return;
|
|
|
|
var strEntityTypeNames = cXmlParser.GetStringFromXmlAttribute(XNode2, "EntityTypeNames");
|
|
if (string.IsNullOrEmpty(EntityClassName))
|
|
return;
|
|
var arrEntityTypeNames = strEntityTypeNames.Split(' ');
|
|
if (arrEntityTypeNames.Length <= 0)
|
|
return;
|
|
EntityTypeNames = new List<string>(arrEntityTypeNames.Length);
|
|
foreach (var _e in arrEntityTypeNames)
|
|
{
|
|
var _e2 = _e.Trim();
|
|
if (!string.IsNullOrEmpty(_e2))
|
|
EntityTypeNames.Add(_e2);
|
|
}
|
|
|
|
OrderBy = cXmlParser.GetStringFromXmlAttribute(XNode2, "OrderBy");
|
|
WhereExpression = cXmlParser.GetStringFromXmlAttribute(XNode2, "WhereExpression");
|
|
|
|
Parser.LeaveElement("Matrix42-DataQueryItems-Template");
|
|
|
|
IsValid = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public class cDataHistoryConfigTableIndex
|
|
{
|
|
public string Name;
|
|
public bool Unique = false;
|
|
public List<cDataHistoryConfigColumnBase> Columns = new List<cDataHistoryConfigColumnBase>();
|
|
}
|
|
|
|
public class cDataHistoryConfigTableReferenceInfo : IConfigNodeValidation
|
|
{
|
|
public bool IsValid { get; private set; } = false;
|
|
public string ForeignTableName { get; private set; } = null;
|
|
public cDataHistoryConfigTable ForeignTable { get; private set; } = null;
|
|
|
|
public string ForeignIndexName { get; private set; } = null;
|
|
public cDataHistoryConfigTableIndex ReferencedIndex { get; private set; } = null;
|
|
|
|
[JsonIgnore]
|
|
private readonly int XLine = 0;
|
|
[JsonIgnore]
|
|
private readonly int XCol = 0;
|
|
|
|
public List<cDataHistoryConfigColumnBase> Columns { get; private set; } = new List<cDataHistoryConfigColumnBase>();
|
|
public List<cDataHistoryConfigColumnBase> ReferencedColumns { get; private set; } = new List<cDataHistoryConfigColumnBase>();
|
|
|
|
internal cDataHistoryConfigTableReferenceInfo(XmlElement XNode, cDataHistoryConfigTable Table, cXmlParser Parser)
|
|
{
|
|
try
|
|
{
|
|
XLine = Parser.currentNode.Line;
|
|
XCol = Parser.currentNode.Column;
|
|
ForeignTableName = XNode.GetAttribute("ForeignTable");
|
|
if (string.IsNullOrEmpty(ForeignTableName))
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> has no valid 'Table' attribute.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
var strReference = XNode.GetAttribute("Columns");
|
|
if (string.IsNullOrEmpty(strReference))
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> with Name='{ForeignTableName}' has no valid 'Reference' attribute.", LogLevels.Warning);
|
|
return;
|
|
}
|
|
|
|
var arrReference = strReference.Split(' ');
|
|
Columns.Clear();
|
|
foreach (var Entry in arrReference)
|
|
{
|
|
var strRef = Entry.Trim();
|
|
if (string.IsNullOrWhiteSpace(strRef))
|
|
continue;
|
|
|
|
if (!Table.Columns.TryGetValue(strRef, out var Col))
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> with Name='{ForeignTableName}' contains a non existing element '{strRef}' within the 'Reference' attribute.", LogLevels.Warning);
|
|
Columns.Clear();
|
|
break;
|
|
}
|
|
|
|
if (Columns.Contains(Col))
|
|
{
|
|
Parser.AddMessage(XNode, $"The element <{XNode.Name}> with Name='{ForeignTableName}' contains a duplicated element '{strRef}' within the 'Reference' attribute.", LogLevels.Warning);
|
|
Columns.Clear();
|
|
break;
|
|
}
|
|
|
|
Columns.Add(Col);
|
|
}
|
|
|
|
ForeignIndexName = XNode.GetAttribute("ForeignIndex");
|
|
|
|
IsValid = true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
finally
|
|
{
|
|
}
|
|
}
|
|
|
|
internal bool Resolve(cDataHistoryConfigTable Table, Dictionary<string, cDataHistoryConfigTable> AllTables, cXmlParser Parser)
|
|
{
|
|
IsValid = false;
|
|
try
|
|
{
|
|
// get the foreign table
|
|
if (!AllTables.TryGetValue(ForeignTableName, out var _ForeignTable))
|
|
return false;
|
|
|
|
// get the foreign table index
|
|
cDataHistoryConfigTableIndex _ForeignIndex = null;
|
|
if (!string.IsNullOrEmpty(ForeignIndexName))
|
|
if (!_ForeignTable.Indexes.TryGetValue(ForeignIndexName, out _ForeignIndex))
|
|
return false;
|
|
|
|
// get the foreign column list
|
|
var _ForeignColumns = new List<cDataHistoryConfigColumnBase>();
|
|
if (_ForeignIndex == null)
|
|
_ForeignColumns.AddRange(_ForeignTable.KeyColumns);
|
|
else
|
|
_ForeignColumns.AddRange(_ForeignIndex.Columns);
|
|
|
|
// check for column compatibilty
|
|
if (_ForeignColumns.Count != Columns.Count)
|
|
{
|
|
Parser.AddMessage(this.XLine, this.XCol, string.Format("The number of referenced columns of table '{0}' does not match the number of referenced foreign columns of table '{1}'.", Table.Name, _ForeignTable.Name), LogLevels.Error);
|
|
return false;
|
|
}
|
|
|
|
var ColsTo = _ForeignColumns.GetEnumerator();
|
|
foreach (var ColFrom in Columns)
|
|
{
|
|
if (!ColsTo.MoveNext())
|
|
return false;
|
|
|
|
var ColTo = ColsTo.Current;
|
|
|
|
if (!cDataHistoryConfigClusters.CheckColumnCompatibility(ColFrom, ColTo))
|
|
{
|
|
Parser.AddMessage(this.XLine, this.XCol, string.Format("The column type or cardinal of column '{0}' in table '{1}' does not match the referenced foreign column '{2}' of table '{3}'.", ColFrom.Name, Table.Name, ColTo.Name, _ForeignTable.Name), LogLevels.Error);
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
ForeignTable = _ForeignTable;
|
|
ReferencedIndex = _ForeignIndex;
|
|
ReferencedColumns = _ForeignColumns;
|
|
|
|
this.IsValid = true;
|
|
return true;
|
|
}
|
|
catch (Exception E)
|
|
{
|
|
LogException(E);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public class cDataHistoryConfigMainTable : cDataHistoryConfigTable
|
|
{
|
|
public cDataHistoryConfigMainTable()
|
|
{
|
|
}
|
|
|
|
}
|
|
}
|