source: trunk/src/org/expeditee/gui/AttributeUtils.java@ 235

Last change on this file since 235 was 235, checked in by ra33, 16 years ago

Refactored the way attribute value pairs work...
Moved static methods into attributeValuePairs class

File size: 21.5 KB
Line 
1package org.expeditee.gui;
2
3import java.awt.Color;
4import java.awt.Font;
5import java.awt.Point;
6import java.lang.reflect.InvocationTargetException;
7import java.lang.reflect.Method;
8import java.util.HashMap;
9import java.util.LinkedList;
10import java.util.List;
11
12import org.expeditee.io.Conversion;
13import org.expeditee.items.Item;
14import org.expeditee.items.Justification;
15import org.expeditee.items.Permission;
16import org.expeditee.items.Text;
17
18/**
19 * This class provides the methods to extract and set attributes of Items and
20 * Frames. These methods are called when a user merges a text item with
21 * <code>Attribute: Value</code> pairs.
22 *
23 * @author jdm18
24 *
25 */
26public class AttributeUtils {
27
28 private static final int GET_LENGTH = "get".length();
29
30 private static int SET_LENGTH = "set".length();
31
32 // List of method names to ignore when searching for a match
33 private static List<Method> _GetMethods = null;
34
35 private static HashMap<String, Method> _SetMethods = null;
36
37 // List of attributes which are ignored when copying.
38 private static List<String> _Ignore = null;
39
40 /***************************************************************************
41 * List of method names to show in extraced lists even when they return null
42 * (Null is often used to indicate the default value is used)
43 **************************************************************************/
44 private static List<Method> _AllowNull = null;
45
46 private static List<String> _ExtractIgnore = null;
47
48 // private static HashMap<String, String> _Abbreviations = null;
49
50 /**
51 * Initialises the _Ignore and _AllowNull lists.
52 */
53 private static void initLists() {
54
55 Class[] param = {};
56
57 try {
58 // TODO load these in with reflection...
59 // Set the shortcuts with annotation tags on the methods
60 _Ignore = new LinkedList<String>();
61 _Ignore.add("date");
62 _Ignore.add("datecreated");
63 _Ignore.add("d");
64 _Ignore.add("link");
65 _Ignore.add("l");
66 _Ignore.add("action");
67 _Ignore.add("a");
68 _Ignore.add("position");
69 _Ignore.add("pos");
70 _Ignore.add("p");
71 _Ignore.add("x");
72 _Ignore.add("y");
73
74 _ExtractIgnore = new LinkedList<String>();
75 _ExtractIgnore.add("x");
76 _ExtractIgnore.add("y");
77
78 _AllowNull = new LinkedList<Method>();
79 _AllowNull.add(Item.class.getMethod("getColor", param));
80 _AllowNull.add(Item.class.getMethod("getBackgroundColor", param));
81
82 _AllowNull.add(Frame.class.getMethod("getBackgroundColor", param));
83 _AllowNull.add(Frame.class.getMethod("getForegroundColor", param));
84
85 _GetMethods = new LinkedList<Method>();
86 _GetMethods.add(Item.class.getMethod("getDateCreated", param));
87
88 _GetMethods.add(Item.class.getMethod("getColor", param));
89 _GetMethods.add(Item.class.getMethod("getBorderColor", param));
90 _GetMethods.add(Item.class.getMethod("getBackgroundColor", param));
91 _GetMethods.add(Item.class.getMethod("getAction", param));
92 _GetMethods.add(Item.class.getMethod("getData", param));
93 _GetMethods.add(Item.class.getMethod("getLink", param));
94 _GetMethods.add(Item.class.getMethod("getFormula", param));
95 _GetMethods.add(Item.class.getMethod("getFillColor", param));
96 _GetMethods.add(Item.class.getMethod("getGradientColor", param));
97 _GetMethods.add(Item.class.getMethod("getFillPattern", param));
98 _GetMethods.add(Item.class.getMethod("getThickness", param));
99
100 _GetMethods.add(Item.class.getMethod("getOwner", param));
101 _GetMethods.add(Item.class.getMethod("getLinkMark", param));
102 _GetMethods.add(Item.class.getMethod("getActionMark", param));
103
104 _GetMethods
105 .add(Item.class.getMethod("getActionCursorEnter", param));
106 _GetMethods
107 .add(Item.class.getMethod("getActionCursorLeave", param));
108 _GetMethods.add(Item.class.getMethod("getActionEnterFrame", param));
109 _GetMethods.add(Item.class.getMethod("getActionLeaveFrame", param));
110
111 _GetMethods.add(Item.class.getMethod("getTopShadowColor", param));
112 _GetMethods
113 .add(Item.class.getMethod("getBottomShadowColor", param));
114 _GetMethods.add(Item.class.getMethod("getArrow", param));
115
116 _GetMethods.add(Item.class.getMethod("getLinePattern", param));
117 _GetMethods.add(Item.class.getMethod("getLinkFrameset", param));
118 _GetMethods.add(Item.class.getMethod("getLinkTemplate", param));
119 _GetMethods.add(Item.class.getMethod("getPosition", param));
120 _GetMethods.add(Item.class.getMethod("getX", param));
121 _GetMethods.add(Item.class.getMethod("getY", param));
122
123 _GetMethods.add(Item.class.getMethod("getAnchorRight", param));
124 _GetMethods.add(Item.class.getMethod("getAnchorBottom", param));
125 _GetMethods.add(Item.class.getMethod("getSize", param));
126
127 _GetMethods.add(Text.class.getMethod("getFamily", param));
128 _GetMethods.add(Text.class.getMethod("getFontStyle", param));
129 _GetMethods.add(Text.class.getMethod("getJustification", param));
130 _GetMethods.add(Text.class.getMethod("getWidth", param));
131
132 _GetMethods.add(Frame.class.getMethod("getOwner", param));
133 _GetMethods.add(Frame.class.getMethod("getPermission", param));
134 _GetMethods.add(Frame.class.getMethod("getDateCreated", param));
135 _GetMethods.add(Frame.class.getMethod("getLastModifyUser", param));
136 _GetMethods.add(Frame.class.getMethod("getLastModifyDate", param));
137 _GetMethods.add(Frame.class.getMethod("getForegroundColor", param));
138 _GetMethods.add(Frame.class.getMethod("getBackgroundColor", param));
139
140 Class[] pPoint = { Point.class };
141 Class[] pString = { String.class };
142 Class[] pInt = { int.class };
143 Class[] pFloat = { float.class };
144 Class[] pFloatO = { Float.class };
145 Class[] pColor = { Color.class };
146 Class[] pBool = { boolean.class };
147 Class[] pArrow = { float.class, double.class };
148 Class[] pList = { List.class };
149 Class[] pIntArray = { int[].class };
150 Class[] pJustification = { Justification.class };
151 Class[] pPermission = { Permission.class };
152
153 // TODO automatically load these by annotating the methods with the
154 // shortcut text
155 // Indicate to users of any symbols that clash
156
157 _SetMethods = new HashMap<String, Method>();
158 _SetMethods.put("x", Item.class.getMethod("setX", pFloat));
159 _SetMethods.put("y", Item.class.getMethod("setY", pFloat));
160 _SetMethods.put("position", Item.class.getMethod("setPosition",
161 pPoint));
162
163 _SetMethods.put("ab", Item.class.getMethod("setAnchorBottom",
164 pFloatO));
165 _SetMethods.put("ar", Item.class.getMethod("setAnchorRight",
166 pFloatO));
167 _SetMethods.put("anchorbottom", Item.class.getMethod(
168 "setAnchorBottom", pFloatO));
169 _SetMethods.put("anchorright", Item.class.getMethod(
170 "setAnchorRight", pFloatO));
171
172 _SetMethods.put("p", Item.class.getMethod("setPosition", pPoint));
173 _SetMethods.put("pos", Item.class.getMethod("setPosition", pPoint));
174 _SetMethods.put("thickness", Item.class.getMethod("setThickness",
175 pFloat));
176 _SetMethods.put("t", Item.class.getMethod("setThickness", pFloat));
177
178 _SetMethods.put("color", Item.class.getMethod("setColor", pColor));
179 _SetMethods.put("c", Item.class.getMethod("setColor", pColor));
180
181 _SetMethods.put("backgroundcolor", Item.class.getMethod(
182 "setBackgroundColor", pColor));
183 _SetMethods.put("bgc", Item.class.getMethod("setBackgroundColor",
184 pColor));
185 _SetMethods.put("bordercolor", Item.class.getMethod(
186 "setBorderColor", pColor));
187 _SetMethods.put("bc", Item.class
188 .getMethod("setBorderColor", pColor));
189
190 _SetMethods
191 .put("action", Item.class.getMethod("setActions", pList));
192 _SetMethods.put("a", Item.class.getMethod("setActions", pList));
193 _SetMethods.put("d", Item.class.getMethod("setData", pList));
194 _SetMethods.put("data", Item.class.getMethod("setData", pList));
195
196 _SetMethods.put("link", Item.class.getMethod("setLink", pString));
197 _SetMethods.put("l", Item.class.getMethod("setLink", pString));
198
199 _SetMethods.put("formula", Item.class.getMethod("calculate",
200 pString));
201 _SetMethods.put("f", Item.class.getMethod("calculate", pString));
202
203 _SetMethods.put("fillcolor", Item.class.getMethod("setFillColor",
204 pColor));
205 _SetMethods.put("fc", Item.class.getMethod("setFillColor", pColor));
206 _SetMethods.put("gc", Item.class.getMethod("setGradientColor",
207 pColor));
208 _SetMethods.put("gradientcolor", Item.class.getMethod(
209 "setGradientColor", pColor));
210
211 _SetMethods.put("fillpattern", Item.class.getMethod(
212 "setFillPattern", pString));
213 _SetMethods.put("fp", Item.class.getMethod("setFillPattern",
214 pString));
215
216 _SetMethods.put("owner", Item.class.getMethod("setOwner", pString));
217 _SetMethods.put("linkmark", Item.class.getMethod("setLinkMark",
218 pBool));
219 _SetMethods.put("lm", Item.class.getMethod("setLinkMark", pBool));
220 _SetMethods.put("actionmark", Item.class.getMethod("setActionMark",
221 pBool));
222 _SetMethods.put("am", Item.class.getMethod("setActionMark", pBool));
223
224 _SetMethods.put("actioncursorenter", Item.class.getMethod(
225 "setActionCursorEnter", pList));
226 _SetMethods.put("actioncursorleave", Item.class.getMethod(
227 "setActionCursorLeave", pList));
228 _SetMethods.put("actionenterframe", Item.class.getMethod(
229 "setActionEnterFrame", pList));
230 _SetMethods.put("actionleaveframe", Item.class.getMethod(
231 "setActionLeaveFrame", pList));
232
233 _SetMethods.put("topshadow", Item.class.getMethod(
234 "setTopShadowColor", pColor));
235 _SetMethods.put("bottomshadow", Item.class.getMethod(
236 "setBottomShadowColor", pColor));
237 _SetMethods.put("arrow", Item.class.getMethod("setArrow", pArrow));
238
239 _SetMethods.put("linepattern", Item.class.getMethod(
240 "setLinePattern", pIntArray));
241 _SetMethods.put("lp", Item.class.getMethod("setLinePattern",
242 pIntArray));
243
244 _SetMethods.put("linkframeset", Item.class.getMethod(
245 "setLinkFrameset", pString));
246 _SetMethods.put("lf", Item.class.getMethod("setLinkFrameset",
247 pString));
248 _SetMethods.put("linktemplate", Item.class.getMethod(
249 "setLinkTemplate", pString));
250 _SetMethods.put("lt", Item.class.getMethod("setLinkTemplate",
251 pString));
252
253 _SetMethods.put("family", Text.class
254 .getMethod("setFamily", pString));
255 _SetMethods.put("face", Text.class.getMethod("setFontStyle",
256 pString));
257 _SetMethods.put("fontstyle", Text.class.getMethod("setFontStyle",
258 pString));
259 _SetMethods.put("justification", Text.class.getMethod(
260 "setJustification", pJustification));
261 _SetMethods.put("j", Text.class.getMethod("setJustification",
262 pJustification));
263 _SetMethods.put("width", Text.class.getMethod("setWidth", pInt));
264 _SetMethods.put("size", Item.class.getMethod("setSize", pFloat));
265 _SetMethods.put("s", Item.class.getMethod("setSize", pFloat));
266
267 _SetMethods.put("foregroundcolor", Frame.class.getMethod(
268 "setForegroundColor", pColor));
269 _SetMethods.put("fgc", Frame.class.getMethod("setForegroundColor",
270 pColor));
271 _SetMethods.put("backgroundcolor0", Frame.class.getMethod(
272 "setBackgroundColor", pColor));
273 _SetMethods.put("bgc0", Frame.class.getMethod("setBackgroundColor",
274 pColor));
275 _SetMethods.put("permission", Frame.class.getMethod(
276 "setPermission", pPermission));
277
278 } catch (SecurityException e) {
279 // TODO Auto-generated catch block
280 e.printStackTrace();
281 } catch (NoSuchMethodException e) {
282 // TODO Auto-generated catch block
283 e.printStackTrace();
284 }
285 }
286
287 /**
288 * Extracts a list of attributes from the given Object. Any method that
289 * starts with <code>get</code>, takes no arguments and is not found in
290 * the Ignore list will be run, All the attributes are then put into a Text
291 * Item of the form <Name>:<Value> If the value returned by the get method
292 * is null, then the attribute will not be included, unless the name of the
293 * method is found in the AllowNull list.
294 *
295 * @param toExtract
296 * The Object from which to extract the attributes
297 * @return A Text Item containing the extracted Attributes.
298 */
299 public static Item extractAttributes(Object toExtract) {
300 if (toExtract == null)
301 return null;
302
303 // ensure the lists are populated
304 if (_Ignore == null)
305 initLists();
306
307 // StringBuffer to store all the extracted Attribute:Value pairs
308 StringBuffer attributes = new StringBuffer();
309
310 // iterate through the list of methods
311 for (Method m : _GetMethods) {
312
313 // Make sure the classes of the methods match the item
314 if (m.getDeclaringClass().isAssignableFrom(toExtract.getClass())) {
315 try {
316 Object o = m.invoke(toExtract, (Object[]) null);
317
318 if (o == null) {
319 // methods that return null are only included if they
320 // are in the AllowNull list
321 if (_AllowNull.contains(m)) {
322 String name = m.getName().substring(GET_LENGTH)
323 .toLowerCase();
324 if (name.equals("color"))
325 o = "default";
326 else if (name.equals("backgroundcolor"))
327 o = "transparent";
328 else if (name.equals("foregroundcolor"))
329 o = "auto";
330 else
331 o = "";
332 } else {
333 continue;
334 }
335 }
336 // skip methods that are in the ignore lists
337 if (_ExtractIgnore.contains(m.getName().substring(
338 GET_LENGTH).toLowerCase())) {
339 continue;
340 }
341
342 if (o instanceof Integer) {
343 Integer i = (Integer) o;
344 if (i == Item.DEFAULT_INTEGER)
345 continue;
346 if (m.getName().endsWith("Justification")
347 && ((Justification) o).toString() != null)
348 o = ((Justification) o).toString();
349 // -1 indicates default value
350 else
351 o = i;
352 } else if (o instanceof Float) {
353 // -1 indicates default value
354 if (((Float) o) < 0.0001)
355 continue;
356 o = Math.round((Float) o);
357 } else if (o instanceof Double) {
358 // -1 indicates default value
359 if (((Double) o) < 0.0001)
360 continue;
361 } else if (o instanceof Color) {
362 // converts the color to the Expeditee code
363 o = Conversion.getExpediteeColorCode((Color) o);
364 if (o == null)
365 continue;
366 } else if (o instanceof Point) {
367 Point p = (Point) o;
368 o = Math.round(p.getX()) + " " + Math.round(p.getY());
369 } else if (o instanceof Font) {
370 Font f = (Font) o;
371
372 String s = f.getName() + "-";
373 if (f.isPlain())
374 s += "Plain";
375
376 if (f.isBold())
377 s += "Bold";
378
379 if (f.isItalic())
380 s += "Italic";
381
382 s += "-" + f.getSize();
383 o = s;
384 } else if (o instanceof Text) {
385 o = ((Text) o).getFirstLine();
386 } else if (o instanceof List) {
387 List list = (List) o;
388 for (Object ob : list)
389 attributes
390 .append(m.getName().substring(GET_LENGTH))
391 .append(AttributeValuePair.SEPARATOR_STRING)
392 .append(ob).append('\n');
393 continue;
394 } else if (o instanceof int[]) {
395 StringBuffer sb = new StringBuffer();
396 int[] values = (int[]) o;
397 for (int i = 0; i < values.length; i++) {
398 sb.append(values[i]).append(' ');
399 }
400 sb.deleteCharAt(attributes.length() - 1);
401 o = sb.toString();
402 } else if (o instanceof Boolean) {
403 // true is the default for boolean values
404 if (((Boolean) o).booleanValue())
405 continue;
406 }
407 // Append the attributes
408 attributes.append(m.getName().substring(GET_LENGTH))
409 .append(AttributeValuePair.SEPARATOR_STRING)
410 .append(o).append('\n');
411 } catch (Exception e) {
412 // TODO Auto-generated catch block
413 e.printStackTrace();
414 }
415 }
416 }
417
418 // if no attributes were extracted
419 if (attributes.length() <= 0)
420 return null;
421
422 while (attributes.charAt(attributes.length() - 1) == '\n')
423 attributes.delete(attributes.length() - 1, attributes.length());
424
425 // create the text Item
426 Frame current = DisplayIO.getCurrentFrame();
427 Item attribs = current.getStatsTextItem(attributes.toString());
428 return attribs;
429 }
430
431 /**
432 * Attempts to set the attribute in the given attribute: value pair. The
433 * value string should be formatted as follows:
434 * <code> Attribute: Value </code> Multiple values can be used if they are
435 * separated by spaces
436 *
437 * @param toSet
438 * The Item or Frame to set the attribute of
439 * @param attribs
440 * The Text item that contains the list of attributes to set
441 * @return True if the attribute(s) were sucessfully set, false otherwise
442 */
443 public static boolean setAttribute(Object toSet, Text attribs) {
444 // error checking
445 if (toSet == null || attribs == null)
446 return false;
447
448 if (_Ignore == null)
449 initLists();
450
451 // get the list of attribute: value pairs
452 List<String> values = attribs.getTextList();
453 // if no pairs exist, we are done
454 if (values == null || values.size() == 0) {
455 return false;
456 }
457
458 // loop through all attribute: value pairs
459 for (int i = 0; i < values.size(); i++) {
460 AttributeValuePair avp = new AttributeValuePair(values.get(i));
461
462 // If the first is not an attribute value pair then dont do
463 // attrubute merging
464 if (!avp.hasAttribute())
465 return false;
466
467 // check if the next string is another attribute to merge or a
468 // continuation
469 for (; i < values.size() - 1; i++) {
470 AttributeValuePair nextAvp = new AttributeValuePair(values
471 .get(i + 1));
472
473 // if the next String has a colon, then it may be another
474 // attribute
475 if (nextAvp.hasAttribute()) {
476 // if the attribute is the same as v, then it is a
477 // continuation
478 if (nextAvp.getAttribute().equals(avp.getAttribute())) {
479 // strip the attribute from next
480 avp.appendValue(nextAvp.getValue());
481
482 // if the attribute is not the same, then it may be a
483 // new method
484 } else {
485 break;
486 }
487 }
488
489 // v.append("\n").append(next);
490 }
491
492 if (!setAttribute(toSet, avp, values.size() > 1)) {
493
494 String stripped = avp.getAttribute();
495 if (stripped == null) {
496 // This happens when there is an attribute at the start
497 // Then a bunch of plain text
498 return false;
499 } else if (_Ignore.contains(stripped)) {
500 return false;
501 } else if (!(_SetMethods.containsKey(stripped))) {
502 // Display an error message if its not in our list of
503 // attributes to ignore when copying
504 MessageBay.warningMessage("Attribute: '"
505 + avp.getAttribute() + "' does not exist.");
506 } else {
507 String types = "";
508 for (Class c : _SetMethods.get(stripped)
509 .getParameterTypes())
510 types += c.getSimpleName() + " ";
511 MessageBay.warningMessage("Wrong arguments for: '"
512 + avp.getAttribute() + "' expecting "
513 + types.trim() + " found '" + avp.getValue() + "'");
514 }
515 }
516 }
517
518 return true;
519 }
520
521 /**
522 * Sets a single attrubute of a frame or item.
523 *
524 * @param toSet
525 * @param avp
526 * @param isAttributeList
527 * some properties are ignored when attribute list are injected
528 * into an item. These properties are ignored if this param is
529 * true
530 * @return
531 */
532 private static boolean setAttribute(Object toSet, AttributeValuePair avp,
533 boolean isAttributeList) {
534
535 assert (avp.hasAttribute());
536
537 // separate attribute and value from string
538 String attribute = avp.getAttribute().toLowerCase();
539
540 String value = avp.getValue();
541 assert (value != null);
542
543 // Some properties are ignored when multiple attributes are being set on
544 // an item at the same time
545 if (isAttributeList && _Ignore.contains(attribute)) {
546 // System.out.println("Attribute ignored: " + attribute);
547 return true;
548 }
549
550 // Separate multiple values if required
551 Method toRun = _SetMethods.get(attribute);
552
553 // if this is not the name of a method, it may be the name of an agent
554 if (toRun == null) {
555 // System.out.println("Attrib not found for: " + attribute);
556 return false;
557 }
558
559 // if there are duplicate methods with the same name
560 List<Method> possibles = new LinkedList<Method>();
561 if (toRun.getDeclaringClass().isInstance(toSet))
562 possibles.add(toRun);
563 int i = 0;
564 while (_SetMethods.containsKey(attribute + i)) {
565 if (_SetMethods.get(attribute + i).getDeclaringClass()
566 .isAssignableFrom(toSet.getClass()))
567 possibles.add(_SetMethods.get(attribute + i));
568 i++;
569 }
570
571 for (Method possible : possibles) {
572 Object current = null;
573 Object[] param = {};
574 // find the corresponding get method for this set method
575 // and get the current value of the attribute
576 for (Method m : _GetMethods) {
577 if (m.getDeclaringClass().isAssignableFrom(toSet.getClass())
578 && m.getName().substring(GET_LENGTH).equals(
579 possible.getName().substring(SET_LENGTH))) {
580 try {
581 current = m.invoke(toSet, param);
582 } catch (IllegalArgumentException e) {
583 // TODO Auto-generated catch block
584 e.printStackTrace();
585 } catch (IllegalAccessException e) {
586 // TODO Auto-generated catch block
587 e.printStackTrace();
588 } catch (InvocationTargetException e) {
589 // TODO Auto-generated catch block
590 e.printStackTrace();
591 }
592 break;
593 }
594
595 }
596
597 try {
598 Object[] params = Conversion.Convert(possible, value, current);
599
600 try {
601 possible.invoke(toSet, params);
602 return true;
603 } catch (IllegalArgumentException e) {
604 // TODO Auto-generated catch block
605 e.printStackTrace();
606 } catch (IllegalAccessException e) {
607 // TODO Auto-generated catch block
608 e.printStackTrace();
609 } catch (InvocationTargetException e) {
610 MessageBay.displayMessage(toSet.getClass().getSimpleName()
611 + " type does not support that attribute.");
612 // e.printStackTrace();
613 }
614 } catch (NumberFormatException e) {
615
616 }
617 }
618
619 return false;
620 }
621
622 /**
623 * Replaces the current value for the text item with the new value.
624 *
625 * @param text
626 * the item whos value is to be changed
627 * @param newValue
628 * the new value for the item
629 */
630 public static void replaceValue(Text text, String newValue) {
631 assert (newValue != null);
632
633 AttributeValuePair avp = new AttributeValuePair(text.getText());
634
635 if (avp.getAttribute() == null) {
636 avp.setAttribute(avp.getValue());
637 }
638 avp.setValue(newValue);
639 text.setText(avp.toString());
640 }
641}
Note: See TracBrowser for help on using the repository browser.