diff --git a/src/main/java/common/Tag.java b/src/main/java/common/Tag.java index 9cabfdf96dc7fd582a96c2d72046d1b4b355fad7..3926538759b70442856c355e442c0275e209b942 100644 --- a/src/main/java/common/Tag.java +++ b/src/main/java/common/Tag.java @@ -58,4 +58,14 @@ public class Tag { public String getTag() { return tag; } + + public String toString() { return tag;} + + public boolean equals(Tag t) { + if (t == null) { + return false; + } + + return t.toString().compareTo(tag) == 0; + } } diff --git a/src/main/java/common/Tags.java b/src/main/java/common/Tags.java index 57a8cd2a875c73ee8ddf6365690b184ece74c17e..b123d77006035b24e1aadc08e73949872df74ce3 100644 --- a/src/main/java/common/Tags.java +++ b/src/main/java/common/Tags.java @@ -52,10 +52,13 @@ import java.util.ArrayList; */ public class Tags { + public static final String[] DEFAULT_TAGS = {"root", "activated", "deactivated"}; + private ArrayList<Tag> tags; public Tags() { tags = new ArrayList<>(); + makeDefaultTags(); } public boolean hasTag(String s) { @@ -78,4 +81,10 @@ public class Tags { return null; } + public void makeDefaultTags() { + for(String s: DEFAULT_TAGS) { + addTag(s); + } + } + } diff --git a/src/main/java/ui/GTURTLEModeling.java b/src/main/java/ui/GTURTLEModeling.java index 8eaefff1825c998b203e0c9ed4d60b158aac8441..3ae99b9085d8f99041edc9de4fc55ad20398e498 100644 --- a/src/main/java/ui/GTURTLEModeling.java +++ b/src/main/java/ui/GTURTLEModeling.java @@ -52,6 +52,7 @@ import avatartranslator.toturtle.AVATAR2TURTLE; import avatartranslator.touppaal.AVATAR2UPPAAL; import common.ConfigurationTTool; import common.SpecConfigTTool; +import common.Tag; import ddtranslator.DDSyntaxException; import ddtranslator.DDTranslator; import graph.RG; @@ -7958,6 +7959,7 @@ public class GTURTLEModeling { boolean masterMutex = false; boolean enable = true; boolean isNewSet = false; + String tags = null; for (i = 0; i < nl.getLength(); i++) { @@ -8036,6 +8038,8 @@ public class GTURTLEModeling { } else if (elt.getTagName().equals("color")) { color = Integer.decode(elt.getAttribute("value")); colorFound = true; + } else if (elt.getTagName().equals("tags")) { + tags = elt.getAttribute("value"); } } } @@ -8137,6 +8141,13 @@ public class GTURTLEModeling { tgc.setCurrentColor(color); } + if (tags != null) { + TraceManager.addDev("-----------------------------------> Found tags: " + tags); + for(String s: tags.split(" ")) { + tgc.addTag(new Tag(s)); + } + } + tgc.setAsNew(isNewSet); if (referenceId != -1) { diff --git a/src/main/java/ui/ModelParameters.java b/src/main/java/ui/ModelParameters.java index 70203378148f9f6f8cedcf7392a0ec35dbb74e92..4a12b3fdeef3b25e095ef20e430e376d19dd43e6 100644 --- a/src/main/java/ui/ModelParameters.java +++ b/src/main/java/ui/ModelParameters.java @@ -63,9 +63,10 @@ public class ModelParameters { "ANIMATE_WITH_INFO_DIPLO_SIM", // Diplo simulator "OPEN_DIAG_DIPLO_SIM", // Diplo simulator "LAST_SELECTED_MAIN_TAB", - "LAST_SELECTED_SUB_TAB" + "LAST_SELECTED_SUB_TAB", + "TAGS", "SHOW_TAGS" }; - private static String[] values = {"true", "true", "true", "true", "false", "0", "0"}; + private static String[] values = {"true", "true", "true", "true", "false", "0", "0", "deactivated root", "true"}; public static boolean getBooleanValueFromID(String value) { for(int i=0; i<ids.length; i++) { @@ -85,6 +86,15 @@ public class ModelParameters { return 0; } + public static String getStringValueFromID(String value) { + for(int i=0; i<ids.length; i++) { + if (ids[i].compareTo(value) == 0) { + return values[i]; + } + } + return null; + } + public static String toXML() { String ret = ""; for(int i=0; i<ids.length; i++) { diff --git a/src/main/java/ui/TDiagramPanel.java b/src/main/java/ui/TDiagramPanel.java index f51b1f621b1422c54e00dea17b0c75df189ae683..343aac198aeffbc0b2b31b1f753137855d3a9167 100644 --- a/src/main/java/ui/TDiagramPanel.java +++ b/src/main/java/ui/TDiagramPanel.java @@ -39,13 +39,12 @@ package ui; import avatartranslator.ElementWithNew; +import common.Tag; import myutil.GenericTree; import myutil.GraphicLib; import myutil.TraceManager; import myutilsvg.SVGGeneration; import myutilsvg.SVGGraphics; -import tmltranslator.TMLActivityElement; -import tmltranslator.TMLTask; import ui.atd.ATDAttack; import ui.atd.ATDBlock; import ui.avatarad.AvatarADActivity; @@ -146,7 +145,7 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { protected TGComponent componentHovered; // popupmenus - protected ActionListener menuAL; + protected ActionListener menuAL, menuAddTag, menuRemoveTag; protected JPopupMenu diagramMenu; protected JPopupMenu componentMenu; protected JPopupMenu selectedMenu; @@ -154,11 +153,12 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { protected JMenuItem remove, edit, clone, bringFront, bringBack, makeSquare, setJavaCode, removeJavaCode, setInternalComment, removeInternalComment, attach, detach, hide, unhide, search, enableDisable, setAsCryptoBlock, setAsRegularBlock, setMainColor, setDefaultColor, tosysmlv2, toText, setAsNew, showStats; + protected JMenu addTagMenu, removeTagMenu; protected JMenuItem checkAccessibility, checkInvariant, checkMasterMutex, checkLatency; protected JMenuItem gotoReference; protected JMenuItem showProVerifTrace; protected JMenuItem breakpoint; - protected JMenuItem paste, insertLibrary, upX, upY, downX, downY, fitToContent, backToMainDiagram; + protected JMenuItem paste, insertLibrary, upX, upY, downX, downY, fitToContent, backToMainDiagram, showTagsMenuItem; protected JMenuItem cut, copy, saveAsLibrary, captureSelected; //author:huytruong //search dialog @@ -188,6 +188,7 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { private double fontModifier = 1.0; private boolean draw; + private boolean showTags; // Issue #14 point 10: Always use the current graphics //private Graphics lastGraphics; @@ -485,6 +486,10 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { } public void basicPaintMyComponents(Graphics g) { + + showTags = ModelParameters.getBooleanValueFromID("SHOW_TAGS"); + TraceManager.addDev("Showing tags? " + showTags); + TGComponent tgc; for (int i = componentList.size() - 1; i >= 0; i--) { tgc = this.componentList.get(i); @@ -497,6 +502,10 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { } } + public boolean showTags() { + return showTags; + } + private Font fontToUse = null; public void paintMyComponents(Graphics g, boolean b, double w, double h) { @@ -506,6 +515,9 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { return; } + showTags = ModelParameters.getBooleanValueFromID("SHOW_TAGS"); + //TraceManager.addDev("Showing tags? " + showTags); + if (this.fontToUse == null) this.fontToUse = g.getFont(); else @@ -1602,6 +1614,32 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { componentMenu.add(checkInvariant); componentMenu.add(checkLatency); componentMenu.add(gotoReference); + addTagMenu = new JMenu("addTag"); + String fullTags = ModelParameters.getStringValueFromID("TAGS"); + if (fullTags != null) { + String tags[] = fullTags.split(" "); + for(int i=0; i<tags.length; i++) { + if (!tgc.hasTag(tags[i])) { + JMenuItem jmi = new JMenuItem(tags[i]); + jmi.addActionListener(menuAddTag); + addTagMenu.add(jmi); + } + } + } + componentMenu.add(addTagMenu); + removeTagMenu = new JMenu("removeTag"); + if (tgc.getTags() != null) { + for(Tag t: tgc.getTags()) { + JMenuItem jmi = new JMenuItem(t.toString()); + jmi.addActionListener(menuRemoveTag); + removeTagMenu.add(jmi); + } + + } + componentMenu.add(removeTagMenu); + + + componentMenu.add(removeTagMenu); componentMenu.add(showProVerifTrace); componentMenu.add(checkMasterMutex); componentMenu.add(breakpoint); @@ -1629,6 +1667,7 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { diagramMenu.add(downY); diagramMenu.add(fitToContent); diagramMenu.add(backToMainDiagram); + diagramMenu.add(showTagsMenuItem); diagramMenu.add(tosysmlv2); diagramMenu.add(toText); diagramMenu.add(showStats); @@ -1655,6 +1694,20 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { } }; + menuAddTag = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + popupAddTag(e); + } + }; + + menuRemoveTag = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + popupRemoveTag(e); + } + }; + remove = new JMenuItem("Remove"); remove.addActionListener(menuAL); @@ -1732,6 +1785,9 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { gotoReference = new JMenuItem("Go to reference"); gotoReference.addActionListener(menuAL); + + + showProVerifTrace = new JMenuItem("Show attack trace"); showProVerifTrace.addActionListener(menuAL); @@ -1780,6 +1836,17 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { } }); + showTagsMenuItem = new JMenuItem("show / unshow tags"); + showTagsMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + boolean b = ModelParameters.getBooleanValueFromID("SHOW_TAGS"); + ModelParameters.setValueForID("SHOW_TAGS", "" + !b); + repaint(); + } + }); + tosysmlv2 = new JMenuItem("to SysML V2"); tosysmlv2.addActionListener(new ActionListener() { @@ -1875,6 +1942,18 @@ public abstract class TDiagramPanel extends JPanel implements GenericTree { } } + private void popupAddTag(ActionEvent e) { + String s = e.getActionCommand(); + componentPopup.addTag(new Tag(s)); + repaint(); + } + + private void popupRemoveTag(ActionEvent e) { + String s = e.getActionCommand(); + componentPopup.removeTag(s); + repaint(); + } + private void popupAction(ActionEvent e) { if (e.getSource() == remove) { removeComponent(componentPopup); diff --git a/src/main/java/ui/TGComponent.java b/src/main/java/ui/TGComponent.java index 321a78b3ac8b1fb48bd5264c5177fa6a995461c3..ec1644474af2999563cf121b5b8c839bba5dcff5 100644 --- a/src/main/java/ui/TGComponent.java +++ b/src/main/java/ui/TGComponent.java @@ -41,6 +41,7 @@ package ui; import avatartranslator.ElementWithUUID; +import common.Tag; import myutil.*; import org.w3c.dom.NodeList; import tmltranslator.simulation.SimulationTransaction; @@ -162,6 +163,9 @@ public abstract class TGComponent extends AbstractCDElement implements /*CDEleme protected boolean userResizable; protected boolean hidden; + // Tags + public ArrayList<Tag> tags; + //Associated transactions public String transaction = ""; public List<SimulationTransaction> transactions = new ArrayList<SimulationTransaction>(); @@ -212,7 +216,7 @@ public abstract class TGComponent extends AbstractCDElement implements /*CDEleme protected boolean mutualExclusionWithMasterMutex; protected String nameOfMasterStateMutex; - protected HashSet<String> tags; + protected HashSet<String> annotations; protected boolean breakpoint; @@ -1047,15 +1051,15 @@ public abstract class TGComponent extends AbstractCDElement implements /*CDEleme } - public void addTag(String tag) { - if (tags == null) { - tags = new HashSet<>(); + public void addAnnotation(String tag) { + if (annotations == null) { + annotations = new HashSet<>(); } - tags.add(tag); + annotations.add(tag); } - public void clearTag() { - tags = null; + public void clearAnnotations() { + annotations = null; } /** @@ -1183,19 +1187,35 @@ public abstract class TGComponent extends AbstractCDElement implements /*CDEleme g.setFont(f); } - if ((tags != null) && (tags.size() > 0)) { + if ((annotations != null) && (annotations.size() > 0)) { g.setColor(ColorManager.ATD_ROOT_ATTACK); Font f = g.getFont(); g.setFont(f.deriveFont(Font.BOLD)); String tag = ""; - for(String s: tags) { + for(String s: annotations) { tag += "\"" + s + "\" "; } g.drawString(tag.trim(), x + width + 2, y + height/2); g.setFont(f); } + if (tdp.showTags()) { + if ((tags != null) && (tags.size() > 0)) { + g.setColor(ColorManager.ATD_ROOT_ATTACK); + Font f = g.getFont(); + g.setFont(f.deriveFont(Font.BOLD)); + + String tag = ""; + for (Tag t : tags) { + tag += "\"" + t + "\" "; + } + g.drawString(tag.trim(), x + width + 2, y + height / 3); + g.setFont(f); + } + } + + if (TDiagramPanel.DIPLO_ANIMATE_ON) { if (!((this instanceof TGConnector) || (this instanceof TGCNote) || (this instanceof TMLArchiFirewallNode))) { @@ -3356,6 +3376,7 @@ public abstract class TGComponent extends AbstractCDElement implements /*CDEleme sb.append(translateMasterMutex()); sb.append(translateBreakpoint()); sb.append(translateColor()); + sb.append(translateTags()); sb.append(translateExtraParam()); if (b) { @@ -3525,6 +3546,22 @@ public abstract class TGComponent extends AbstractCDElement implements /*CDEleme return "<color value=\"" + currentMainColor.getRGB() + "\" />\n"; } + protected String translateTags() { + if (tags == null) { + //TraceManager.addDev("Current color: null"); + return ""; + } + + String allTags = ""; + for(Tag t: tags) { + allTags += t.toString() + " "; + } + + //TraceManager.addDev("Instance color customizable ok"); + + return "<tags value=\"" + allTags.trim() + "\" />\n"; + } + protected String translateExtraParam() { return ""; } @@ -3615,7 +3652,7 @@ public abstract class TGComponent extends AbstractCDElement implements /*CDEleme reachability = ACCESSIBILITY_UNKNOWN; liveness = ACCESSIBILITY_UNKNOWN; mutex = MUTEX_NOT_YET_STUDIED; - tags = null; + clearAnnotations(); } @Override @@ -3864,5 +3901,62 @@ public abstract class TGComponent extends AbstractCDElement implements /*CDEleme return Math.sqrt(Math.pow(tgc2.getX() - getX(), 2) + Math.pow(tgc2.getY() - getY(), 2)); } + // Tags + public boolean hasTag(String tag) { + if (tags == null) { + return false; + } + + for(Tag g: tags) { + if (g.toString().compareTo(tag) == 0) { + return true; + } + } + + return false; + } + + public void addTag(Tag tag) { + if ((tag == null) || (tag.getTag().length() == 0)) { + return; + } + + + if (tags == null) { + tags = new ArrayList<>(); + } + // check that the component does not have already this tag + for(Tag t: tags) { + if (t.toString().compareTo(tag.toString()) == 0) { + return; + } + } + tags.add(tag); + } + + public List<Tag> getTags() { + return tags; + } + + public void removeTag(String s) { + if (tags == null) { + return; + } + + int index = 0; + boolean found = false; + for(Tag t: tags) { + if (t.toString().compareTo(s) == 0) { + found = true; + break; + } + index ++; + } + + if (found) { + tags.remove(index); + } + } + } diff --git a/src/main/java/ui/window/JDialogAvatarModelChecker.java b/src/main/java/ui/window/JDialogAvatarModelChecker.java index 113f8a823f5f1748a123a62bdd80f858d2b2f77f..cfa15a691f65276aac3fd3c008704649e47dd720 100644 --- a/src/main/java/ui/window/JDialogAvatarModelChecker.java +++ b/src/main/java/ui/window/JDialogAvatarModelChecker.java @@ -1273,7 +1273,7 @@ public class JDialogAvatarModelChecker extends javax.swing.JFrame implements Act if (ase.getReferenceObject() != null) { if (ase.getReferenceObject() instanceof TGComponent) { TGComponent tgc = (TGComponent) (ase.getReferenceObject()); - tgc.addTag("Deadlock (in at least one execution path)"); + tgc.addAnnotation("Deadlock (in at least one execution path)"); } } }