source: trunk/org/expeditee/gui/AttributeUtils.java@ 4

Last change on this file since 4 was 4, checked in by davidb, 16 years ago

Starting source code to Expeditee

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