From 6deac6d853eb87a493b1c3b9646d52f85d6034ae Mon Sep 17 00:00:00 2001 From: Letitia Li <letitia.li@telecom-paristech.fr> Date: Thu, 19 Jan 2017 16:31:08 +0100 Subject: [PATCH] Autocomplete for security pragmas --- src/ui/avatarbd/AvatarBDPanel.java | 22 ++- src/ui/avatarbd/AvatarBDPragma.java | 216 +++++++++++----------- src/ui/avatarbd/AvatarBDSafetyPragma.java | 2 +- src/ui/window/JDialogPragma.java | 104 +++++++++-- 4 files changed, 208 insertions(+), 136 deletions(-) diff --git a/src/ui/avatarbd/AvatarBDPanel.java b/src/ui/avatarbd/AvatarBDPanel.java index ae1e590a8e..5d703efcee 100644 --- a/src/ui/avatarbd/AvatarBDPanel.java +++ b/src/ui/avatarbd/AvatarBDPanel.java @@ -420,18 +420,22 @@ public class AvatarBDPanel extends TDiagramPanel { } } - public HashMap<String, List<String>> getBlockStrings(){ - HashMap<String,List<String>> blockAttributeMap = new HashMap<String, List<String>>(); + public HashMap<String, List<String>> getBlockStrings(boolean addAttributes, boolean addStates){ + HashMap<String,List<String>> blockStringMap = new HashMap<String, List<String>>(); for (AvatarBDBlock block: getFullBlockList()){ - List<String> attrs = new ArrayList<String>(); - for (TAttribute attr: getAllAttributesOfBlock(block.getBlockName())){ - attrs.add(attr.getId()); + List<String> strs = new ArrayList<String>(); + if (addAttributes){ + for (TAttribute attr: getAllAttributesOfBlock(block.getBlockName())){ + strs.add(attr.getId()); + } } - AvatarSMDPanel smd = block.getAvatarSMDPanel(); - attrs.addAll(smd.getAllStates()); - blockAttributeMap.put(block.getBlockName(), attrs); + if (addStates){ + AvatarSMDPanel smd = block.getAvatarSMDPanel(); + strs.addAll(smd.getAllStates()); + } + blockStringMap.put(block.getBlockName(), strs); } - return blockAttributeMap; + return blockStringMap; } public LinkedList<AvatarBDStateMachineOwner> getFullStateMachineOwnerList() { diff --git a/src/ui/avatarbd/AvatarBDPragma.java b/src/ui/avatarbd/AvatarBDPragma.java index 6ec8090bc1..f1602a4e9d 100755 --- a/src/ui/avatarbd/AvatarBDPragma.java +++ b/src/ui/avatarbd/AvatarBDPragma.java @@ -94,28 +94,28 @@ public class AvatarBDPragma extends TGCScalableWithoutInternalComponent { height = 30; minWidth = 80; minHeight = 10; - models = new LinkedList<String>(); - properties = new LinkedList<String>(); - authStrongMap = new HashMap<String, Integer>(); - authWeakMap = new HashMap<String, Integer>(); + models = new LinkedList<String>(); + properties = new LinkedList<String>(); + authStrongMap = new HashMap<String, Integer>(); + authWeakMap = new HashMap<String, Integer>(); oldScaleFactor = tdp.getZoom(); nbConnectingPoint = 0; //addTGConnectingPointsComment(); - int len = makeTGConnectingPointsComment(16); - int decw = 0; - int dech = 0; - for(int i=0; i<2; i++) { - connectingPoint[len] = new TGConnectingPointComment(this, 0, 0, true, true, 0.0 + decw, 0.0 + dech); - connectingPoint[len + 1 ] = new TGConnectingPointComment(this, 0, 0, true, true, 0.5 + decw, 0.0 + dech); - connectingPoint[len + 2 ] = new TGConnectingPointComment(this, 0, 0, true, true, 1.0 + decw, 0.0 + dech); - connectingPoint[len + 3 ] = new TGConnectingPointComment(this, 0, 0, true, true, 0.0 + decw, 0.5 + dech); - connectingPoint[len + 4 ] = new TGConnectingPointComment(this, 0, 0, true, true, 1.0 + decw, 0.5 + dech); - connectingPoint[len + 5 ] = new TGConnectingPointComment(this, 0, 0, true, true, 0.0 + decw, 1.0 + dech); - connectingPoint[len + 6 ] = new TGConnectingPointComment(this, 0, 0, true, true, 0.5 + decw, 1.0 + dech); - connectingPoint[len + 7 ] = new TGConnectingPointComment(this, 0, 0, true, true, 0.9 + decw, 1.0 + dech); - len += 8; - } + int len = makeTGConnectingPointsComment(16); + int decw = 0; + int dech = 0; + for(int i=0; i<2; i++) { + connectingPoint[len] = new TGConnectingPointComment(this, 0, 0, true, true, 0.0 + decw, 0.0 + dech); + connectingPoint[len + 1 ] = new TGConnectingPointComment(this, 0, 0, true, true, 0.5 + decw, 0.0 + dech); + connectingPoint[len + 2 ] = new TGConnectingPointComment(this, 0, 0, true, true, 1.0 + decw, 0.0 + dech); + connectingPoint[len + 3 ] = new TGConnectingPointComment(this, 0, 0, true, true, 0.0 + decw, 0.5 + dech); + connectingPoint[len + 4 ] = new TGConnectingPointComment(this, 0, 0, true, true, 1.0 + decw, 0.5 + dech); + connectingPoint[len + 5 ] = new TGConnectingPointComment(this, 0, 0, true, true, 0.0 + decw, 1.0 + dech); + connectingPoint[len + 6 ] = new TGConnectingPointComment(this, 0, 0, true, true, 0.5 + decw, 1.0 + dech); + connectingPoint[len + 7 ] = new TGConnectingPointComment(this, 0, 0, true, true, 0.9 + decw, 1.0 + dech); + len += 8; + } moveable = true; editable = true; @@ -131,11 +131,11 @@ public class AvatarBDPragma extends TGCScalableWithoutInternalComponent { return values; } public void setValues(String[] v){ - values=v; - makeValue(); + values=v; + makeValue(); } public LinkedList<String> getProperties() { - return properties; + return properties; } public void internalDrawing(Graphics g) { @@ -177,11 +177,11 @@ public class AvatarBDPragma extends TGCScalableWithoutInternalComponent { * from the Graphics object. * Thus we use a saved FontMetrics object in TDiagramPanel that only changes when zoom changes. */ - int desiredWidth = Math.max(this.minWidth, 2*this.tdp.stringWidth(g, "Property Pragma") + marginX+ textX); + int desiredWidth = Math.max(this.minWidth, 2*this.tdp.stringWidth(g, "Property Pragma") + marginX+ textX); for(int i=0; i< values.length; i++) desiredWidth = Math.max(desiredWidth, this.tdp.stringWidth(g, values[i]) + marginX+textX); -// currentFontSize= 5; + // currentFontSize= 5; int desiredHeight = ((models.size() + properties.size()+4)*currentFontSize) + textY + 1; //TraceManager.addDev("resize: " + desiredWidth + "," + desiredHeight); @@ -212,32 +212,32 @@ public class AvatarBDPragma extends TGCScalableWithoutInternalComponent { g.setColor(c); - int i = 1; - Font heading = new Font("heading", Font.BOLD, this.tdp.getFontSize ()*7/6); - g.setFont(heading); - g.drawString("Model Pragma", x+textX, y+textY + currentFontSize); - g.setFont(fold); - for (String s: models){ - g.drawString(s, x + textX, y + textY + (i+1)* currentFontSize); - i++; - } + int i = 1; + Font heading = new Font("heading", Font.BOLD, this.tdp.getFontSize ()*7/6); + g.setFont(heading); + g.drawString("Model Pragma", x+textX, y+textY + currentFontSize); + g.setFont(fold); + for (String s: models){ + g.drawString(s, x + textX, y + textY + (i+1)* currentFontSize); + i++; + } // FIXME: why the empty string ? - g.drawString(" ", x+ textX, y+ textY+(i+1)*currentFontSize); - i++; - g.drawLine(x, y+textY/2+i*currentFontSize, x+width, y+textY/2+i*currentFontSize); - g.setFont(heading); - g.drawString("Property Pragma", x+textX, y+textY+(i+1)* currentFontSize); - g.setFont(fold); - i++; - for (String s: properties){ - if (authStrongMap.containsKey(s) || authWeakMap.containsKey(s)){ - g.setFont(new Font("tmp", Font.PLAIN, 7)); - drawConfidentialityVerification(s, g, x+ lockX, y + lockY + (i+1)*currentFontSize); + g.drawString(" ", x+ textX, y+ textY+(i+1)*currentFontSize); + i++; + g.drawLine(x, y+textY/2+i*currentFontSize, x+width, y+textY/2+i*currentFontSize); + g.setFont(heading); + g.drawString("Property Pragma", x+textX, y+textY+(i+1)* currentFontSize); g.setFont(fold); - } - g.drawString(s, x + textX, y + textY + (i+1)* currentFontSize); - i++; - } + i++; + for (String s: properties){ + if (authStrongMap.containsKey(s) || authWeakMap.containsKey(s)){ + g.setFont(new Font("tmp", Font.PLAIN, 7)); + drawConfidentialityVerification(s, g, x+ lockX, y + lockY + (i+1)*currentFontSize); + g.setFont(fold); + } + g.drawString(s, x + textX, y + textY + (i+1)* currentFontSize); + i++; + } /* for (int i = 0; i<values.length; i++) { //TraceManager.addDev("x+texX=" + (x + textX) + " y+textY=" + y + textY + i* h + ": " + values[i]); @@ -250,24 +250,24 @@ public class AvatarBDPragma extends TGCScalableWithoutInternalComponent { public void makeValue() { values = Conversion.wrapText(value); - models.clear(); - properties.clear(); - for (String s: values){ - if (s.isEmpty() || s.split(" ").length < 1){ - //Ignore - } - else if (Arrays.asList(mPragma).contains(s.split(" ")[0])){ - models.add(s); - } - else if (Arrays.asList(pPragma).contains(s.split(" ")[0])){ - properties.add(s); - } - else { - //Warning Message - JOptionPane.showMessageDialog(null, s + " is not a valid pragma.", "Invalid Pragma", + models.clear(); + properties.clear(); + for (String s: values){ + if (s.isEmpty() || s.split(" ").length < 1){ + //Ignore + } + else if (Arrays.asList(mPragma).contains(s.split(" ")[0])){ + models.add(s); + } + else if (Arrays.asList(pPragma).contains(s.split(" ")[0])){ + properties.add(s); + } + else { + //Warning Message + JOptionPane.showMessageDialog(null, s + " is not a valid pragma.", "Invalid Pragma", JOptionPane.INFORMATION_MESSAGE); - } - } + } + } //checkMySize(); } @@ -289,64 +289,63 @@ public class AvatarBDPragma extends TGCScalableWithoutInternalComponent { private void drawConfidentialityVerification(String s, Graphics g, int _x, int _y) { Color c = g.getColor(); Color c1; - Color c2; - int confStatus; - if (authStrongMap.containsKey(s)){ - confStatus = authStrongMap.get(s); - switch(confStatus) { - case PROVED_TRUE: + Color c2; + int confStatus; + if (authStrongMap.containsKey(s)){ + confStatus = authStrongMap.get(s); + switch(confStatus) { + case PROVED_TRUE: c1 = Color.green; - break; - case PROVED_FALSE: + break; + case PROVED_FALSE: c1 = Color.red; break; - case NOT_PROVED: - c1 = Color.gray; - break; - default: + case NOT_PROVED: + c1 = Color.gray; + break; + default: return; } - } else { - c1 = Color.gray; - } - - if (authWeakMap.containsKey(s)){ - confStatus = authWeakMap.get(s); - switch(confStatus) { - case PROVED_TRUE: + } else { + c1 = Color.gray; + } + if (authWeakMap.containsKey(s)){ + confStatus = authWeakMap.get(s); + switch(confStatus) { + case PROVED_TRUE: c2 = Color.green; - break; - case PROVED_FALSE: + break; + case PROVED_FALSE: c2 = Color.red; break; - case NOT_PROVED: - c2 = Color.gray; - break; - default: + case NOT_PROVED: + c2 = Color.gray; + break; + default: return; } - } else { - c2 = c1; - } + } else { + c2 = c1; + } - g.drawOval(_x+6, _y-16, 10, 15); - g.setColor(c1); - int[] xps = new int[]{_x+4, _x+4, _x+20}; - int[] yps = new int[]{_y-10, _y+4, _y+4}; - int[] xpw = new int[]{_x+20, _x+20, _x+4}; - int[] ypw = new int[]{_y+4, _y-10, _y-10}; - g.fillPolygon(xps, yps,3); + g.drawOval(_x+6, _y-16, 10, 15); + g.setColor(c1); + int[] xps = new int[]{_x+4, _x+4, _x+20}; + int[] yps = new int[]{_y-10, _y+4, _y+4}; + int[] xpw = new int[]{_x+20, _x+20, _x+4}; + int[] ypw = new int[]{_y+4, _y-10, _y-10}; + g.fillPolygon(xps, yps,3); - g.setColor(c2); - g.fillPolygon(xpw, ypw, 3); + g.setColor(c2); + g.fillPolygon(xpw, ypw, 3); // g.fillRect(_x+4, _y-7, 18, 14); - g.setColor(c); + g.setColor(c); // g.drawRect(_x+4, _y-7, 18, 14); - g.drawPolygon(xps, yps,3); - g.drawPolygon(xpw, ypw, 3); - g.drawString("S", _x+6, _y+2); - g.drawString("W", _x+13, _y-2); + g.drawPolygon(xps, yps,3); + g.drawPolygon(xpw, ypw, 3); + g.drawString("S", _x+6, _y+2); + g.drawString("W", _x+13, _y-2); // if (c1==Color.gray){ // g.drawString("?", _x+4, _y+2); // } @@ -357,6 +356,9 @@ public class AvatarBDPragma extends TGCScalableWithoutInternalComponent { JDialogPragma jdn = new JDialogPragma(frame, "Setting the pragma", value); //jdn.setLocation(200, 150); + AvatarBDPanel abdp = (AvatarBDPanel) tdp; + jdn.blockAttributeMap = abdp.getBlockStrings(true,false); + jdn.blockStateMap = abdp.getBlockStrings(false,true); GraphicLib.centerOnParent(jdn); jdn.show(); // blocked until dialog has been closed diff --git a/src/ui/avatarbd/AvatarBDSafetyPragma.java b/src/ui/avatarbd/AvatarBDSafetyPragma.java index a0aaf29a04..ec38f3077b 100644 --- a/src/ui/avatarbd/AvatarBDSafetyPragma.java +++ b/src/ui/avatarbd/AvatarBDSafetyPragma.java @@ -256,7 +256,7 @@ public class AvatarBDSafetyPragma extends TGCScalableWithoutInternalComponent { //jdn.setLocation(200, 150); GraphicLib.centerOnParent(jdn); AvatarBDPanel abdp = (AvatarBDPanel) tdp; - jdn.blockAttributeMap = abdp.getBlockStrings(); + jdn.blockAttributeMap = abdp.getBlockStrings(true,true); jdn.show(); // blocked until dialog has been closed String s = jdn.getText(); diff --git a/src/ui/window/JDialogPragma.java b/src/ui/window/JDialogPragma.java index 0995477281..acc9bfe2b0 100755 --- a/src/ui/window/JDialogPragma.java +++ b/src/ui/window/JDialogPragma.java @@ -52,6 +52,7 @@ import javax.swing.*; import javax.swing.text.*; import ui.*; import java.util.*; +import java.util.regex.*; public class JDialogPragma extends javax.swing.JDialog implements ActionListener { @@ -64,7 +65,8 @@ public class JDialogPragma extends javax.swing.JDialog implements ActionListener protected JMenuBar menuBar; protected JMenu help; protected JPopupMenu helpPopup; - + public HashMap<String, java.util.List<String>> blockAttributeMap = new HashMap<String, java.util.List<String>>(); + public HashMap<String, java.util.List<String>> blockStateMap = new HashMap<String, java.util.List<String>>(); /** Creates new form */ public JDialogPragma(Frame f, String title, String _text) { super(f, title, true); @@ -76,24 +78,24 @@ public class JDialogPragma extends javax.swing.JDialog implements ActionListener //Suggestion Panel code from: http://stackoverflow.com/questions/10873748/how-to-show-autocomplete-as-i-type-in-jtextarea public class SuggestionPanel { - private final String[] pragma = {"#Authenticity", "#Confidentiality", "#PublicConstant", "#PrivateConstant", "#InitialSessionKnowledge", "#InitialSystemKnowledge", "#PrivatePublicKeys", "#Public", "#SecrecyAssumption", "#Secret"}; - private JList list; + private final String[] pragma = {"#Authenticity", "#Confidentiality", "#PublicConstant", "#PrivateConstant", "#InitialSessionKnowledge", "#InitialSystemKnowledge", "#PrivatePublicKeys", "#Public", "#SecrecyAssumption", "#Secret"}; + private JList list; private JPopupMenu popupMenu; private String subWord; private final int insertionPosition; - public SuggestionPanel(JTextArea textarea, int position, String subWord, Point location) { + public SuggestionPanel(JTextArea textarea, int position, String subWord, Point location, String header) { this.insertionPosition = position; this.subWord = subWord; popupMenu = new JPopupMenu(); popupMenu.removeAll(); popupMenu.setOpaque(false); popupMenu.setBorder(null); - popupMenu.add(list = createSuggestionList(position, subWord), BorderLayout.CENTER); - //Show popupMenu only if there are matching suggestions - if (list.getModel().getSize() >0){ + popupMenu.add(list = createSuggestionList(position, subWord, header), BorderLayout.CENTER); + //Show popupMenu only if there are matching suggestions + if (list.getModel().getSize() >0){ popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + location.y); - } + } } public void hide() { @@ -103,16 +105,62 @@ public class JDialogPragma extends javax.swing.JDialog implements ActionListener } } - private JList createSuggestionList(final int position, final String subWord) { - ArrayList<String> matches = new ArrayList<String>(); - if (subWord.startsWith("#")){ - for (String p: pragma) { - if (p.startsWith(subWord)){ - matches.add(p); - } - } - } - Object[] data = new Object[matches.size()]; + private JList createSuggestionList(final int position, final String subWord, String header) { + ArrayList<String> matches = new ArrayList<String>(); + if (subWord.startsWith("#")){ + for (String p: pragma) { + if (p.startsWith(subWord)){ + matches.add(p); + } + } + } + else if (header.contains("#")){ + //Find instances of '.' + Pattern p = Pattern.compile("\\."); + Matcher m = p.matcher(subWord); + int count = 0; + while (m.find()){ + count +=1; + } + if (count==0){ + //Suggest block names + for (String block: blockAttributeMap.keySet()){ + if (block.startsWith(subWord)){ + matches.add(block); + } + } + } + else if (count==1){ + if (header.contains("Authenticity")){ + //Suggest state names + String block = subWord.split("\\.")[0]; + for (String st: blockStateMap.get(block)){ + if (st.startsWith(subWord.split("\\.")[1])){ + matches.add(block+"."+st); + } + } + } + else { + String block = subWord.split("\\.")[0]; + for (String attr: blockAttributeMap.get(block)){ + if (attr.startsWith(subWord.split("\\.")[1])){ + matches.add(block+"."+attr); + } + } + } + } + else { + String block = subWord.split("\\.")[0]; + String state = subWord.split("\\.")[1]; + for (String attr: blockAttributeMap.get(block)){ + if (attr.startsWith(subWord.split("\\.")[2])){ + matches.add(block+"."+state+"."+attr); + } + } + + } + } + Object[] data = new Object[matches.size()]; data = matches.toArray(data); JList list = new JList(data); list.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1)); @@ -207,7 +255,25 @@ public class JDialogPragma extends javax.swing.JDialog implements ActionListener if (subWord.length() < 1) { return; } - suggestion = new SuggestionPanel(textarea, position, subWord, location); + String header=""; + //Find the most recent pragma name + start=Math.max(0,position-1); + while (start>0){ + //Find previous new line position + if (!String.valueOf(text.charAt(start)).matches(".")){ + break; + } + else { + start--; + } + } + if (start==0){ + header = text.substring(start, position).split(" ")[0]; + } + else { + header = text.substring(start+1,position).split(" ")[0]; + } + suggestion = new SuggestionPanel(textarea, position, subWord, location, header); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { -- GitLab