From dcc473be977dff4d026d36ce32c1e82d37499f7e Mon Sep 17 00:00:00 2001
From: Johannes Mey <johannes.mey@tu-dresden.de>
Date: Mon, 22 Jun 2020 18:13:46 +0200
Subject: [PATCH] add some constraint checking

---
 src/main/jastadd/Constraints.jrag | 91 +++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)
 create mode 100644 src/main/jastadd/Constraints.jrag

diff --git a/src/main/jastadd/Constraints.jrag b/src/main/jastadd/Constraints.jrag
new file mode 100644
index 0000000..f713c77
--- /dev/null
+++ b/src/main/jastadd/Constraints.jrag
@@ -0,0 +1,91 @@
+aspect Constraints {
+
+  coll Set<ConstraintViolation> PetriNet.constraintViolations() [new java.util.HashSet()] root PetriNet;
+
+}
+
+aspect ConstraintViolations {
+
+  abstract class ConstraintViolation {
+
+
+    public String toString() {
+      return "Constraint " + getTitle() + " violated in object " + id() + ": " + getMessage();
+    }
+
+    protected ASTNode location;
+
+    public String id() {
+      if (location instanceof PnObject) return ((PnObject) location).getId();
+      if (location instanceof PetriNet) return ((PetriNet) location).getId();
+      return location.toString();
+    }
+
+    protected String title;
+    protected String description;
+    protected String message;
+
+    public String getTitle() { return title; }
+    public String getDescription() { return description; }
+    public String getMessage() { return message; }
+
+  }
+
+  class CheckIdsConstraint extends ConstraintViolation {
+    public CheckIdsConstraint(ASTNode location) {
+      this.location = location;
+      this.title = "CheckIds";
+      this.description = "Checks id attribute existence";
+      this.message = "A node of type '" + location.getClass().getSimpleName() + "' must have an id attribute.";
+    }
+  }
+
+  class CheckIdUniquenessConstraint extends ConstraintViolation {
+    public CheckIdUniquenessConstraint(ASTNode location) {
+      this.location = location;
+      this.title = "CheckIdUniquess";
+      this.description = "Checks id attribute uniqueness";
+      this.message = "The id attribute value " + id() + " of the node of type '" + location.getClass().getSimpleName() + "' is not unique.";
+    }
+  }
+
+  PetriNet contributes new CheckIdsConstraint(this)
+      when checkIdsConstraintViolated()
+      to PetriNet.constraintViolations();
+  PnObject contributes new CheckIdsConstraint(this)
+      when checkIdsConstraintViolated()
+      to PetriNet.constraintViolations();
+}
+
+aspect CoreModelConstraints {
+
+  syn boolean PetriNet.checkIdsConstraintViolated() = getId() == null || getId().equals("");
+  syn boolean PnObject.checkIdsConstraintViolated() = getId() == null || getId().equals("");
+
+  coll List<String> PetriNet.ids() [new ArrayList()] root PetriNet;
+  PnObject contributes getId() to PetriNet.ids();
+
+  syn Map<String, Long> PetriNet.idCount() =
+      ids().stream().collect(Collectors.groupingBy(java.util.function.Function.identity(), Collectors.counting()));
+
+  syn boolean PetriNet.uniqueId(String id) = idCount().get(id) <= 1;
+  syn boolean PnObject.uniqueId(String id) = petriNet().idCount().get(id) <= 1;
+
+  syn Optional<CheckIdUniquenessConstraint> PetriNet.checkIdUniqueness() {
+    if(uniqueId(getId())) return Optional.empty();
+    else return Optional.of(new CheckIdUniquenessConstraint(this));
+  }
+  syn Optional<CheckIdUniquenessConstraint> PnObject.checkIdUniqueness() {
+    if(petriNet().uniqueId(getId())) return Optional.empty();
+    else return Optional.of(new CheckIdUniquenessConstraint(this));
+  }
+
+  PetriNet contributes checkIdUniqueness().get()
+      when checkIdUniqueness().isPresent()
+      to PetriNet.constraintViolations();
+  PnObject contributes checkIdUniqueness().get()
+      when checkIdUniqueness().isPresent()
+      to PetriNet.constraintViolations();
+
+
+}
-- 
GitLab