GReQL Regeln: Unterschied zwischen den Versionen

Aus JACK Wiki
Zur Navigation springen Zur Suche springen
Keine Bearbeitungszusammenfassung
 
(8 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt)
Zeile 31: Zeile 31:
           with
           with
             x.name=capitalizeFirst(x.name) and
             x.name=capitalizeFirst(x.name) and
             isEmpty(from m : V{Modifier} with x <nowiki>&amp;lt;--&amp;amp;{FieldDeclaration} --&amp;gt;</nowiki> m and m.name="final" report m end)
             isEmpty(from m : V{Modifier} with x &lt;--&amp;{FieldDeclaration} --> m and m.name="final" report m end)
           report 0 end
           report 0 end
   </query>
   </query>
Zeile 77: Zeile 77:
</syntaxhighlight>
</syntaxhighlight>
Diese Regel sucht nach Paketdefinitionen und meldet diese als Fehler.
Diese Regel sucht nach Paketdefinitionen und meldet diese als Fehler.
<syntaxhighlight lang="xml" line='line'>
<rule type="absence" points="1">
  <query> from p : V{ImportDeclaration}
          report 0 end
  </query>
  <feedback prefix="Importdefinition"> Deine Lösung beinhaltet eine import-Angabe. Bitte entferne diese.</feedback>
</rule>
</syntaxhighlight>
Diese Regel sucht nach Importdefinitionen und meldet diese als Fehler.


<syntaxhighlight lang="xml" line='line'>
<syntaxhighlight lang="xml" line='line'>
Zeile 90: Zeile 100:
  </rule>
  </rule>
</syntaxhighlight>
</syntaxhighlight>
Diese Regel sucht nach Aufrufen von System.exit() und melde diese unter Angabe von Klasse und Zeilennummer als Fehler.
Diese Regel sucht nach Aufrufen von <code>System.exit()</code> und melde diese unter Angabe von Klasse und Zeilennummer als Fehler.
 
<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="1">
    <query>from x : V{MethodInvocation}, y, z : V{SimpleName}
          with
              x -->{ElementExpression}&amp;{QualifiedName} -->{QualifiedNameName} y and
              x -->{ElementExpression}&amp;{QualifiedName} -->{QualifiedNameQualifier} z and
              (x.name="print" or x.name="println") and
              y.name="out" and z.name="System"
          report x.line as "line" end
  </query>
  <feedback>You have a print statement in line {line}. Are you sure you want to print to console instead of returning?</feedback>
  </rule>
</syntaxhighlight>
Diese Regel sucht nach Aufrufen von <code>System.out.print()</code> oder <code>System.out.println()</code> und melde diese unter Angabe von Klasse und Zeilennummer als Fehler.


=== Kontrollstrukturen ===
=== Kontrollstrukturen ===
Zeile 181: Zeile 206:


=== Methoden ===
=== Methoden ===
<syntaxhighlight lang="xml" line='line'>
<syntaxhighlight lang="xml" line="1">
  <rule type="presence" points="4">
  <rule type="presence" points="4">
   <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}
   <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}
           with
           with
             t.name="A" and
             t.name="A" and
             t -->{TypeDeclarationBodyDeclarations2} m and
             t -->{TypeDeclarationBodyDeclarations1} m and
             hasSignature(m, "public static String method(int)")
             hasSignature(m, "public static String method(int)")
           report 0 end
           report 0 end
Zeile 200: Zeile 225:
           with
           with
             t.name="A" and
             t.name="A" and
             t -->{TypeDeclarationBodyDeclarations2} m and
             t -->{TypeDeclarationBodyDeclarations1} m and
             hasSignature(m, "int method()") and
             hasSignature(m, "int method()") and
             isEmpty(m -->{Child}&amp;{Modifier})
             isEmpty(m -->{Child}&amp;{Modifier})
Zeile 208: Zeile 233:
           with
           with
             t.name="A" and
             t.name="A" and
             t -->{TypeDeclarationBodyDeclarations2} m and
             t -->{TypeDeclarationBodyDeclarations1} m and
             hasSignature(m, "int method()") and
             hasSignature(m, "int method()") and
             m --> mo and not (mo.name="private")
             m --> mo and not (mo.name="private")
Zeile 223: Zeile 248:
           with
           with
               t.name="A" and
               t.name="A" and
               t -->{TypeDeclarationBodyDeclarations2} m and
               t -->{TypeDeclarationBodyDeclarations1} m and
               m.name="m" and
               m.name="m" and
               m -->{MethodDeclarationReturnType} pt and
               m -->{MethodDeclarationReturnType} pt and
               pt -->{ParameterizedTypeType} ptt and
               pt -->{ParameterizedTypeType} ptt and
               ptt.name="B" and
               ptt.name="B" and
               pt -->{ParameterizedTypeTypeArguments1} pta and
               pt -->{ParameterizedTypeTypeArguments} pta and
               pta.name="C"
               pta.name="C"
           report 0 end
           report 0 end
Zeile 244: Zeile 269:
             t.name="A" and
             t.name="A" and
             st.name="B" and
             st.name="B" and
             t -->{TypeDeclarationSuperclassType2} st
             t -->{TypeDeclarationSuperclassType} st
           report 0 end
           report 0 end
   </query>
   </query>
Zeile 257: Zeile 282:
           with
           with
               t.name="A" and
               t.name="A" and
               t -->{TypeDeclarationSuperInterfaceTypes2} st and
               t -->{TypeDeclarationSuperInterfaceTypes} st and
               st.name="B"
               st.name="B"
           report 0 end
           report 0 end
Zeile 271: Zeile 296:
           with
           with
             t.name="A" and
             t.name="A" and
             t -->{TypeDeclarationSuperInterfaceTypes1} pt and
             t -->{TypeDeclarationSuperInterfaceTypes} pt and
             pt -->{ParameterizedTypeType} ptt and
             pt -->{ParameterizedTypeType} ptt and
             ptt.name="B" and
             ptt.name="B" and
             pt -->{ParameterizedTypeTypeArguments1} pta and
             pt -->{ParameterizedTypeTypeArguments} pta and
             pta.name="C"
             pta.name="C"
           report 0 end
           report 0 end
Zeile 287: Zeile 312:
   <query>from u : V{TypeDeclaration}, s : V{SimpleType}
   <query>from u : V{TypeDeclaration}, s : V{SimpleType}
           with
           with
             ((u -->{TypeDeclarationSuperclassType2} s and s.name="Thread") or
             ((u -->{TypeDeclarationSuperclassType} s and s.name="Thread") or
             (u -->{TypeDeclarationSuperInterfaceTypes2} s and s.name="Runnable")) and
             (u -->{TypeDeclarationSuperInterfaceTypes} s and s.name="Runnable")) and
             u.name="A"
             u.name="A"
           report 0 end
           report 0 end
Zeile 352: Zeile 377:
     <query>from x,y : V{Class}
     <query>from x,y : V{Class}
           with
           with
               x --> V{Property} --> V{Association} <-- V{Property} <-- y and
               x --> V{Property} --> V{Association} &lt;-- V{Property} &lt;-- y and
               isDefined(x.name) and x.name="A" and
               isDefined(x.name) and x.name="A" and
               isDefined(y.name) and y.name="B"
               isDefined(y.name) and y.name="B"
Zeile 366: Zeile 391:
     <query>from x,y : V{Class}
     <query>from x,y : V{Class}
           with
           with
               x --> V{Property} --> V{Association} <-- V{Property} <-- y and
               x --> V{Property} --> V{Association} &lt;-- V{Property} &lt;-- y and
               isDefined(x.name) and x.name="A" and
               isDefined(x.name) and x.name="A" and
               isDefined(y.name) and y.name="B"
               isDefined(y.name) and y.name="B"
Zeile 381: Zeile 406:
           with
           with
               x --> z and
               x --> z and
               z --> V{Association} <-- V{Property} <-- y and
               z --> V{Association} &lt;-- V{Property} &lt;-- y and
               isDefined(x.name) and x.name="A" and
               isDefined(x.name) and x.name="A" and
               isDefined(y.name) and y.name="B" and
               isDefined(y.name) and y.name="B" and
Zeile 396: Zeile 421:
     <query>from a,b : V{Class}, p: V{Property}
     <query>from a,b : V{Class}, p: V{Property}
           with
           with
               isEmpty(a -->&{Property} -->&{Association}) and
               isEmpty(a -->&amp;{Property} -->&amp;{Association}) and
               b --> p and
               b --> p and
               isDefined(p.aggregation) and p.aggregation="composite"
               isDefined(p.aggregation) and p.aggregation="composite"
Zeile 428: Zeile 453:
               isDefined(x.name) and x.name="A" and
               isDefined(x.name) and x.name="A" and
               x --> y and
               x --> y and
               isDefined(y.name) and stringLevenshteinDistance(y.name, "ausführen")<3 and
               isDefined(y.name) and stringLevenshteinDistance(y.name, "ausführen")&lt;3 and
               y --> z
               y --> z
           report 1 end
           report 1 end
Zeile 442: Zeile 467:
               from x : set(1)
               from x : set(1)
               with
               with
                 c<>7
                 c&lt;>7
               report c as "count" end
               report c as "count" end
     </query>
     </query>
Zeile 454: Zeile 479:
     <query>from x : V{Class}
     <query>from x : V{Class}
           with
           with
               isDefined(x.name) and x.name=A" and
               isDefined(x.name) and x.name="A" and
               x.isAbstract and
               x.isAbstract and
               not isEmpty(x <--&{Generalization})
               not isEmpty(x &lt;--&amp;{Generalization})
           report 1 end
           report 1 end
     </query>
     </query>
Zeile 481: Zeile 506:
</syntaxhighlight>
</syntaxhighlight>
Diese Regel überprüft, ob das Modell eine Klasse "D" enthält, die drei direkte Unterklassen "A", "B" und "C" hat.
Diese Regel überprüft, ob das Modell eine Klasse "D" enthält, die drei direkte Unterklassen "A", "B" und "C" hat.
== Beispiele für statische Prüfregeln für EPML ==
<syntaxhighlight lang="xml" line='line'>
  <rule type="presence" points="5">
  <query>from x: V{Event}
        with
            isEmpty(x &lt;--)
        report 0 end
  </query>
  <feedback prefix="Fehlerhafte Grundelemente">Es gibt kein Startevent.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel testet, ob der gegebene Graph kein Startevent hat.
<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="5">
  <query> from x,y: V{Event}
  with
    isEmpty(x &lt;--) and
    isEmpty(y &lt;--) and
    not (x=y)
  report 0 end
  </query>
  <feedback prefix="Fehlerhafte Grundelemente">Es gibt mehr als ein Startevent.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel testet, ob der gegebene Graph mehr als ein Startevent hat.
<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="3">
  <query> from x,y: V{Element, ^Connector}
  with
    not (x.name="") and
    x.name = y.name and
    not (x = y)
  report x.name as "name" end
  </query>
  <feedback prefix="Anmerkung zur Namensgebung">Es gibt mindestens zwei Elemente mit demselben Namen ("{name}").</feedback>
  </rule>
</syntaxhighlight>
Diese Regel testet, ob es der Graph Elemente mit demselben Namen besitzt.
<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="4">
  <query>from x: V{Element, ^Connector}, y1, y2 : V{Element}
        with
            x --> y1 and
            x --> y2 and
            not (y1=y2)
        report x.name as "xName", x.id as "xID" end
  </query>
  <feedback prefix="Fehlerhafte Grundstruktur">Das Element "{xName}" (ID {xID}) hat mehr als einen Ausgang.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel testet, ob ein Event oder Funktion mehr als einen Ausgang hat.
<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="4">
  <query>from x: V{Connector}, y: V{Connector}
        with
            not (x.name="") and
            not (y.name="") and
            x --> y
        report x.name as "xName", y.name as "yName", x.id as "xID", y.id as "yID" end
  </query>
  <feedback prefix="Fehlerhafte Grundstruktur">Es dürfen keine zwei Konnektoren direkt aufeinander folgen. Es folgt jedoch "{yName}" (ID {yID}) direkt auf "{xName}" (ID {xID}).</feedback>
  </rule>
</syntaxhighlight>
Diese Regel testet, ob 2 Konnektoren aufeinander folgen.
<syntaxhighlight lang="xml" line='line'>
  <rule type="absence" points="1">
  <query>from x: V{Element, ^Connector}
        with
            contains(x.name, " and ") or
            contains(x.name, "+") or
            contains(x.name, " und ")
        report x.name as "name" end
  </query>
  <feedback prefix="Anmerkung zur Namensgebung">Der Name "{name}" sieht danach aus, als wenn hier zwei Events bzw. Funktionen in einem Element zusammengefasst wurden.</feedback>
  </rule>
</syntaxhighlight>
Diese Regel testet, ob der Graph möglicherweise Zeichen bzw. Wörter besitzt die mehrere Funktionen/Events in einem Element verbinden.


[[Category:R-GReQL]]
[[Category:R-GReQL]]

Aktuelle Version vom 21. März 2024, 12:15 Uhr

Beispiele für statische Prüfregeln für Java-Code

Codestil

 <rule type="absence" points="0">
   <query>from x : V{MethodDeclaration}
          with
             x.name=capitalizeFirst(x.name) and
             x.constructor="false"
          report 0 end
   </query>
   <feedback prefix="Hinweis (ohne Punktabzug)">Du verwendest Methodennamen, die mit einem Großbuchstaben beginnen. Das ist möglich, aber es entspricht nicht dem üblichen Programmierstil für Java.</feedback>
 </rule>

Diese Regel sucht nach groß geschriebenen Methodennamen.

 <rule type="absence" points="0">
   <query>from x : V{TypeDeclaration}
          with
             not (x.name=capitalizeFirst(x.name))
          report 0 end
   </query>
   <feedback prefix="Hinweis (ohne Punktabzug)">Du verwendest Klassennamen, die nicht mit einem Großbuchstaben beginnen. Das ist möglich, aber es entspricht nicht dem üblichen Programmierstil für Java.</feedback>
 </rule>

Diese Regel sucht nach klein geschriebenen Klassennamen.

 <rule type="absence" points="0">
   <query>from x : V{VariableDeclarationFragment}
          with
             x.name=capitalizeFirst(x.name) and
             isEmpty(from m : V{Modifier} with x &lt;--&amp;{FieldDeclaration} --> m and m.name="final" report m end)
          report 0 end
   </query>
 <feedback prefix="Hinweis (ohne Punktabzug)">Du verwendest Variablennamen, die mit einem Großbuchstaben beginnen. Das ist möglich, aber es entspricht nicht dem üblichen Programmierstil für Java.</feedback>
 </rule>

Diese Regel sucht nach groß geschriebenen Variablennamen, wobei als "final" deklarierte Klassenvariablen ausgelassen werden.

Einfache Inhalte

 <rule type="presence" points="2">
   <query>from m : V{MethodDeclaration}, s : V{StringLiteral}
          with
             m.name="m" and
             m -->{Child}* s and
             s.content = "\"Zeichenkette\""
          report 0 end
   </query>
   <feedback>Deine Lösung verwendet nicht den String "Zeichenkette".</feedback>
 </rule>

Diese Regel sucht in der Methode m nach einem String-Literal mit einem vorgegebenen Inhalt.

 <rule type="absence" points="2">
   <query>from m : V{MethodDeclaration}, s : V{StringLiteral}
          with
             m.name="m" and
             m -->{Child}* s and
             stringLength(s.content) > 4
          report s.line as "line" end
   </query>
   <feedback>Du verwendest in Zeile {line} ein festes String-Literal. Ist deine Lösung allgemeingültig?</feedback>
 </rule>

Diese Regel sucht in der Methode m nach einem String-Literal der Länge 4 oder länger (inklusive Anführungszeichen) und meldet es mit Angabe der Zeilennummer als Fehler.

 <rule type="absence" points="0">
   <query>from p : V{PackageDeclaration}
          report 0 end
   </query>
   <feedback prefix="Paketdefinition">Deine Lösung beinhaltet eine package-Angabe. Bitte entferne diese.</feedback>
 </rule>

Diese Regel sucht nach Paketdefinitionen und meldet diese als Fehler.

 <rule type="absence" points="1">
   <query> from p : V{ImportDeclaration}
          report 0 end
  </query>
  <feedback prefix="Importdefinition"> Deine Lösung beinhaltet eine import-Angabe. Bitte entferne diese.</feedback>
 </rule>

Diese Regel sucht nach Importdefinitionen und meldet diese als Fehler.

 <rule type="absence" points="1">
    <query>from u : V{CompilationUnit}, x : V{MethodInvocation}, y : V{SimpleName}
           with
              u -->* x -->{ElementExpression} y and
              x.name="exit" and
              y.name="System"
           report u.name as "name", x.line as "line" end
   </query>
   <feedback>Der Aufruf von "System.exit()" in der Datei {name} in Zeile {line} ist nicht gestattet.</feedback>
 </rule>

Diese Regel sucht nach Aufrufen von System.exit() und melde diese unter Angabe von Klasse und Zeilennummer als Fehler.

  <rule type="absence" points="1">
    <query>from x : V{MethodInvocation}, y, z : V{SimpleName}
           with
              x -->{ElementExpression}&amp;{QualifiedName} -->{QualifiedNameName} y and
              x -->{ElementExpression}&amp;{QualifiedName} -->{QualifiedNameQualifier} z and
              (x.name="print" or x.name="println") and
              y.name="out" and z.name="System"
           report x.line as "line" end
   </query>
   <feedback>You have a print statement in line {line}. Are you sure you want to print to console instead of returning?</feedback>
  </rule>

Diese Regel sucht nach Aufrufen von System.out.print() oder System.out.println() und melde diese unter Angabe von Klasse und Zeilennummer als Fehler.

Kontrollstrukturen

 <rule type="absence" points="4">
   <query>from m : V{MethodDeclaration}
          with
             m.name="m" and
             isEmpty(m -->{Child}*&amp;{WhileStatement}) and
             isEmpty(m -->{Child}*&amp;{DoStatement}) and
             isEmpty(m -->{Child}*&amp;{ForStatement}) and
             isEmpty(m -->{Child}*&amp;{EnhancedForStatement})
          report 0 end
   </query>
   <feedback>In der Methode "m()" wird kein Schleifenkonstrukt verwendet.</feedback>
 </rule>

Diese Regel überprüft, ob Methode m ein beliebiges Schleifenkonstrukt enthält.

 <rule type="absence" points="2">
   <query>from u : V{CompilationUnit}, x : V{IfStatement}
          with
             ( not isEmpty(u -->* x -->{IfStatementThenStatement}&amp;{EmptyStatement}) or
               (not isEmpty(u -->* x -->{IfStatementThenStatement}&amp;{Block}) and isEmpty(u -->* x -->{IfStatementThenStatement}&amp;{Block} -->{Child}))
             ) and
             ( not isEmpty(u -->* x -->{IfStatementElseStatement}&amp;{EmptyStatement}) or
               (not isEmpty(u -->* x -->{IfStatementElseStatement}&amp;{Block}) and isEmpty(u -->* x -->{IfStatementElseStatement}&amp;{Block} -->{Child}))
             )
          report u.name as "name", x.line as "line" end
   </query>
   <feedback>In der Datei {name} enthält das if-Statement in Zeile {line} in beiden Zweigen keinen Code und ist dadurch sinnlos.</feedback>
 </rule>

Diese Regel sucht nach einer if-Anweisung, die nur leere Zweige enthält und meldet eine solche Anweisung als Fehler.

 <rule type="absence" points="2">
   <query>from u : V{CompilationUnit}, x : V{IfStatement}
          with
             not isEmpty(u -->* x -->{IfStatementThenStatement}&amp;{EmptyStatement}) and
             isEmpty(x -->{IfStatementElseStatement}&amp;{Statement})
          report u.name as "name", x.line as "line" end
   </query>
   <feedback>In der Datei {name} endet das if-Statement in Zeile {line} hinter der Bedingung sofort mit einem Semikolon. Die Bedingung ist dadurch wirkungslos und die folgende Anweisung wird immer ausgeführt.</feedback>
 </rule>

Diese Regel sucht nach einer if-Anweisung, die keine Zweige enthält und meldet eine solche Anweisung als Fehler.

 <rule type="absence" points="2">
   <query>from u : V{CompilationUnit}, x : V{WhileStatement}
          with
             not isEmpty(u -->* x -->{WhileStatementBody}&amp;{EmptyStatement}) or
             (not isEmpty(u -->* x -->{WhileStatementBody}&amp;{Block}) and
             isEmpty(u -->* x -->{WhileStatementBody}&amp;{Block} -->{Child}))
          report u.name as "name", x.line as "line" end
   </query>
   <feedback>In der Datei {name} besteht die while-Schleife in Zeile {line} nur aus einer Abbruchbedingung und ist dadurch sinnlos.</feedback>
 </rule>

Diese Regel sucht nach einer while-Schleife, die nur aus einer Abbruchbedingung besteht und meldet eine solche Schleife als Fehler.

 <rule type="presence" points="1">
    <query>from m : V{MethodDeclaration}, n : V{MethodDeclaration}
           with
              m (-->{Child}*&amp;{MethodInvocation} -->{Access}&amp;{MethodDeclaration})* n and
              n -->{Child}*&amp;{MethodInvocation} -->{Access} m and
              m.name="m"
           report 0 end
   </query>
   <feedback prefix="Rekursionscheck"> Die Methode "m()" enthält nicht die geforderte Rekursion.</feedback>
 </rule>

Diese Regel überprüft, ob Methode m rekursiv arbeitet. Dabei ist es egal, ob sich die Methode direkt selber aufruft, oder über einen oder mehrere Zwischenschritte aufgerufen wird.

 <rule type="presence" points="5">
    <query>from m : V{MethodDeclaration}
           with
              m (-->{Child}*&amp;{MethodInvocation} -->{Access}&amp;{MethodDeclaration}) m and
              m.name="m"
           report 0 end
   </query>
   <feedback prefix="Rekursionscheck">Die Methode "m()" enthält nicht die geforderte Rekursion.</feedback>
 </rule>

Diese Regel überprüft, ob Methode m rekursiv arbeitet und sich insbesondere ohne Zwischenschritte über andere Methoden selber wieder aufruft.

Methoden

 <rule type="presence" points="4">
   <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}
          with
             t.name="A" and
             t -->{TypeDeclarationBodyDeclarations1} m and
             hasSignature(m, "public static String method(int)")
          report 0 end
   </query>
   <feedback prefix="Signaturcheck">Die Methode "public static String method(int param)" in der Klasse "A" fehlt. Hast du die vorgegebene Methodensignatur veraendert?</feedback>
 </rule>

Diese Regel überprüft, ob Klasse A eine Methode mit einer bestimmten Signatur enthält, wobei der Name des Methodenparameters unerheblich ist.

 <rule type="presence" points="4">
   <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}
          with
             t.name="A" and
             t -->{TypeDeclarationBodyDeclarations1} m and
             hasSignature(m, "int method()") and
             isEmpty(m -->{Child}&amp;{Modifier})
          report 0 end
   </query>
   <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}, mo : V{Modifier}
          with
             t.name="A" and
             t -->{TypeDeclarationBodyDeclarations1} m and
             hasSignature(m, "int method()") and
             m --> mo and not (mo.name="private")
         report 0 end
   </query>
   <feedback prefix="Signaturcheck">Die Methode "int method()" in der Klasse "A" fehlt oder ist mit dem Modifier "private" versehen. Hast du die vorgegebene Methodensignatur veraendert?</feedback>
 </rule>

Diese Regel überprüft, ob Klasse A eine Methode mit einer bestimmten Signatur enthält, die nicht mit dem Modifier private versehen ist.

 <rule type="presence" points="1">
    <query>from t : V{TypeDeclaration}, m : V{MethodDeclaration}, pt : V{ParameterizedType}, ptt : V{SimpleType}, pta : V{SimpleType}
           with
              t.name="A" and
              t -->{TypeDeclarationBodyDeclarations1} m and
              m.name="m" and
              m -->{MethodDeclarationReturnType} pt and
              pt -->{ParameterizedTypeType} ptt and
              ptt.name="B" and
              pt -->{ParameterizedTypeTypeArguments} pta and
              pta.name="C"
           report 0 end
   </query>
   <feedback prefix="Signatur">Der Methode "public B&lt;C&gt; m()" in der Klasse "A" fehlt. Hast du die vorgegebene Methodensignatur veraendert?</feedback>
 </rule>

Diese Regel überprüft, ob Klasse A eine Methode m mit parametrisierten Rückgabetyp B<C> enthält.

Vererbungshierarchie

 <rule type="presence" points="5">
   <query>from t : V{TypeDeclaration}, st : V{SimpleType}
          with
             t.name="A" and
             st.name="B" and
             t -->{TypeDeclarationSuperclassType} st
          report 0 end
   </query>
   <feedback prefix="Typhierarchie">A ist nicht als Unterklasse von B modelliert.</feedback>
 </rule>

Diese Regel überprüft, ob Klasse A direkte Unterklasse von Klasse B ist.

 <rule type="presence" points="1">
    <query>from t : V{TypeDeclaration}, st : V{SimpleType}
           with
              t.name="A" and
              t -->{TypeDeclarationSuperInterfaceTypes} st and
              st.name="B"
           report 0 end
   </query>
   <feedback prefix="Typhierarchie">A implementiert nicht das Interface B.</feedback>
 </rule>

Diese Regel überprüft, ob Klasse A das Interface B implementiert.

 <rule type="presence" points="1">
   <query>from t : V{TypeDeclaration}, pt : V{ParameterizedType}, ptt : V{SimpleType}, pta : V{SimpleType}
          with
             t.name="A" and
             t -->{TypeDeclarationSuperInterfaceTypes} pt and
             pt -->{ParameterizedTypeType} ptt and
             ptt.name="B" and
             pt -->{ParameterizedTypeTypeArguments} pta and
             pta.name="C"
          report 0 end
   </query>
   <feedback prefix="Typhierarchie">A implementiert nicht das Interface B&lt;C&gt;.</feedback>
 </rule>

Diese Regel überprüft, ob Klasse A das Interface B<C> implementiert.

 <rule type="presence" points="3">
   <query>from u : V{TypeDeclaration}, s : V{SimpleType}
          with
             ((u -->{TypeDeclarationSuperclassType} s and s.name="Thread") or
             (u -->{TypeDeclarationSuperInterfaceTypes} s and s.name="Runnable")) and
             u.name="A"
          report 0 end
   </query>
   <feedback>In der Klasse "A" sollte entweder das Interface "Runnable" implementieren oder von "Thread" erben.</feedback>
 </rule>

Diese Regel überprüft, ob Klasse A das Interface Runnable implementiert oder von Thread erbt.

Aufrufbeziehungen

 <rule type="presence" points="5">
   <query>from u : V{TypeDeclaration}, x : V{MethodInvocation}, y : V{SimpleName}
          with
             u -->* x -->{ElementExpression} y and
             u.name="A" and
             x.name="m" and
             y.name="B"
          report 0 end
   </query>
   <feedback>In der Klasse "A" sollte "B.m()" aufgerufen werden.</feedback>
 </rule>

Diese Regel überprüft, ob Klasse A eine Methode B.m aufruft.

 <rule type="presence" points="5">
   <query>from u : V{TypeDeclaration}, x : V{MethodInvocation}, y : V{SimpleName}, z : V{VariableDeclarationStatement}, f : V{VariableDeclarationFragment}, t : V{SimpleType}
          with
             u -->* x -->{ElementExpression} y and
             u -->* z -->{VariableDeclarationStatementType} t and
             u -->* z -->{VariableDeclarationStatementFragments} f and
             u.name="A" and
             x.name="m" and
             y.name=f.name and
             t.name="B"
          report 0 end
   </query>
   <feedback>In der Klasse "A" sollte "m()" auf einem Objekt vom Typ "B" aufgerufen werden.</feedback>
 </rule>

Diese Regel überprüft, ob Klasse A Methode m auf einem Objekt vom Typ B aufruft.

 <rule type="presence" points="4">
   <query>from u : V{TypeDeclaration}, m : V{MethodDeclaration}, x : V{ClassInstanceCreation}, t : V{SimpleType}
          with
             u -->{Child}* m -->* x -->{ClassInstanceCreationType} t and
             u.name="A" and
             m.name="m" and
             t.name="B"
          report 0 end
   </query>
   <feedback>In der Klasse "A" muss in Methode m() mindestens eine Instanz von "B" erzeugt werden.</feedback>
 </rule>

Diese Regel überprüft, ob Klasse A in Methode m eine Instanz von Klasse B erstellt.

Beispiele für statische Prüfregeln für UML-Modelle im XMI2-Format

Klassendiagramme

  <rule type="presence" points="11">
    <query>from x,y : V{Class}
           with
              x --> V{Property} --> V{Association} &lt;-- V{Property} &lt;-- y and
              isDefined(x.name) and x.name="A" and
              isDefined(y.name) and y.name="B"
           report 1 end
    </query>
    <feedback>Das Diagramm enthält keine Beziehung zwischen einem "A" und einem "B" oder keine Klassen mit diesen Namen.</feedback>
  </rule>

Diese Regel überprüft, ob das Modell zwei Klassen "A" und "B" enthält, die über eine Assoziation verbunden sind.

  <rule type="absence" points="0">
    <query>from x,y : V{Class}
           with
              x --> V{Property} --> V{Association} &lt;-- V{Property} &lt;-- y and
              isDefined(x.name) and x.name="A" and
              isDefined(y.name) and y.name="B"
           report 1 end
    </query>
    <feedback prefix="Hinweis">Im Diagramm sind die "B" eines "A" als eigene Klasse abgebildet. Das kannst du durch eine bessere Modellierung vermeiden.</feedback>
  </rule>

Diese Regel überprüft ebenfalls, ob das Modell zwei Klassen "A" und "B" enthält, die über eine Assoziation verbunden sind, definiert dies aber als unerwünschte Situation mit entsprechendem Feedback.

  <rule type="presence" points="11">
    <query>from x,y : V{Class}, z: V{Property}
           with
              x --> z and
              z --> V{Association} &lt;-- V{Property} &lt;-- y and
              isDefined(x.name) and x.name="A" and
              isDefined(y.name) and y.name="B" and
              isDefined(z.lower) and z.lower="1" and (not isDefined(z.upper) or z.upper="1")
           report 1 end
    </query>
    <feedback>Das Diagramm enthält keine Beziehung zwischen einem "A" und einem "B" mit der Kardinalität 1 oder keine Klassen mit diesen Namen.</feedback>
  </rule>

Diese Regel überprüft, ob das Modell zwei Klassen "A" und "B" enthält, die über eine Assoziation mit Kardinalität 1 (jedes A kennt genau ein B) verbunden sind.

  <rule type="presence" points="5">
    <query>from a,b : V{Class}, p: V{Property}
           with
              isEmpty(a -->&amp;{Property} -->&amp;{Association}) and
              b --> p and
              isDefined(p.aggregation) and p.aggregation="composite"
           report 1 end
    </query>
    <feedback>Es sollte im Diagramm zwei Klassen geben, bei denen die eine keine weiteren Bestandteile hat, während die andere weitere Bestandteile gemäß der Komposition hat.</feedback>
  </rule>

Diese Regel überprüft, ob es im Modell eine Klasse ohne ausgehende Assoziationen gibt und eine weitere, die mindestens eine ausgehende Komposition hat.

  <rule type="presence" points="5">
    <query>from x : V{Class}, y : V{Property}, z : V{PrimitiveType}
           with
              isDefined(x.name) and x.name="A" and
              x --> y and
              isDefined(y.name) and y.name="b" and
              y --> z and
              isDefined(z.name) and z.name="String"
           report 1 end
    </query>
    <feedback>Ein "A" soll ein Attribut für die Eigenschaft "b" bereitstellen.</feedback>
  </rule>

Diese Regel überprüft, ob es im Modell eine Klasse "A" mit dem Attribut "b" vom Typ "String" gibt.

  <rule type="presence" points="5">
    <query>from x : V{Class}, y : V{Operation}, z: V{Parameter}
           with
              isDefined(x.name) and x.name="A" and
              x --> y and
              isDefined(y.name) and stringLevenshteinDistance(y.name, "ausführen")&lt;3 and
              y --> z
           report 1 end
    </query>
    <feedback>Ein "A" soll eine Methode bereitstellen, mit der sie etwas ausführen kann.</feedback>
  </rule>

Diese Regel prüft, ob es im Modell eine Klasse "A" mit einer Operation gibt, deren Name "ausführen" oder ähnlich lautet.

  <rule type="absence" points="4">
    <query>let c := count(from y : V{Operation} with isDefined(y.name) report y end) in
              from x : set(1)
              with
                 c&lt;>7
              report c as "count" end
    </query>
    <feedback>Das Diagramm sollte genau 7 Methoden enthalten, enthält aber {count}.</feedback>
  </rule>

Diese Regel überprüft, ob das Modell genau 7 Methoden enthält und gibt im Falle einer anderen Anzahl diese im Feedback mit aus.

  <rule type="presence" points="5">
    <query>from x : V{Class}
           with
              isDefined(x.name) and x.name="A" and
              x.isAbstract and
              not isEmpty(x &lt;--&amp;{Generalization})
           report 1 end
    </query>
    <feedback>Das Diagramm sollte eine abstrakte Klasse "A" enthalten, von der mindestens eine Klasse erbt.</feedback>
  </rule>

Diese Regel überprüft, ob das Modell eine abstrakte Klasse "A" enthält, auf die in mindestens einer Generalisierung verwiesen wird.

  <rule type="presence" points="5">
    <query>from a,b,c,d : V{Class}
           with
              isDefined(a.name) and a.name="A" and
              isDefined(b.name) and b.name="B" and
              isDefined(c.name) and c.name="C" and
              isDefined(d.name) and d.name="D" and
              a --> V{Generalization} --> d and
              b --> V{Generalization} --> d and
              c --> V{Generalization} --> d
           report 1 end
    </query>
    <feedback>Das Diagramm sollte Klassen "A", "B" und "C" enthalten, die von einer gemeinsamen Oberklasse "D" erben.</feedback>
  </rule>

Diese Regel überprüft, ob das Modell eine Klasse "D" enthält, die drei direkte Unterklassen "A", "B" und "C" hat.

Beispiele für statische Prüfregeln für EPML

  <rule type="presence" points="5">
  	<query>from x: V{Event}
  	       with
  	          isEmpty(x &lt;--)
  	       report 0 end
  	</query>
  	<feedback prefix="Fehlerhafte Grundelemente">Es gibt kein Startevent.</feedback>
  </rule>

Diese Regel testet, ob der gegebene Graph kein Startevent hat.

  <rule type="absence" points="5">
  	<query> from x,y: V{Event}
  		with
  		   isEmpty(x &lt;--) and
  		   isEmpty(y &lt;--) and
  		   not (x=y)
  		report 0 end
  	</query>
  	<feedback prefix="Fehlerhafte Grundelemente">Es gibt mehr als ein Startevent.</feedback>
  </rule>

Diese Regel testet, ob der gegebene Graph mehr als ein Startevent hat.

  <rule type="absence" points="3">
  	<query> from x,y: V{Element, ^Connector}
  		with
  		   not (x.name="") and
  		   x.name = y.name and
  		   not (x = y)
  		report x.name as "name" end
  	</query>
  	<feedback prefix="Anmerkung zur Namensgebung">Es gibt mindestens zwei Elemente mit demselben Namen ("{name}").</feedback>
  </rule>

Diese Regel testet, ob es der Graph Elemente mit demselben Namen besitzt.

  <rule type="absence" points="4">
  	<query>from x: V{Element, ^Connector}, y1, y2 : V{Element}
  	       with
  	          x --> y1 and
  	          x --> y2 and
  	          not (y1=y2)
  	       report x.name as "xName", x.id as "xID" end
  	</query>
  	<feedback prefix="Fehlerhafte Grundstruktur">Das Element "{xName}" (ID {xID}) hat mehr als einen Ausgang.</feedback>
  </rule>

Diese Regel testet, ob ein Event oder Funktion mehr als einen Ausgang hat.

  <rule type="absence" points="4">
  	<query>from x: V{Connector}, y: V{Connector}
  	       with
  	          not (x.name="") and
  	          not (y.name="") and
  	          x --> y
  	       report x.name as "xName", y.name as "yName", x.id as "xID", y.id as "yID" end
  	</query>
  	<feedback prefix="Fehlerhafte Grundstruktur">Es dürfen keine zwei Konnektoren direkt aufeinander folgen. Es folgt jedoch "{yName}" (ID {yID}) direkt auf "{xName}" (ID {xID}).</feedback>
  </rule>

Diese Regel testet, ob 2 Konnektoren aufeinander folgen.

  <rule type="absence" points="1">
  	<query>from x: V{Element, ^Connector}
  	       with
  	          contains(x.name, " and ") or
  	          contains(x.name, "+") or
  	          contains(x.name, " und ")
  	       report x.name as "name" end
  	</query>
  	<feedback prefix="Anmerkung zur Namensgebung">Der Name "{name}" sieht danach aus, als wenn hier zwei Events bzw. Funktionen in einem Element zusammengefasst wurden.</feedback>
  </rule>

Diese Regel testet, ob der Graph möglicherweise Zeichen bzw. Wörter besitzt die mehrere Funktionen/Events in einem Element verbinden.