Improve SysML checkers
diff --git a/plugins/org.polarsys.chess.checkers/META-INF/MANIFEST.MF b/plugins/org.polarsys.chess.checkers/META-INF/MANIFEST.MF
index edc9c77..d0651ae 100644
--- a/plugins/org.polarsys.chess.checkers/META-INF/MANIFEST.MF
+++ b/plugins/org.polarsys.chess.checkers/META-INF/MANIFEST.MF
@@ -25,6 +25,7 @@
org.polarsys.chess.contracts.profile,
org.eclipse.emf.common
Export-Package: org.polarsys.chess.checkers,
- org.polarsys.chess.checkers.core.checkerManager
+ org.polarsys.chess.checkers.core.checkerManager,
+ org.polarsys.chess.checkers.core.impl
Bundle-Activator: org.polarsys.chess.checkers.Activator
Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/Activator.java b/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/Activator.java
index 2614c27..8c9e7b5 100644
--- a/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/Activator.java
+++ b/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/Activator.java
@@ -80,20 +80,8 @@
new TestChecker1("StateMachineChecker2", tags2, 2);*/
- Set<String> tags3 = new HashSet<String>();
- tags3.add("fast");
- tags3.add("warnings");
- tags3.add("errors");
- tags3.add("sysml");
-// NameDistance nameDistance_2 = new NameDistance("Name Distance Checker (2)", tags3);
- new NameDistance("Name Distance Checker (1)", tags3, 1);
-
- Set<String> tags4 = new HashSet<String>();
- tags4.add("fast");
- tags4.add("errors");
- tags4.add("state machine");
-// NameDistance nameDistance_2 = new NameDistance("Name Distance Checker (2)", tags3);
- new StateStatus("State Checker", tags4);
+ new NameDistance(1, 1);
+ new StateStatus();
started = true;
}
diff --git a/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/core/impl/NameDistance.java b/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/core/impl/NameDistance.java
index cc24785..0516012 100644
--- a/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/core/impl/NameDistance.java
+++ b/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/core/impl/NameDistance.java
@@ -2,6 +2,7 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
@@ -27,21 +28,44 @@
*/
public class NameDistance extends Checker {
- /** Minimum distance between two elements; below it, mark as suspect. */
+ /** Minimum distance between two elements; below it, marks as suspect. */
private int threshold = 2;
private Package systemViewPackage;
private static final Logger logger = Logger.getLogger(NameDistance.class);
- private String checkerName;
+ private static final String checkerName = "NameDistance";
- public NameDistance(String unifiedName, Set<String> checkerTags) {
- super(unifiedName, checkerTags);
- checkerName = unifiedName;
+ /**
+ * Creates a name distance checker with default threshold
+ */
+ public NameDistance() {
+ super(checkerName, getTags());
}
- public NameDistance(String unifiedName, Set<String> checkerTags, int threshold) {
- super(unifiedName, checkerTags);
- checkerName = unifiedName;
- this.threshold = threshold;
+ /**
+ * Creates a name distance checker with the given priority
+ * @param priority the priority
+ */
+ public NameDistance(int priority) {
+ super(checkerName, getTags(), priority);
+ }
+
+ /**
+ * Creates a name distance checker with the given priority and threshold
+ * @param priority the priority
+ * @param threshold the threshold to use
+ */
+ public NameDistance(int priority, int threshold) {
+ super(checkerName, getTags(), priority);
+ setThreshold(threshold);
+ }
+
+ private static Set<String> getTags() {
+ Set<String> tags = new HashSet<String>();
+ tags.add("fast");
+ tags.add("warnings");
+ tags.add("errors");
+ tags.add("sysml");
+ return tags;
}
public int getThreshold() {
@@ -54,7 +78,7 @@
@Override
public List<CheckerMessage> check(IProgressMonitor monitor) throws Exception {
- List<CheckerMessage> warnings = new ArrayList<CheckerMessage>();
+ List<CheckerMessage> messages = new ArrayList<CheckerMessage>();
Collection<Class> blocks = null;
try {
blocks = (Collection<Class>) EntityUtil.getInstance().getAllClasses(systemViewPackage);
@@ -64,12 +88,12 @@
monitor.beginTask(unifiedName, blocks.size());
for (Class block : blocks) {
- warnings.addAll(processBlock(block));
+ messages.addAll(processBlock(block));
if (monitor.isCanceled())
throw new Exception("Checker interrupted");
monitor.worked(1);
}
- return warnings;
+ return messages;
}
/**
@@ -80,6 +104,16 @@
* @return a list of warnings
*/
private List<CheckerMessage> processBlock(Class block) {
+ final EList<NamedElement> elements = filterElements(block);
+ return processElements(elements);
+ }
+
+ /**
+ * Creates the list of elements to be analized. Can be overridden if necessary.
+ * @param elements
+ * @return the filtered elements
+ */
+ protected EList<NamedElement> filterElements(Class block) {
final EList<Property> attributes = block.getOwnedAttributes();
final EList<Operation> operations = block.getOwnedOperations();
final EList<Behavior> behaviors = block.getOwnedBehaviors();
@@ -91,9 +125,9 @@
elements.addAll(operations);
elements.addAll(behaviors);
elements.addAll(ports);
- return processElements(elements);
+ return elements;
}
-
+
/**
* Processes the given list of elements.
*
@@ -123,8 +157,8 @@
logger.debug(firstName + " and " + secondName + " distance = " + distance);
if (distance == 0) {
- final String msg = "Term " + first.getName() + " is equal to " + second.getName();
- warnings.add(new CheckerMessage(msg, 2, first, checkerName));
+ final String msg = equalsMsg(first, second);
+ warnings.add(new CheckerMessage(msg, 2, first, unifiedName));
}
if (distance <= threshold) {
similarNames.add(second.getName());
@@ -133,14 +167,23 @@
// If some similarities are found, store the entry in the warnings
if (similarNames.size() > 0) {
- final String msg = "Term " + first.getName() + " is very similar to "
- + String.join(" e ", similarNames);
- warnings.add(new CheckerMessage(msg, 1, first, checkerName));
+ final String msg = similarMsg(first, similarNames);
+ warnings.add(new CheckerMessage(msg, 1, first, unifiedName));
}
}
return warnings;
}
+
+ protected String equalsMsg(NamedElement first, NamedElement second) {
+ return "The term '" + first.getName() + "' is equal to '" + second.getName() +
+ "' in block '" + ((Class) first.getOwner()).getName() + "'";
+ }
+ protected String similarMsg(NamedElement first, ArrayList<String> similarNames) {
+ return "The term '" + first.getName() + "' is very similar to '"
+ + String.join("' and '", similarNames) + "' in block '" + ((Class) first.getOwner()).getName() + "'";
+ }
+
/**
* Removes macro and event prefixes from the name, and put it in lowercase.
*
diff --git a/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/core/impl/StateStatus.java b/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/core/impl/StateStatus.java
index fc6d196..61adb2d 100644
--- a/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/core/impl/StateStatus.java
+++ b/plugins/org.polarsys.chess.checkers/src/org/polarsys/chess/checkers/core/impl/StateStatus.java
@@ -2,9 +2,9 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -21,45 +21,71 @@
public class StateStatus extends Checker {
private Package systemViewPackage;
- private static final Logger logger = Logger.getLogger(NameDistance.class);
+ private static final Logger logger = Logger.getLogger(StateStatus.class);
private final EntityUtil entityUtil = EntityUtil.getInstance();
- private String checkerName;
+ private static final String checkerName = "StateStatus";
- public StateStatus(String unifiedName, Set<String> checkerTags) {
- super(unifiedName, checkerTags);
- checkerName = unifiedName;
+ /**
+ * Creates a state checker
+ */
+ public StateStatus() {
+ super(checkerName, getTags());
+ }
+
+ /**
+ * Creates a state checker with the given priority
+ * @param priority the priority
+ */
+ public StateStatus(int priority) {
+ super(checkerName, getTags(), priority);
+ }
+
+ private static Set<String> getTags() {
+ Set<String> tags = new HashSet<String>();
+ tags.add("fast");
+ tags.add("errors");
+ tags.add("state machine");
+ return tags;
}
@Override
public List<CheckerMessage> check(IProgressMonitor monitor) throws Exception {
- List<CheckerMessage> warnings = new ArrayList<CheckerMessage>();
+ List<CheckerMessage> messages = new ArrayList<CheckerMessage>();
Collection<Class> blocks = null;
- try {
- blocks = (Collection<Class>) EntityUtil.getInstance().getAllClasses(systemViewPackage);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ blocks = getBlocks(systemViewPackage);
monitor.beginTask(unifiedName, blocks.size());
for (Class block : blocks) {
// warnings.addAll(checkForDeadAndUnreachableStates(block));
- warnings.addAll(checkForDeadStates(block));
- warnings.addAll(checkForUnreachableStates(block));
+ messages.addAll(checkForDeadStates(block));
+ messages.addAll(checkForUnreachableStates(block));
if (monitor.isCanceled())
throw new Exception("Checker interrupted");
monitor.worked(1);
-// TimeUnit.SECONDS.sleep(1);
}
-
- return warnings;
+ return messages;
}
/**
+ * Returns the blocks that should be checked inside the model. Can be overwritter if necessary.
+ * @param systemViewPackage
+ * @return
+ */
+ protected Collection<Class> getBlocks(Package systemViewPackage) {
+ try {
+ return (Collection<Class>) EntityUtil.getInstance().getAllClasses(systemViewPackage);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
* A dead state is a state with no transitions to other states.
* @param block
* @return list of errors
*/
- public List<CheckerMessage> checkForDeadStates(Class block) {
+ private List<CheckerMessage> checkForDeadStates(Class block) {
List<CheckerMessage> errors = new ArrayList<CheckerMessage>();
final Set<StateMachine> stateMachines = entityUtil.getNominalStateMachines(block);
@@ -93,9 +119,8 @@
}
}
if (dead) {
- final String msg = "The state '" + state.getName() + "' of block '" +
- block.getName() + "' does not have any transitions to other states";
- errors.add(new CheckerMessage(msg, 2, state, checkerName));
+ final String msg = deadMsg(state, block);
+ errors.add(new CheckerMessage(msg, 2, state, unifiedName));
deadStates.add(state.getName());
}
@@ -116,7 +141,7 @@
* @param block
* @return list of errors
*/
- public List<CheckerMessage> checkForUnreachableStates(Class block) {
+ private List<CheckerMessage> checkForUnreachableStates(Class block) {
List<CheckerMessage> errors = new ArrayList<CheckerMessage>();
final Set<StateMachine> stateMachines = entityUtil.getNominalStateMachines(block);
@@ -145,9 +170,8 @@
}
}
if (unreachable) {
- final String msg = "The state '" + state.getName() + "' of block '" +
- block.getName() + "' is never reachable";
- errors.add(new CheckerMessage(msg, 2, state, checkerName));
+ final String msg = unreachableMsg(state, block);
+ errors.add(new CheckerMessage(msg, 2, state, unifiedName));
unreachableStates.add(state.getName());
}
}
@@ -167,7 +191,7 @@
* @param block
* @return list of errors
*/
- public List<CheckerMessage> checkForDeadAndUnreachableStates(Class block) {
+ private List<CheckerMessage> checkForDeadAndUnreachableStates(Class block) {
List<CheckerMessage> errors = new ArrayList<CheckerMessage>();
final Set<StateMachine> stateMachines = entityUtil.getNominalStateMachines(block);
@@ -221,16 +245,14 @@
}
if ((dead && stateCounter > 2)) {
- final String msg = "The state '" + state.getName() + "' of block '" +
- block.getName() + "' does not have any transitions to other states";
- errors.add(new CheckerMessage(msg, 2, state, checkerName));
+ final String msg = deadMsg(state, block);
+ errors.add(new CheckerMessage(msg, 2, state, unifiedName));
deadStates.add(state.getName());
}
if ((unreachable)) {
- final String msg = "The state '" + state.getName() + "' of block '" +
- block.getName() + "' is never reachable";
- errors.add(new CheckerMessage(msg, 2, state, checkerName));
+ final String msg = unreachableMsg(state, block);
+ errors.add(new CheckerMessage(msg, 2, state, unifiedName));
unreachableStates.add(state.getName());
}
}
@@ -249,6 +271,16 @@
}
return errors;
}
+
+ protected String deadMsg(Vertex state, Class block) {
+ return "The state '" + state.getName() + "' of block '" +
+ block.getName() + "' does not have any transitions to other states";
+ }
+
+ protected String unreachableMsg(Vertex state, Class block) {
+ return "The state '" + state.getName() + "' of block '" +
+ block.getName() + "' is never reachable";
+ }
@Override
public void init() throws Exception {