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

Last change on this file since 242 was 242, checked in by ra33, 16 years ago
File size: 21.7 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 return setAttribute(toSet, attribs, 1);
445 }
446
447 public static boolean setAttribute(Object toSet, Text attribs, int minAttributeLength) {
448 // error checking
449 if (toSet == null || attribs == null)
450 return false;
451
452 if (_Ignore == null)
453 initLists();
454
455 if(attribs.isAnnotation())
456 return false;
457
458 // get the list of attribute: value pairs
459 List<String> values = attribs.getTextList();
460 // if no pairs exist, we are done
461 if (values == null || values.size() == 0) {
462 return false;
463 }
464
465 // loop through all attribute: value pairs
466 for (int i = 0; i < values.size(); i++) {
467 AttributeValuePair avp = new AttributeValuePair(values.get(i));
468
469 // If the first is not an attribute value pair then dont do
470 // attrubute merging
471 if (!avp.hasAttribute() || avp.getAttribute().length() < minAttributeLength)
472 return false;
473
474 // check if the next string is another attribute to merge or a
475 // continuation
476 for (; i < values.size() - 1; i++) {
477 AttributeValuePair nextAvp = new AttributeValuePair(values
478 .get(i + 1));
479
480 // if the next String has a colon, then it may be another
481 // attribute
482 if (nextAvp.hasAttribute()) {
483 // if the attribute is the same as v, then it is a
484 // continuation
485 if (nextAvp.getAttribute().equals(avp.getAttribute())) {
486 // strip the attribute from next
487 avp.appendValue(nextAvp.getValue());
488
489 // if the attribute is not the same, then it may be a
490 // new method
491 } else {
492 break;
493 }
494 }
495
496 // v.append("\n").append(next);
497 }
498
499 if (!setAttribute(toSet, avp, values.size() > 1)) {
500
501 String stripped = avp.getAttribute();
502 if (!avp.hasPair()) {
503 // This happens when there is an attribute at the start
504 // Then a bunch of plain text
505 return false;
506 } else if (_Ignore.contains(stripped)) {
507 return false;
508 } else if (!(_SetMethods.containsKey(stripped))) {
509 // Display an error message if its not in our list of
510 // attributes to ignore when copying
511 MessageBay.warningMessage("Attribute: '"
512 + avp.getAttribute() + "' does not exist.");
513 } else {
514 String types = "";
515 for (Class c : _SetMethods.get(stripped)
516 .getParameterTypes())
517 types += c.getSimpleName() + " ";
518 MessageBay.warningMessage("Wrong arguments for: '"
519 + avp.getAttribute() + "' expecting "
520 + types.trim() + " found '" + avp.getValue() + "'");
521 }
522 }
523 }
524
525 return true;
526 }
527
528 /**
529 * Sets a single attrubute of a frame or item.
530 *
531 * @param toSet
532 * @param avp
533 * @param isAttributeList
534 * some properties are ignored when attribute list are injected
535 * into an item. These properties are ignored if this param is
536 * true
537 * @return
538 */
539 private static boolean setAttribute(Object toSet, AttributeValuePair avp,
540 boolean isAttributeList) {
541
542 assert (avp.hasAttribute());
543
544 // separate attribute and value from string
545 String attribute = avp.getAttribute().toLowerCase();
546
547 String value = avp.getValue();
548 assert (value != null);
549
550 // Some properties are ignored when multiple attributes are being set on
551 // an item at the same time
552 if (isAttributeList && _Ignore.contains(attribute)) {
553 // System.out.println("Attribute ignored: " + attribute);
554 return true;
555 }
556
557 // Separate multiple values if required
558 Method toRun = _SetMethods.get(attribute);
559
560 // if this is not the name of a method, it may be the name of an agent
561 if (toRun == null) {
562 // System.out.println("Attrib not found for: " + attribute);
563 return false;
564 }
565
566 // if there are duplicate methods with the same name
567 List<Method> possibles = new LinkedList<Method>();
568 if (toRun.getDeclaringClass().isInstance(toSet))
569 possibles.add(toRun);
570 int i = 0;
571 while (_SetMethods.containsKey(attribute + i)) {
572 if (_SetMethods.get(attribute + i).getDeclaringClass()
573 .isAssignableFrom(toSet.getClass()))
574 possibles.add(_SetMethods.get(attribute + i));
575 i++;
576 }
577
578 for (Method possible : possibles) {
579 Object current = null;
580 Object[] param = {};
581 // find the corresponding get method for this set method
582 // and get the current value of the attribute
583 for (Method m : _GetMethods) {
584 if (m.getDeclaringClass().isAssignableFrom(toSet.getClass())
585 && m.getName().substring(GET_LENGTH).equals(
586 possible.getName().substring(SET_LENGTH))) {
587 try {
588 current = m.invoke(toSet, param);
589 } catch (IllegalArgumentException e) {
590 // TODO Auto-generated catch block
591 e.printStackTrace();
592 } catch (IllegalAccessException e) {
593 // TODO Auto-generated catch block
594 e.printStackTrace();
595 } catch (InvocationTargetException e) {
596 // TODO Auto-generated catch block
597 e.printStackTrace();
598 }
599 break;
600 }
601
602 }
603
604 try {
605 Object[] params = Conversion.Convert(possible, value, current);
606
607 try {
608 possible.invoke(toSet, params);
609 return true;
610 } catch (IllegalArgumentException e) {
611 // TODO Auto-generated catch block
612 e.printStackTrace();
613 } catch (IllegalAccessException e) {
614 // TODO Auto-generated catch block
615 e.printStackTrace();
616 } catch (InvocationTargetException e) {
617 MessageBay.displayMessage(toSet.getClass().getSimpleName()
618 + " type does not support that attribute.");
619 // e.printStackTrace();
620 }
621 } catch (NumberFormatException e) {
622
623 }
624 }
625
626 return false;
627 }
628
629 /**
630 * Replaces the current value for the text item with the new value.
631 *
632 * @param text
633 * the item whos value is to be changed
634 * @param newValue
635 * the new value for the item
636 */
637 public static void replaceValue(Text text, String newValue) {
638 assert (newValue != null);
639
640 AttributeValuePair avp = new AttributeValuePair(text.getText());
641
642 if (avp.getAttribute() == null) {
643 avp.setAttribute(avp.getValue());
644 }
645 avp.setValue(newValue);
646 text.setText(avp.toString());
647 }
648}
Note: See TracBrowser for help on using the repository browser.