source: src/main/java/genius/gui/tree/NegotiatorTreeTableModel.java@ 126

Last change on this file since 126 was 126, checked in by Aron Hammond, 6 years ago

Added function to calculate opposition to MultiLateralAnalysis.java

Moved code to add RLBOA listeners to RLBOAUtils is misc package

Added input for strategyParameters to SessionPanel (gui)

!! close SessionInfo after tournament; this caused /tmp/ to fill up with GeniusData files

Our own package:

  • Added opponents and strategies that are mentioned in the report
  • Change class hierarchy, agents can now extend from RLBOAagentBilateral to inherit RL functionality.
  • States extend from AbstractState
File size: 12.4 KB
Line 
1package genius.gui.tree;
2
3import java.util.Enumeration;
4import java.util.HashMap;
5import java.util.Map;
6
7import javax.swing.BorderFactory;
8import javax.swing.JTextField;
9import javax.swing.tree.TreePath;
10
11import genius.core.DomainImpl;
12import genius.core.issue.ISSUETYPE;
13import genius.core.issue.Issue;
14import genius.core.issue.IssueDiscrete;
15import genius.core.issue.IssueInteger;
16import genius.core.issue.IssueReal;
17import genius.core.issue.Objective;
18import genius.core.jtreetable.AbstractTreeTableModel;
19import genius.core.jtreetable.TreeTableModel;
20import genius.core.utility.AdditiveUtilitySpace;
21
22/**
23 * Tree model for editing {@link AdditiveUtilitySpace}.
24 */
25public class NegotiatorTreeTableModel extends AbstractTreeTableModel
26 implements TreeTableModel {
27
28 private static final String NAME = "Name";
29 private static final String TYPE = "Type";
30 private static final String NUMBER = "Number";
31 private static final String VALUE = "Value";
32 private static final String WEIGHT = "Weight";
33
34 private Objective root;
35 private DomainImpl domain;
36 private String[] colNames;
37 private Class[] colTypes;
38 private AdditiveUtilitySpace utilitySpace;
39 private boolean containsUtilitySpace;
40 private Map<Objective, JTextField> names;
41 private Map<Objective, JTextField> types;
42 private Map<Objective, JTextField> numbers;
43 private Map<Objective, WeightSlider> sliders;
44 private Map<Objective, IssueValuePanel> issueValues; // Contains objects
45 // representing the
46 // possible values
47 // of an issue
48
49 private static final String[] domainColNames = { NAME, TYPE, /* NUMBER, */
50 VALUE };
51 private static final Class[] domainColTypes = { TreeTableModel.class,
52 JTextField.class, /* JTextField.class, */IssueValuePanel.class };
53 private static final String[] domainAndUtilityColNames = { NAME,
54 TYPE, /*
55 * NUMBER ,
56 */
57 VALUE, WEIGHT };
58 private static final Class[] domainAndUtilityColTypes = {
59 TreeTableModel.class, JTextField.class, /* JTextField.class, */
60 IssueValuePanel.class, WeightSlider.class };
61
62 /**
63 * Create new profile for domain
64 *
65 * @param domain
66 * the domain to edit
67 */
68 public NegotiatorTreeTableModel(DomainImpl domain) {
69 this.domain = domain;
70 this.root = domain.getObjectivesRoot();
71 this.containsUtilitySpace = false;
72 this.colNames = domainColNames;
73 this.colTypes = domainColTypes;
74 names = new HashMap<Objective, JTextField>();
75 types = new HashMap<Objective, JTextField>();
76 numbers = new HashMap<Objective, JTextField>();
77 issueValues = new HashMap<Objective, IssueValuePanel>();
78 }
79
80 /**
81 * Edit existing profile in domain
82 *
83 * @param domain
84 * the domain of the profile
85 * @param utilitySpace
86 * the profile to edit
87 */
88 public NegotiatorTreeTableModel(DomainImpl domain,
89 AdditiveUtilitySpace utilitySpace) {
90 this.domain = domain;
91 this.root = domain.getObjectivesRoot();
92 this.utilitySpace = utilitySpace;
93 this.containsUtilitySpace = true;
94 this.colNames = domainAndUtilityColNames;
95 this.colTypes = domainAndUtilityColTypes;
96 names = new HashMap<Objective, JTextField>();
97 types = new HashMap<Objective, JTextField>();
98 numbers = new HashMap<Objective, JTextField>();
99 issueValues = new HashMap<Objective, IssueValuePanel>();
100 sliders = new HashMap<Objective, WeightSlider>();
101
102 }
103
104 /**
105 * @return the root Object of the tree.
106 */
107 @Override
108 public Object getRoot() {
109 return root;
110 }
111
112 /**
113 * @return true if and only if node is an Issue.
114 */
115 @Override
116 public boolean isLeaf(Object node) {
117 return (node instanceof Issue);
118 }
119
120 /**
121 *
122 * @param row
123 * the row number of the cell.
124 * @param col
125 * the column number of the cell.
126 * @return if the given cell is editable.
127 */
128 public boolean isCellEditable(int row, int col) {
129 if (col >= colTypes.length || col < 0)
130 return false;
131 else if (colTypes[col] == TreeTableModel.class)
132 return true;
133 else if (colTypes[col] == WeightSlider.class)
134 return true;
135 else
136 return false;
137 }
138
139 @Override
140 public boolean isCellEditable(Object node, int column) {
141 return isCellEditable(-1, column);
142 }
143
144 /**
145 * Method is empty at the moment. Default implementation from
146 * AbstractTreeTableModel.
147 */
148 @Override
149 public void valueForPathChanged(TreePath path, Object newValue) {
150 }
151
152 /**
153 * @return the number of columns for the TreeTable.
154 */
155 @Override
156 public int getColumnCount() {
157 return colNames.length;
158 }
159
160 /**
161 * @return the name of column. If column >= getColumnCount, an empty String
162 * is returned.
163 */
164 @Override
165 public String getColumnName(int column) {
166 if (column < getColumnCount())
167 return colNames[column];
168 else
169 return "";
170 }
171
172 @Override
173 public Class getColumnClass(int column) {
174 return colTypes[column];
175 }
176
177 /**
178 * When node is an Objective, this method returns the object beloging in the
179 * given column. If node is no Objective, or column has an invalid value,
180 * null is returned.
181 *
182 * @return the contents of column, for the given node.
183 */
184 @Override
185 public Object getValueAt(Object node, int column) {
186 Objective objective;
187 if (!(node instanceof Objective) || getColumnCount() <= column
188 || column < 0)
189 return null;
190 else
191 objective = (Objective) node;
192
193 // TODO Maybe also instanceof Issue.
194 // do the rest
195 // Also, when only editing Objectives, don't show anything after the
196 // objective columns. <-- already happens automatically due to
197 // getColumnCount()
198
199 /*
200 * switch(column) { case 0: return objective.getName(); case 1: return
201 * objective.getType(); case 2: return objective.getNumber(); case 3:
202 * return utilitySpace.getEvaluator(objective.getNumber());//Is this
203 * going to work in all cases? Answer: no case 4: return
204 * getWeightSlider(objective); }
205 */
206
207 // if (getColumnName(column).equals(arg0))
208 if (getColumnName(column) == NAME)
209 return getNameField(objective);
210 else if (getColumnName(column) == TYPE)
211 return getTypeField(objective);
212 else if (getColumnName(column) == NUMBER)
213 return getNumberField(objective);
214 else if (getColumnName(column) == VALUE)
215 return getIssueValuePanel(objective);
216 else if (getColumnName(column) == WEIGHT)
217 if (utilitySpace instanceof AdditiveUtilitySpace) {
218 return getWeightSlider(objective);
219 } else {
220 return null;
221 }
222
223 return null;
224 }
225
226 /**
227 * Returns parent's child at the given index. If parent is not of type
228 * Objective, or index is invalid, null is returned.
229 */
230 @Override
231 public Object getChild(Object parent, int index) {
232 if (!(parent instanceof Objective)
233 || ((Objective) parent).getChildCount() <= index || index < 0)
234 return null;
235 else
236 return ((Objective) parent).getChildAt(index);
237 }
238
239 /**
240 * If parent is instanceof Objective, returns the number of children.
241 * Otherwise, 0 is returned.
242 */
243 @Override
244 public int getChildCount(Object parent) {
245 if (parent instanceof Objective)
246 return ((Objective) parent).getChildCount();
247 else
248 return 0;
249 }
250
251 /**
252 * Recursively calculates the highest Objective / Issue number in the tree.
253 *
254 * @return the highest Objective / Issue number in the tree, or -1.
255 */
256 public int getHighestObjectiveNr() {
257 if (root != null)
258 return root.getHighestObjectiveNr(-1);
259 else
260 return -1;
261 }
262
263 /**
264 *
265 * @return the Domain.
266 */
267 public DomainImpl getDomain() {
268 return domain;
269 }
270
271 /**
272 *
273 * @return the UtilitySpace.
274 */
275 public AdditiveUtilitySpace getUtilitySpace() {
276 return utilitySpace;
277 }
278
279 /**
280 * Sets this model's UtilitySpace. A UtilitySpace is required to map
281 * utilities to treeNodes.
282 *
283 * @param space
284 * a UtilitySpace object.
285 */
286 public void setUtilitySpace(AdditiveUtilitySpace space) {
287 utilitySpace = space;
288
289 if (space != null) {
290 containsUtilitySpace = true;
291 colNames = domainAndUtilityColNames;
292 colTypes = domainAndUtilityColTypes;
293 } else {
294 containsUtilitySpace = false;
295 colNames = domainColNames;
296 colTypes = domainColTypes;
297 }
298 }
299
300 public void updateWeights(WeightSlider caller, double newWeight) {
301 // Calculate the new weights for the tree, and return to caller with the
302 // caller's new weight. This new weight can be
303 // different from the requested weight, for instance if that
304 // modification is impossible for some reason.
305
306 // Root may not be null!
307 Enumeration<Objective> objectives = root.getPreorderEnumeration();
308 while (objectives.hasMoreElements()) {
309 Objective obj = objectives.nextElement();
310 double updatedWeight = utilitySpace.getWeight(obj.getNumber());
311 getWeightSlider(obj).setWeight(updatedWeight);
312 }
313 }
314
315 protected JTextField getNameField(Objective node) {
316 JTextField field = names.get(node);
317 if (field == null) {
318 field = new JTextField(node.getName());
319 field.setBorder(BorderFactory.createEmptyBorder());
320 setNameField(node, field);
321 }
322 return field;
323 }
324
325 protected JTextField getTypeField(Objective node) {
326 JTextField field = types.get(node);
327 if (field == null) {
328 field = new JTextField("" + node.getType());
329 field.setBorder(BorderFactory.createEmptyBorder());
330 setTypeField(node, field);
331 }
332 return field;
333 }
334
335 protected JTextField getNumberField(Objective node) {
336 JTextField field = numbers.get(node);
337 if (field == null) {
338 field = new JTextField("" + node.getNumber());
339 field.setBorder(BorderFactory.createEmptyBorder());
340 setNumberField(node, field);
341 }
342 return field;
343 }
344
345 /**
346 * Returns the WeightSlider belonging to the given Objective. If there is no
347 * WeightSlider attached to the given Objective, a new one is created and
348 * added using setWeightSlider(Objective, WeightSlider).
349 *
350 * @param node
351 * an Objective.
352 * @return the slider associated with node.
353 */
354 public WeightSlider getWeightSlider(Objective node) {
355 WeightSlider slider = sliders.get(node);
356 if (slider == null) {
357 slider = new WeightSlider(this, node);
358 setWeightSlider(node, slider);
359
360 if (utilitySpace != null) {
361 slider.setWeight(utilitySpace.getWeight(node.getNumber()));
362 } else {
363 slider.setWeight(0.5);
364 }
365 }
366 return slider;
367 }
368
369 /**
370 * Sets the WeightSlider object for the given Objective.
371 *
372 * @param node
373 * Objective to attach the slider to.
374 * @param slider
375 * the WeightSlider to be attached to node.
376 */
377 protected void setWeightSlider(Objective node, WeightSlider slider) {
378 sliders.put(node, slider);
379 }
380
381 protected void setNameField(Objective node, JTextField field) {
382 names.put(node, field);
383 }
384
385 protected void setTypeField(Objective node, JTextField field) {
386 types.put(node, field);
387 }
388
389 protected void setNumberField(Objective node, JTextField field) {
390 numbers.put(node, field);
391 }
392
393 public IssueValuePanel getIssueValuePanel(Objective node) {
394 if (utilitySpace != null
395 && !(utilitySpace instanceof AdditiveUtilitySpace))
396 return null;
397 IssueValuePanel value = issueValues.get(node);
398 if (value == null) {
399 if (node.getType() == ISSUETYPE.DISCRETE) {
400 value = new IssueDiscreteValuePanel(this, (IssueDiscrete) node);
401 } else if (node.getType() == ISSUETYPE.INTEGER) {
402 value = new IssueIntegerValuePanel(this, (IssueInteger) node);
403 } else if (node.getType() == ISSUETYPE.REAL) {
404 value = new IssueRealValuePanel(this, (IssueReal) node);
405 } else if (node.getType() == ISSUETYPE.OBJECTIVE) {
406 value = new ObjectiveValuePanel(this, node);
407 }
408 setIssueValuePanel(node, value);
409 }
410 return value;
411 }
412
413 protected void setIssueValuePanel(Objective node, IssueValuePanel panel) {
414 issueValues.put(node, panel);
415 }
416
417 /**
418 * Notifies the listeners that the structure of the tree has changed. In
419 * it's current implementation, this method is just a wrapper for the
420 * protected method fireTreeStructureChanged where the child index array and
421 * the children array are left empty. Wouter: be careful with calling this,
422 * The GUI below the source point will be collapsed
423 *
424 * @param source
425 * the source that triggered the change.
426 * @param path
427 * a TreePath object that identifies the path to the parent of
428 * the modified item(s)
429 */
430 public void treeStructureChanged(Object source, Object[] path) {
431 fireTreeStructureChanged(source, path, new int[0], new Object[0]);
432 }
433
434 /**
435 * Wouter: added to handle change of values without change of tree
436 * structure.
437 *
438 * @param source
439 * the source that triggered the change.
440 * @param path
441 * path a TreePath object that identifies the path to the parent
442 * of the modified item(s)
443 */
444 public void treeNodesChanged(Object source, Object[] path) {
445 fireTreeNodesChanged(source, path, new int[0], new Object[0]);
446 }
447}
Note: See TracBrowser for help on using the repository browser.