diff --git a/src/ILICheck.Web/ClientApp/src/logHierarchy.js b/src/ILICheck.Web/ClientApp/src/logHierarchy.js index e9e451e..f5a5eaf 100644 --- a/src/ILICheck.Web/ClientApp/src/logHierarchy.js +++ b/src/ILICheck.Web/ClientApp/src/logHierarchy.js @@ -1,19 +1,17 @@ import groupBy from "object.groupby"; const constraintPatterns = [ - ["Mandatory Constraint", /^validate mandatory constraint (\S+)\.\.\.$/, /^Mandatory Constraint (\S+) is not true\.$/], - [ - "Plausibility Constraint", - /^validate plausibility constraint (\S+)\.\.\.$/, - /^Plausibility Constraint (\S+) is not true\.$/, - ], - ["Existence Constraint", /^validate existence constraint (\S+)\.\.\.$/, /^Existence constraint (\S+) is violated/], - ["Uniqueness Constraint", /^validate unique constraint (\S+)\.\.\.$/, /^Unique constraint (\S+) is violated/], - ["Set Constraint", /^validate set constraint (\S+)\.\.\.$/, /^Set Constraint (\S+) is not true\.$/], + ["Mandatory Constraint", /^validate mandatory constraint (\S+)\.\.\.$/], + ["Plausibility Constraint", /^validate plausibility constraint (\S+)\.\.\.$/], + ["Existence Constraint", /^validate existence constraint (\S+)\.\.\.$/], + ["Uniqueness Constraint", /^validate unique constraint (\S+)\.\.\.$/], + ["Set Constraint", /^validate set constraint (\S+)\.\.\.$/], ]; +// e.g. "Custom message ModelA.TopicA.ClassA.ConstraintName (ILI syntax)" will result in "Custom message" const customConstraintMessagePattern = /^(.*) (\w+\.\w+\.\w+\.\w+) \(.*\)$/; -const constraintNamePattern = /\s(\w+\.\w+\.\w+\.\w+)\s/; +// e.g. " ModelA.TopicA.ClassA.ConstraintName (ILI syntax) " (ILI syntax is optional and will be removed from the message) +const constraintNamePattern = /\s(\w+\.\w+\.\w+\.\w+)(\s\(.+\))?\s/; export function createLogHierarchy(logData) { const [constraintEntries, otherEntries] = collectLogEntries(logData); @@ -26,35 +24,29 @@ function collectLogEntries(entries) { const otherErrors = new Set(); for (const entry of entries) { - let constraintFound = false; - for (const [name, infoPattern, errorPattern] of constraintPatterns) { - let match; - if (entry.type === "Info") { - match = infoPattern.exec(entry.message); - } else if (entry.type === "Error") { - match = errorPattern.exec(entry.message); - } else { - continue; - } - - if (match) { - const constraintName = match[1]; - addOrReplaceLogEntry(constraintEntries, name, constraintName, entry); - constraintFound = true; - break; + if (entry.type === "Info") { + for (const [name, infoPattern] of constraintPatterns) { + const match = infoPattern.exec(entry.message); + if (match) { + const constraintName = match[1]; + addOrReplaceLogEntry(constraintEntries, name, constraintName, entry); + break; + } } - } - - if (!constraintFound && entry.type !== "Info") { - const match = customConstraintMessagePattern.exec(entry.message); - if (match) { - entry.message = match[1]; - const constraintName = match[2]; + } else { + const customMessageMatch = customConstraintMessagePattern.exec(entry.message); + if (customMessageMatch) { + entry.message = customMessageMatch[1]; + const constraintName = customMessageMatch[2]; addOrReplaceLogEntry(constraintEntries, "", constraintName, entry); } else { const nameMatch = constraintNamePattern.exec(entry.message); if (nameMatch) { const constraintName = nameMatch[1]; + const iliSyntax = nameMatch[2]; + if (iliSyntax) { + entry.message = entry.message.replace(iliSyntax, ""); + } addOrReplaceLogEntry(constraintEntries, "", constraintName, entry); } else if (entry.type === "Error") { otherErrors.add(entry.message); diff --git a/src/ILICheck.Web/ClientApp/src/logHierarchy.test.js b/src/ILICheck.Web/ClientApp/src/logHierarchy.test.js index dce0b8b..21b09d7 100644 --- a/src/ILICheck.Web/ClientApp/src/logHierarchy.test.js +++ b/src/ILICheck.Web/ClientApp/src/logHierarchy.test.js @@ -45,7 +45,7 @@ describe("transform log data to hierarchy", () => { { tid: "o3", message: - "Existence constraint ModelA.TopicA.ClassA.ConstraintName is violated! The value of the attribute Test of t1 was not found in the condition class.", + "Existence constraint ModelA.TopicA.ClassA.ConstraintName (EXISTENCE CONSTRAINT Test REQUIRED IN OtherClass:Test;) is violated! The value of the attribute Test of t1 was not found in the condition class.", type: "Error", }, ]; diff --git a/src/ILICheck.Web/Controllers/DownloadController.cs b/src/ILICheck.Web/Controllers/DownloadController.cs index 1a8bde1..44628b2 100644 --- a/src/ILICheck.Web/Controllers/DownloadController.cs +++ b/src/ILICheck.Web/Controllers/DownloadController.cs @@ -50,12 +50,12 @@ public IActionResult Download(Guid jobId, LogType logType) } /// - /// Gets the log of the specified in JSON format. + /// Gets the log data of the specified in JSON format. /// /// The job identifier. /// The log data for the specified . [HttpGet("json")] - [SwaggerResponse(StatusCodes.Status200OK, "Returns the ilivalidator log file in JSON format.", typeof(IEnumerable), new[] { "application/json" })] + [SwaggerResponse(StatusCodes.Status200OK, "Returns the ilivalidator log data in JSON format.", typeof(IEnumerable), new[] { "application/json" })] [SwaggerResponse(StatusCodes.Status400BadRequest, "The server cannot process the request due to invalid or malformed request.", typeof(ValidationProblemDetails), new[] { "application/json" })] [SwaggerResponse(StatusCodes.Status404NotFound, "The log file for the requested jobId cannot be found.", ContentTypes = new[] { "application/json" })] public IActionResult GetJsonLog(Guid jobId)