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

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

Made both types of messages (normal and overwrite mode) output the numbered prefix

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