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

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

Can navigate with PgUp PgDn Home and End with remote framesets

File size: 21.6 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("w", Text.class.getMethod("setWidth", pInt));
265
266 _SetMethods.put("size", Item.class.getMethod("setSize", pFloat));
267 _SetMethods.put("s", Item.class.getMethod("setSize", pFloat));
268
269 _SetMethods.put("foregroundcolor", Frame.class.getMethod(
270 "setForegroundColor", pColor));
271 _SetMethods.put("fgc", Frame.class.getMethod("setForegroundColor",
272 pColor));
273 _SetMethods.put("backgroundcolor0", Frame.class.getMethod(
274 "setBackgroundColor", pColor));
275 _SetMethods.put("bgc0", Frame.class.getMethod("setBackgroundColor",
276 pColor));
277 _SetMethods.put("permission", Frame.class.getMethod(
278 "setPermission", pPermission));
279
280 } catch (SecurityException e) {
281 // TODO Auto-generated catch block
282 e.printStackTrace();
283 } catch (NoSuchMethodException e) {
284 // TODO Auto-generated catch block
285 e.printStackTrace();
286 }
287 }
288
289 /**
290 * Extracts a list of attributes from the given Object. Any method that
291 * starts with <code>get</code>, takes no arguments and is not found in
292 * the Ignore list will be run, All the attributes are then put into a Text
293 * Item of the form <Name>:<Value> If the value returned by the get method
294 * is null, then the attribute will not be included, unless the name of the
295 * method is found in the AllowNull list.
296 *
297 * @param toExtract
298 * The Object from which to extract the attributes
299 * @return A Text Item containing the extracted Attributes.
300 */
301 public static Item extractAttributes(Object toExtract) {
302 if (toExtract == null)
303 return null;
304
305 // ensure the lists are populated
306 if (_Ignore == null)
307 initLists();
308
309 // StringBuffer to store all the extracted Attribute:Value pairs
310 StringBuffer attributes = new StringBuffer();
311
312 // iterate through the list of methods
313 for (Method m : _GetMethods) {
314
315 // Make sure the classes of the methods match the item
316 if (m.getDeclaringClass().isAssignableFrom(toExtract.getClass())) {
317 try {
318 Object o = m.invoke(toExtract, (Object[]) null);
319
320 if (o == null) {
321 // methods that return null are only included if they
322 // are in the AllowNull list
323 if (_AllowNull.contains(m)) {
324 String name = m.getName().substring(GET_LENGTH)
325 .toLowerCase();
326 if (name.equals("color"))
327 o = "default";
328 else if (name.equals("backgroundcolor"))
329 o = "transparent";
330 else if (name.equals("foregroundcolor"))
331 o = "auto";
332 else
333 o = "";
334 } else {
335 continue;
336 }
337 }
338 // skip methods that are in the ignore lists
339 if (_ExtractIgnore.contains(m.getName().substring(
340 GET_LENGTH).toLowerCase())) {
341 continue;
342 }
343
344 if (o instanceof Integer) {
345 Integer i = (Integer) o;
346 if (i == Item.DEFAULT_INTEGER)
347 continue;
348 if (m.getName().endsWith("Justification")
349 && ((Justification) o).toString() != null)
350 o = ((Justification) o).toString();
351 // -1 indicates default value
352 else
353 o = i;
354 } else if (o instanceof Float) {
355 if (((Float) o) < -0.0001)
356 continue;
357 //Null indicates default
358 o = Math.round((Float) o);
359 } else if (o instanceof Double) {
360 // -1 indicates default value
361 if (((Double) o) < 0.0001)
362 continue;
363 } else if (o instanceof Color) {
364 // converts the color to the Expeditee code
365 o = Conversion.getExpediteeColorCode((Color) o);
366 if (o == null)
367 continue;
368 } else if (o instanceof Point) {
369 Point p = (Point) o;
370 o = Math.round(p.getX()) + " " + Math.round(p.getY());
371 } else if (o instanceof Font) {
372 Font f = (Font) o;
373
374 String s = f.getName() + "-";
375 if (f.isPlain())
376 s += "Plain";
377
378 if (f.isBold())
379 s += "Bold";
380
381 if (f.isItalic())
382 s += "Italic";
383
384 s += "-" + f.getSize();
385 o = s;
386 } else if (o instanceof Text) {
387 o = ((Text) o).getFirstLine();
388 } else if (o instanceof List) {
389 List list = (List) o;
390 for (Object ob : list)
391 attributes
392 .append(m.getName().substring(GET_LENGTH))
393 .append(AttributeValuePair.SEPARATOR_STRING)
394 .append(ob).append('\n');
395 continue;
396 } else if (o instanceof int[]) {
397 StringBuffer sb = new StringBuffer();
398 int[] values = (int[]) o;
399 for (int i = 0; i < values.length; i++) {
400 sb.append(values[i]).append(' ');
401 }
402 sb.deleteCharAt(sb.length() - 1);
403 o = sb.toString();
404 } else if (o instanceof Boolean) {
405 // true is the default for boolean values
406 if (((Boolean) o).booleanValue())
407 continue;
408 }
409 // Append the attributes
410 attributes.append(m.getName().substring(GET_LENGTH))
411 .append(AttributeValuePair.SEPARATOR_STRING)
412 .append(o).append('\n');
413 } catch (Exception e) {
414 // TODO Auto-generated catch block
415 e.printStackTrace();
416 }
417 }
418 }
419
420 // if no attributes were extracted
421 if (attributes.length() <= 0)
422 return null;
423
424 while (attributes.charAt(attributes.length() - 1) == '\n')
425 attributes.delete(attributes.length() - 1, attributes.length());
426
427 // create the text Item
428 Frame current = DisplayIO.getCurrentFrame();
429 Item attribs = current.getStatsTextItem(attributes.toString());
430 return attribs;
431 }
432
433 /**
434 * Attempts to set the attribute in the given attribute: value pair. The
435 * value string should be formatted as follows:
436 * <code> Attribute: Value </code> Multiple values can be used if they are
437 * separated by spaces
438 *
439 * @param toSet
440 * The Item or Frame to set the attribute of
441 * @param attribs
442 * The Text item that contains the list of attributes to set
443 * @return True if the attribute(s) were sucessfully set, false otherwise
444 */
445 public static boolean setAttribute(Object toSet, Text attribs) {
446 return setAttribute(toSet, attribs, 1);
447 }
448
449 public static boolean setAttribute(Object toSet, Text attribs, int minAttributeLength) {
450 // error checking
451 if (toSet == null || attribs == null)
452 return false;
453
454 if (_Ignore == null)
455 initLists();
456
457 //if(attribs.isAnnotation())
458 // return false;
459
460 // get the list of attribute: value pairs
461 List<String> values = attribs.getTextList();
462 // if no pairs exist, we are done
463 if (values == null || values.size() == 0) {
464 return false;
465 }
466
467 // loop through all attribute: value pairs
468 for (int i = 0; i < values.size(); i++) {
469 AttributeValuePair avp = new AttributeValuePair(values.get(i), false);
470
471 // If the first is not an attribute value pair then dont do
472 // attrubute merging
473 if (!avp.hasAttribute() || avp.getAttribute().length() < minAttributeLength)
474 return false;
475
476 // check if the next string is another attribute to merge or a
477 // continuation
478 for (; i < values.size() - 1; i++) {
479 AttributeValuePair nextAvp = new AttributeValuePair(values
480 .get(i + 1), false);
481
482 // if the next String has a colon, then it may be another
483 // attribute
484 if (nextAvp.hasAttribute()) {
485 // if the attribute is the same as v, then it is a
486 // continuation
487 if (nextAvp.getAttribute().equals(avp.getAttribute())) {
488 // strip the attribute from next
489 avp.appendValue(nextAvp.getValue());
490
491 // if the attribute is not the same, then it may be a
492 // new method
493 } else {
494 break;
495 }
496 }
497
498 // v.append("\n").append(next);
499 }
500
501 if (!setAttribute(toSet, avp, values.size() > 1)) {
502
503 String stripped = avp.getAttribute();
504 if (!avp.hasPair()) {
505 // This happens when there is an attribute at the start
506 // Then a bunch of plain text
507 return false;
508 } else if (_Ignore.contains(stripped)) {
509 return false;
510 } else if (!(_SetMethods.containsKey(stripped))) {
511 return false;
512 } else {
513 String types = "";
514 for (Class c : _SetMethods.get(stripped)
515 .getParameterTypes())
516 types += c.getSimpleName() + " ";
517 MessageBay.warningMessage("Wrong arguments for: '"
518 + avp.getAttribute() + "' expecting "
519 + types.trim() + " found '" + avp.getValue() + "'");
520 }
521 }
522 }
523
524 return true;
525 }
526
527 /**
528 * Sets a single attrubute of a frame or item.
529 *
530 * @param toSet
531 * @param avp
532 * @param isAttributeList
533 * some properties are ignored when attribute list are injected
534 * into an item. These properties are ignored if this param is
535 * true
536 * @return
537 */
538 private static boolean setAttribute(Object toSet, AttributeValuePair avp,
539 boolean isAttributeList) {
540
541 assert (avp.hasAttribute());
542
543 // separate attribute and value from string
544 String attribute = avp.getAttribute().toLowerCase();
545
546 String value = avp.getValue();
547 assert (value != null);
548
549 // Some properties are ignored when multiple attributes are being set on
550 // an item at the same time
551 if (isAttributeList && _Ignore.contains(attribute)) {
552 // System.out.println("Attribute ignored: " + attribute);
553 return true;
554 }
555
556 // Separate multiple values if required
557 Method toRun = _SetMethods.get(attribute);
558
559 // if this is not the name of a method, it may be the name of an agent
560 if (toRun == null) {
561 // System.out.println("Attrib not found for: " + attribute);
562 return false;
563 }
564
565 // if there are duplicate methods with the same name
566 List<Method> possibles = new LinkedList<Method>();
567 if (toRun.getDeclaringClass().isInstance(toSet))
568 possibles.add(toRun);
569 int i = 0;
570 while (_SetMethods.containsKey(attribute + i)) {
571 if (_SetMethods.get(attribute + i).getDeclaringClass()
572 .isAssignableFrom(toSet.getClass()))
573 possibles.add(_SetMethods.get(attribute + i));
574 i++;
575 }
576
577 for (Method possible : possibles) {
578 Object current = null;
579 Object[] param = {};
580 // find the corresponding get method for this set method
581 // and get the current value of the attribute
582 for (Method m : _GetMethods) {
583 if (m.getDeclaringClass().isAssignableFrom(toSet.getClass())
584 && m.getName().substring(GET_LENGTH).equals(
585 possible.getName().substring(SET_LENGTH))) {
586 try {
587 current = m.invoke(toSet, param);
588 } catch (IllegalArgumentException e) {
589 // TODO Auto-generated catch block
590 e.printStackTrace();
591 } catch (IllegalAccessException e) {
592 // TODO Auto-generated catch block
593 e.printStackTrace();
594 } catch (InvocationTargetException e) {
595 // TODO Auto-generated catch block
596 e.printStackTrace();
597 }
598 break;
599 }
600
601 }
602
603 try {
604 Object[] params = Conversion.Convert(possible, value, current);
605
606 try {
607 possible.invoke(toSet, params);
608 return true;
609 } catch (IllegalArgumentException e) {
610 // TODO Auto-generated catch block
611 e.printStackTrace();
612 } catch (IllegalAccessException e) {
613 // TODO Auto-generated catch block
614 e.printStackTrace();
615 } catch (InvocationTargetException e) {
616 MessageBay.displayMessage(toSet.getClass().getSimpleName()
617 + " type does not support that attribute.");
618 // e.printStackTrace();
619 }
620 } catch (NumberFormatException e) {
621
622 }
623 }
624
625 return false;
626 }
627
628 /**
629 * Replaces the current value for the text item with the new value.
630 *
631 * @param text
632 * the item whos value is to be changed
633 * @param newValue
634 * the new value for the item
635 */
636 public static void replaceValue(Text text, String newValue) {
637 assert (newValue != null);
638
639 AttributeValuePair avp = new AttributeValuePair(text.getText());
640
641 if (avp.getAttribute() == null) {
642 avp.setAttribute(avp.getValue());
643 }
644 avp.setValue(newValue);
645 text.setText(avp.toString());
646 }
647}
Note: See TracBrowser for help on using the repository browser.