CertainTrustHTI.java 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /**
  2. * CertainTrust SDK
  3. *
  4. * Implements the computational trust model "CertainTrust"
  5. * in Java.
  6. * See <http://www.tk.informatik.tu-darmstadt.de/de/research/smart-security-and-trust/> for further details.
  7. *
  8. *
  9. * Telecooperation Department, Technische Universität Darmstadt
  10. * <http://www.tk.informatik.tu-darmstadt.de/>
  11. *
  12. * Prof. Dr. Max Mühlhäuser <max@informatik.tu-darmstadt.de>
  13. * Florian Volk <florian.volk@cased.de>
  14. *
  15. *
  16. * @author David Kalnischkies
  17. * @author Florian Volk
  18. * @version 1.0
  19. */
  20. /* This Source Code Form is subject to the terms of the Mozilla Public
  21. * License, v. 2.0. If a copy of the MPL was not distributed with this
  22. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  23. package CertainTrust;
  24. import java.awt.BorderLayout;
  25. import java.awt.GridLayout;
  26. import java.awt.event.ActionEvent;
  27. import java.awt.event.ActionListener;
  28. import java.awt.event.FocusEvent;
  29. import java.awt.event.FocusListener;
  30. import java.text.DecimalFormat;
  31. import java.text.NumberFormat;
  32. import java.util.HashMap;
  33. import java.util.Map;
  34. import java.util.Observable;
  35. import java.util.Observer;
  36. import javax.swing.BoxLayout;
  37. import javax.swing.JLabel;
  38. import javax.swing.JPanel;
  39. import javax.swing.JTextField;
  40. import javax.swing.border.EmptyBorder;
  41. /**
  42. * The CertainTrustHTI includes a formular to change
  43. * the C, T and F values of the given CertainTrust
  44. * element and a canvas displaying the expectation
  45. * calculated from these values
  46. */
  47. public class CertainTrustHTI extends JPanel implements Observer {
  48. private static final long serialVersionUID = -1194437596328826222L;
  49. /**
  50. * Creates a new HTI to display a CertainTrust element
  51. *
  52. * @param certainlogic element to display
  53. */
  54. public CertainTrustHTI(CertainTrust certainlogic) {
  55. setup(certainlogic, null);
  56. }
  57. /**
  58. * Creates a new HTI to display a CertainTrust element
  59. *
  60. * Supported config options are:
  61. * - label.lang: language for the text elements (available: "de" and "en" (default))
  62. * - label.f, label.c, label.t and label.e to set the text explicitly
  63. * - readonly: to effect the complete HTI (value either "true" or "false") and
  64. * - readonly.f, readonly.c, readonly.t, readonly.e to set explicitly
  65. * See also {@link CertainTrustCanvas#CertainTrustCanvas(CertainTrust, Map)} for
  66. * additional options which are accepted by the canvas element
  67. *
  68. * @param certainlogic element to display
  69. * @param config to use for this HTI
  70. */
  71. public CertainTrustHTI(CertainTrust certainlogic, Map<String, String> config) {
  72. setup(certainlogic, config);
  73. }
  74. private CertainTrust cl;
  75. private JTextField f;
  76. private JTextField c;
  77. private JTextField t;
  78. private JTextField e;
  79. private CertainTrustCanvas ctc;
  80. private Map<String,String> config;
  81. protected CertainTrustCanvas getCanvas() { return ctc; }
  82. private static JTextField appendInput(JPanel p, String name, char mnemonic, double value, String readOnly, CertainTrustActionFocusListener listener) {
  83. JLabel l = new JLabel(name);
  84. l.setBorder(new EmptyBorder(0, 0, 0, (int) (l.getFont().getSize() * 1.5)));
  85. final JTextField f = new JTextField(CertainTrustHTI.formatFloat(value), 4);
  86. if (readOnly.compareToIgnoreCase("true") == 0) {
  87. f.setEditable(false);
  88. f.setFocusable(false);
  89. }
  90. else if (readOnly.compareToIgnoreCase("false") != 0)
  91. throw new IllegalArgumentException("Input element " + name + " has no valid readonly setting");
  92. else if (listener != null) {
  93. f.addActionListener(listener);
  94. f.addFocusListener(listener);
  95. }
  96. l.setLabelFor(f);
  97. if (mnemonic != '\0')
  98. l.setDisplayedMnemonic(mnemonic);
  99. p.add(l);
  100. p.add(f);
  101. return f;
  102. }
  103. private abstract class CertainTrustActionFocusListener implements ActionListener, FocusListener {
  104. @Override
  105. public void focusGained(FocusEvent arg0) {}
  106. @Override
  107. public void focusLost(FocusEvent arg0) {
  108. update();
  109. }
  110. @Override
  111. public void actionPerformed(ActionEvent arg0) {
  112. update();
  113. }
  114. abstract void update();
  115. /**
  116. * parseInput tries to convert a textual input into a floating point number in [0;1]
  117. * It accepts both "." and "," as decimal delimiters.
  118. * If the conversion fails, a default value is used.
  119. * @param input the textual input to convert into a floating point number
  120. * @param defaultValue the default value used in case the conversion fails
  121. * @return the floating point value generated from the textual input
  122. */
  123. protected double parseInput(String input, double defaultValue) {
  124. double result;
  125. try {
  126. // first, replace the first "," with a "." to understand German-language style floating point notation
  127. String rawInput = input.replaceFirst(",", ".");
  128. result = Double.parseDouble(rawInput);
  129. // check, if the value in within our bounds of [0;1]
  130. if ((1 < result) || (0 > result)) {
  131. result = defaultValue;
  132. }
  133. }
  134. catch (NumberFormatException e) {
  135. result = defaultValue;
  136. }
  137. return result;
  138. }
  139. }
  140. private void setup(CertainTrust certainlogic, Map<String,String> config) {
  141. cl = certainlogic;
  142. if (config != null)
  143. this.config = config;
  144. else
  145. this.config = new HashMap<String,String>();
  146. if (this.config.containsKey("label.lang") == false)
  147. this.config.put("label.lang", "en");
  148. if (this.config.get("label.lang") == "de") {
  149. if (this.config.containsKey("label.f") == false)
  150. this.config.put("label.f", "Initialwert");
  151. if (this.config.containsKey("label.t") == false)
  152. this.config.put("label.t", "Vertrauen");
  153. if (this.config.containsKey("label.c") == false)
  154. this.config.put("label.c", "Sicherheit");
  155. if (this.config.containsKey("label.e") == false)
  156. this.config.put("label.e", "Erwartung");
  157. } else {
  158. if (this.config.containsKey("label.f") == false)
  159. this.config.put("label.f", "Init. value");
  160. if (this.config.containsKey("label.t") == false)
  161. this.config.put("label.t", "Trust");
  162. if (this.config.containsKey("label.c") == false)
  163. this.config.put("label.c", "Certainty");
  164. if (this.config.containsKey("label.e") == false)
  165. this.config.put("label.e", "Expectation");
  166. }
  167. if (this.config.containsKey("readonly") == false) {
  168. if (this.config.containsKey("readonly.f") == false)
  169. this.config.put("readonly.f", "false");
  170. if (this.config.containsKey("readonly.t") == false)
  171. this.config.put("readonly.t", "false");
  172. if (this.config.containsKey("readonly.c") == false)
  173. this.config.put("readonly.c", "false");
  174. if (this.config.containsKey("readonly.e") == false)
  175. this.config.put("readonly.e", "true");
  176. } else {
  177. String readOnly = this.config.get("readonly");
  178. if (this.config.containsKey("readonly.f") == false)
  179. this.config.put("readonly.f", readOnly);
  180. if (this.config.containsKey("readonly.t") == false)
  181. this.config.put("readonly.t", readOnly);
  182. if (this.config.containsKey("readonly.c") == false)
  183. this.config.put("readonly.c", readOnly);
  184. if (this.config.containsKey("readonly.e") == false)
  185. this.config.put("readonly.e", readOnly);
  186. }
  187. JPanel inputs = new JPanel(new GridLayout(5,2));
  188. f = appendInput(inputs, this.config.get("label.f"), 'f', cl.getF(), this.config.get("readonly.f"),
  189. new CertainTrustActionFocusListener() {
  190. @Override
  191. void update() {
  192. cl.setF(this.parseInput(f.getText(), cl.getF()));
  193. }
  194. });
  195. t = appendInput(inputs, this.config.get("label.t"), 't', cl.getT(), this.config.get("readonly.t"),
  196. new CertainTrustActionFocusListener() {
  197. @Override
  198. void update() {
  199. cl.setTC(this.parseInput(t.getText(), cl.getT()),
  200. cl.getC());
  201. }
  202. });
  203. c = appendInput(inputs, this.config.get("label.c"), 'c', cl.getC(), this.config.get("readonly.c"),
  204. new CertainTrustActionFocusListener() {
  205. @Override
  206. void update() {
  207. cl.setTC(cl.getT(),
  208. this.parseInput(c.getText(), cl.getC()));
  209. }
  210. });
  211. JLabel ignore0 = new JLabel("");
  212. inputs.add(ignore0);
  213. JLabel ignore1 = new JLabel("");
  214. inputs.add(ignore1);
  215. e = appendInput(inputs, this.config.get("label.e"),'\0', cl.getExpectation(), this.config.get("readonly.e"), null);
  216. this.add(inputs);
  217. JPanel jp = new JPanel();
  218. jp.setLayout(new BoxLayout(jp, BoxLayout.PAGE_AXIS));
  219. JPanel jp1 = new JPanel();
  220. JLabel certain = new JLabel(this.config.get("label.c") + "\u00a0\u2192");
  221. certain.setUI(new VerticalLabelUI());
  222. jp1.add(certain);
  223. ctc = new CertainTrustCanvas(cl, this.config);
  224. ctc.repaint();
  225. jp1.add(ctc);
  226. JPanel jp2 = new JPanel(new BorderLayout());
  227. JLabel origin = new JLabel("0");
  228. int fontsize = certain.getFont().getSize();
  229. origin.setBorder(new EmptyBorder(0, fontsize, 0, fontsize));
  230. jp2.add(origin, BorderLayout.LINE_START);
  231. JLabel trust = new JLabel(this.config.get("label.t") + "\u00a0\u2192");
  232. jp2.add(trust, BorderLayout.CENTER);
  233. jp.add(jp1);
  234. jp.add(jp2);
  235. this.add(jp);
  236. this.setVisible(true);
  237. cl.addObserver(this);
  238. }
  239. @Override
  240. public void update(Observable ignored0, Object ignored1) {
  241. f.setText(CertainTrustHTI.formatFloat(cl.getF()));
  242. t.setText(CertainTrustHTI.formatFloat(cl.getT()));
  243. c.setText(CertainTrustHTI.formatFloat(cl.getC()));
  244. e.setText(CertainTrustHTI.formatFloat(cl.getExpectation()));
  245. }
  246. /**
  247. * Rounds a number to at most 3 decimal places and converts it to a string
  248. * @param value the number to round
  249. * @return the rounded value as string
  250. */
  251. static private String formatFloat(double value) {
  252. // the explicit type cast from Long to double is required, otherwise rounded will always be 0
  253. double rounded = ((double)Math.round(value * 1000) / 1000);
  254. // Use NumerFormat to omit trailing 0s as those which Double.toString() produces
  255. NumberFormat formatter = new DecimalFormat("0.###");
  256. String result = formatter.format(rounded);
  257. // for compatibility with the JS version, our decimal delimiter *always* is "."
  258. result = result.replaceFirst(",", ".");
  259. return result;
  260. }
  261. }