From ab8c5263045e8f83a354e5714c1a84ffbac5e4dc Mon Sep 17 00:00:00 2001
From: Jonas Blatt <jonasblatt@uni-koblenz.de>
Date: Mon, 10 Jul 2023 10:12:32 +0200
Subject: [PATCH] #36 Add Circular DRD Verifier

---
 .../verifier/impl/CircularDRDVerifier.java    | 69 +++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 dmnverifierapi/src/main/java/de/unikoblenz/ps/core/dmn/verification/verifier/impl/CircularDRDVerifier.java

diff --git a/dmnverifierapi/src/main/java/de/unikoblenz/ps/core/dmn/verification/verifier/impl/CircularDRDVerifier.java b/dmnverifierapi/src/main/java/de/unikoblenz/ps/core/dmn/verification/verifier/impl/CircularDRDVerifier.java
new file mode 100644
index 00000000..3b4b4adb
--- /dev/null
+++ b/dmnverifierapi/src/main/java/de/unikoblenz/ps/core/dmn/verification/verifier/impl/CircularDRDVerifier.java
@@ -0,0 +1,69 @@
+package de.unikoblenz.ps.core.dmn.verification.verifier.impl;
+
+import de.unikoblenz.ps.base.domain.Name;
+import de.unikoblenz.ps.core.dmn.domain.vdmn.*;
+import de.unikoblenz.ps.core.dmn.domain.vdmn.utils.VDmnFunctions;
+import de.unikoblenz.ps.core.dmn.verification.result.VerificationResultEntryElement;
+import de.unikoblenz.ps.core.dmn.verification.result.actions.Action;
+import de.unikoblenz.ps.core.dmn.verification.result.actions.VerificationFix;
+import de.unikoblenz.ps.core.dmn.verification.verifier.AbstractVerifier;
+import de.unikoblenz.ps.core.dmn.verification.verifier.DmnVerifier;
+import de.unikoblenz.ps.core.dmn.verification.verifier.classification.DrdModelingLevelVerification;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static de.unikoblenz.ps.base.domain.Name.NO_NAME;
+import static de.unikoblenz.ps.core.dmn.domain.vdmn.utils.VDmnFunctions.*;
+import static de.unikoblenz.ps.core.dmn.verification.result.VerificationResultEntry.VerificationClassification.ERROR;
+import static de.unikoblenz.ps.core.dmn.verification.result.VerificationResultEntry.VerificationClassification.WARNING;
+import static de.unikoblenz.ps.core.dmn.verification.result.actions.Action.ACTION_SHOW_DECISION;
+import static de.unikoblenz.ps.core.dmn.verification.result.actions.Action.ACTION_SHOW_INPUT_DATA;
+import static de.unikoblenz.ps.core.dmn.verification.result.actions.ActionScope.*;
+import static de.unikoblenz.ps.core.dmn.verification.result.actions.ActionType.*;
+import static de.unikoblenz.ps.core.dmn.verification.result.actions.VerificationFix.DEFAULT_SHOW_NAME;
+import static de.unikoblenz.ps.core.dmn.verification.result.actions.VerificationFix.SHOW_INPUT_COLUMNS;
+
+@DmnVerifier(
+        classification = DrdModelingLevelVerification.class,
+        name = "CircularDRDVerifier",
+        niceName = "Circular DRD",
+        description =
+                "Detecting circles in the DRD.")
+public class CircularDRDVerifier extends AbstractVerifier {
+
+    @Override
+    protected void doVerification() {
+        Stack<VDmnDecision> history = new Stack<>();
+        Set<Set<VDmnDecision>> circles = new HashSet<>();
+        for (VDmnDecision decision : dmnObjectContainer.getVDmnDefinition().getVDmnDecisions()) {
+            history.push(decision);
+            dfs(history, circles);
+            history.pop();
+        }
+    }
+
+    private void dfs(Stack<VDmnDecision> history, Set<Set<VDmnDecision>> circles) {
+        for (VDmnDecision next : history.peek().getInformationProvidingDecisions()) {
+            if (history.firstElement().equals(next)) {
+                Set<VDmnDecision> circle = new HashSet<>(history);
+                if (!circles.contains(circle)) {
+                    // new circle
+                    circles.add(circle);
+                    circle.forEach(vDmnDecision -> vreFactory.addElement(VerificationResultEntryElement.create(vDmnDecision)));
+                    vreFactory
+                            .addVerificationFix(
+                                    VerificationFix.getBuilder()
+                                            .withFixName(DEFAULT_SHOW_NAME)
+                                            .addAction(ACTION_SHOW_DECISION)
+                                            .build());
+                    vreFactory.addToEntry(ERROR, "Circle in Decision nodes detected.");
+                }
+            } else {
+                history.push(next);
+                dfs(history, circles);
+                history.pop();
+            }
+        }
+    }
+}
-- 
GitLab