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

Last change on this file since 1405 was 1405, checked in by bln4, 5 years ago

Added Group attribute to frames.

Some early logic on using the group attribute to determine group members. At this point just detects if the specified group doesn't actually exist. Will do more soon.

File size: 31.3 KB
Line 
1/**
2 * AttributeUtils.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.gui;
20
21import java.lang.reflect.InvocationTargetException;
22import java.lang.reflect.Method;
23import java.util.HashMap;
24import java.util.LinkedList;
25import java.util.List;
26
27import org.expeditee.core.Colour;
28import org.expeditee.core.Font;
29import org.expeditee.core.Point;
30import org.expeditee.encryption.items.EncryptionPermissionTriple;
31import org.expeditee.io.Conversion;
32import org.expeditee.items.DotType;
33import org.expeditee.items.Item;
34import org.expeditee.items.Justification;
35import org.expeditee.items.PermissionTriple;
36import org.expeditee.items.Text;
37import org.expeditee.simple.IncorrectTypeException;
38
39/**
40 * This class provides the methods to extract and set attributes of Items and
41 * Frames. These methods are called when a user merges a text item with
42 * <code>Attribute: Value</code> pairs.
43 *
44 * @author jdm18
45 *
46 */
47public class AttributeUtils {
48
49 public static final class Attribute {
50 public final String displayName;
51 public final Method getter;
52 public final Method setter;
53
54 public Attribute(String displayName, Method getter, Method setter) {
55 this.displayName = displayName;
56 this.getter = getter;
57 this.setter = setter;
58 }
59 }
60
61 public static final class AttributeSet {
62
63 // the internal hashmap
64 private final HashMap<String, Attribute> map;
65 // a list of keys in the order they were added (used to make attribute extraction consistent)
66 public final List<String> keys;
67
68 public AttributeSet(int size) {
69 map = new HashMap<String, Attribute>(size);
70 keys = new LinkedList<String>();
71 }
72
73 public void put(String attributeName, Method getter, Method setter) {
74 if(map.containsKey(attributeName.toLowerCase())) {
75 System.err.println(this + " already contains key '" + attributeName + "', overwriting value!");
76 } else {
77 // we keep an ordered list of attributes for extraction
78 keys.add(attributeName.toLowerCase());
79 }
80 map.put(attributeName.toLowerCase(), new Attribute(attributeName, getter, setter));
81 }
82
83 // Create a second reference the the same Attribute, using a different name
84 // Does not modify the list of keys
85 public void alias(String alias, String name) {
86 if(map.containsKey(name.toLowerCase())) {
87 map.put(alias.toLowerCase(), map.get(name.toLowerCase()));
88 } else {
89 System.err.println("Cannot add alias '" + alias + "', because key '" + name + "' does not exist!");
90 }
91 }
92
93 public boolean containsKey(String key) {
94 return map.containsKey(key);
95 }
96
97 public Attribute get(String key) {
98 return map.get(key);
99 }
100 }
101
102 public static final AttributeSet _Attrib = new AttributeSet(128);
103 public static final AttributeSet _FrameAttrib = new AttributeSet(16);
104
105
106 // List of attributes which are ignored when extracting attributes
107 private static List<String> _IgnoreGet = null;
108 // List of attributes which are ignored when setting attributes,
109 // if multiple attributes are being set at once
110 private static List<String> _IgnoreSet = null;
111
112 /***************************************************************************
113 * List of method names to show in extraced lists even when they return null
114 * (Null is often used to indicate the default value is used)
115 **************************************************************************/
116 private static List<Method> _AllowNull = null;
117
118 // private static HashMap<String, String> _Abbreviations = null;
119
120 public static void ensureReady() {
121 if(_IgnoreSet == null) {
122 initLists();
123 }
124 }
125
126 /**
127 * Initialises the _Ignore and _AllowNull lists.
128 */
129 private static void initLists() {
130
131 try {
132
133 Class<?>[] pPoint = { Point.class };
134 Class<?>[] pString = { String.class };
135 Class<?>[] pInt = { int.class };
136 Class<?>[] pIntO = { Integer.class };
137 Class<?>[] pFloat = { float.class };
138 Class<?>[] pFloatO = { Float.class };
139 Class<?>[] pDouble = {double.class };
140 Class<?>[] pColor = { Colour.class };
141 Class<?>[] pBool = { boolean.class };
142 //Class[] pDouble = { double.class };
143 //Class[] pDoubleO = { Double.class };
144 Class<?>[] pArrow = { float.class, double.class, double.class };
145 Class<?>[] pList = { List.class };
146 Class<?>[] pIntArray = { int[].class };
147 Class<?>[] pJustification = { Justification.class };
148 Class<?>[] pPermission = { PermissionTriple.class };
149 Class<?>[] pDotType = { DotType.class };
150 Class<?>[] pEncPermission = { EncryptionPermissionTriple.class };
151
152 _IgnoreSet = new LinkedList<String>();
153 _IgnoreGet = new LinkedList<String>();
154 _AllowNull = new LinkedList<Method>();
155
156 // TODO load these in with reflection...
157 // Set the shortcuts with annotation tags on the methods
158 _IgnoreSet.add("date");
159 _IgnoreSet.add("datecreated");
160 _IgnoreSet.add("d");
161 _IgnoreSet.add("link");
162 _IgnoreSet.add("l");
163 _IgnoreSet.add("action");
164 _IgnoreSet.add("a");
165 _IgnoreSet.add("position");
166 _IgnoreSet.add("pos");
167 _IgnoreSet.add("p");
168 _IgnoreSet.add("x");
169 _IgnoreSet.add("y");
170
171 _IgnoreGet.add("x");
172 _IgnoreGet.add("y");
173 _IgnoreGet.add("text");
174 _IgnoreGet.add("gradientangle");
175
176 _AllowNull.add(Item.class.getMethod("getColor"));
177 _AllowNull.add(Item.class.getMethod("getBackgroundColor"));
178
179 _AllowNull.add(Frame.class.getMethod("getBackgroundColor"));
180 _AllowNull.add(Frame.class.getMethod("getForegroundColor"));
181
182 /*
183 * Populate the backing lists of attributes
184 */
185
186 // Frames
187 _FrameAttrib.put("Permission", Frame.class.getMethod("getPermission"),
188 Frame.class.getMethod("setPermission", pPermission));
189 _FrameAttrib.put("Owner", Frame.class.getMethod("getOwner"),
190 Frame.class.getMethod("setOwner", pString));
191 _FrameAttrib.put("DateCreated", Frame.class.getMethod("getDateCreated"),
192 null);
193 _FrameAttrib.put("LastModifyUser", Frame.class.getMethod("getLastModifyUser"),
194 null);
195 _FrameAttrib.put("LastModifyDate", Frame.class.getMethod("getLastModifyDate"),
196 null);
197 _FrameAttrib.put("ForegroundColor", Frame.class.getMethod("getForegroundColor"),
198 Frame.class.getMethod("setForegroundColor", pColor));
199 _FrameAttrib.put("BackgroundColor", Frame.class.getMethod("getBackgroundColor"),
200 Frame.class.getMethod("setBackgroundColor", pColor));
201 _FrameAttrib.put("EncryptionLabel", Frame.class.getMethod("getEncryptionLabel"),
202 Frame.class.getMethod("setEncryptionLabel", pString));
203 _FrameAttrib.put("EncPermission", Frame.class.getMethod("getEncryptionPermission"),
204 Frame.class.getMethod("setEncryptionPermission", pEncPermission));
205 _FrameAttrib.put("Group", Frame.class.getMethod("getGroup"),
206 Frame.class.getMethod("setGroup", pString));
207
208
209 // aliases for attribute setting
210 _FrameAttrib.alias("fgc", "foregroundcolor");
211 _FrameAttrib.alias("bgc", "backgroundcolor");
212 _FrameAttrib.alias("p", "permission");
213 _FrameAttrib.alias("enc", "encryptionlabel");
214 _FrameAttrib.alias("encp", "encpermission");
215 _FrameAttrib.alias("EncryptionPermission", "encpermission");
216
217
218 // Generic Items
219 _Attrib.put("DateCreated", Item.class.getMethod("getDateCreated"),
220 Item.class.getMethod("setDateCreated", pString));
221 _Attrib.put("Color", Item.class.getMethod("getColor"),
222 Item.class.getMethod("setColor", pColor));
223 _Attrib.put("BackgroundColor", Item.class.getMethod("getBackgroundColor"),
224 Item.class.getMethod("setBackgroundColor", pColor));
225 _Attrib.put("BorderColor", Item.class.getMethod("getBorderColor"),
226 Item.class.getMethod("setBorderColor", pColor));
227 _Attrib.put("AnchorLeft", Item.class.getMethod("getAnchorLeft"),
228 Item.class.getMethod("setAnchorLeft", pIntO));
229 _Attrib.put("AnchorRight", Item.class.getMethod("getAnchorRight"),
230 Item.class.getMethod("setAnchorRight", pIntO));
231 _Attrib.put("AnchorTop", Item.class.getMethod("getAnchorTop"),
232 Item.class.getMethod("setAnchorTop", pIntO));
233 _Attrib.put("AnchorBottom", Item.class.getMethod("getAnchorBottom"),
234 Item.class.getMethod("setAnchorBottom", pIntO));
235 _Attrib.put("Position", Item.class.getMethod("getPosition"),
236 Item.class.getMethod("setPosition", pPoint));
237 _Attrib.put("Link", Item.class.getMethod("getLink"),
238 Item.class.getMethod("setLink", pString));
239 _Attrib.put("AddToHistory", Item.class.getMethod("getLinkHistory"),
240 Item.class.getMethod("setLinkHistory", pBool));
241 _Attrib.put("Action", Item.class.getMethod("getAction"),
242 Item.class.getMethod("setActions", pList));
243 _Attrib.put("ActionMark", Item.class.getMethod("getActionMark"),
244 Item.class.getMethod("setActionMark", pBool));
245 _Attrib.put("ActionCursorEnter", Item.class.getMethod("getActionCursorEnter"),
246 Item.class.getMethod("setActionCursorEnter", pList));
247 _Attrib.put("ActionCursorLeave", Item.class.getMethod("getActionCursorLeave"),
248 Item.class.getMethod("setActionCursorLeave", pList));
249 _Attrib.put("ActionEnterFrame", Item.class.getMethod("getActionEnterFrame"),
250 Item.class.getMethod("setActionEnterFrame", pList));
251 _Attrib.put("ActionLeaveFrame", Item.class.getMethod("getActionLeaveFrame"),
252 Item.class.getMethod("setActionLeaveFrame", pList));
253 _Attrib.put("Data", Item.class.getMethod("getData"),
254 Item.class.getMethod("setData", pList));
255 _Attrib.put("Highlight", Item.class.getMethod("getHighlight"),
256 Item.class.getMethod("setHighlight", pBool));
257 _Attrib.put("FillColor", Item.class.getMethod("getFillColor"),
258 Item.class.getMethod("setFillColor", pColor));
259 _Attrib.put("GradientColor", Item.class.getMethod("getGradientColor"),
260 Item.class.getMethod("setGradientColor", pColor));
261 _Attrib.put("GradientAngle", Item.class.getMethod("getGradientAngle"),
262 Item.class.getMethod("setGradientAngle", pDouble));
263 _Attrib.put("FillPattern", Item.class.getMethod("getFillPattern"),
264 Item.class.getMethod("setFillPattern", pString));
265 _Attrib.put("Owner", Item.class.getMethod("getOwner"),
266 Item.class.getMethod("setOwner", pString));
267 _Attrib.put("LinkMark", Item.class.getMethod("getLinkMark"),
268 Item.class.getMethod("setLinkMark", pBool));
269 _Attrib.put("LinkFrameset", Item.class.getMethod("getLinkFrameset"),
270 Item.class.getMethod("setLinkFrameset", pString));
271 _Attrib.put("LinkTemplate", Item.class.getMethod("getLinkTemplate"),
272 Item.class.getMethod("setLinkTemplate", pString));
273 _Attrib.put("LinePattern", Item.class.getMethod("getLinePattern"),
274 Item.class.getMethod("setLinePattern", pIntArray));
275 _Attrib.put("Arrow", Item.class.getMethod("getArrow"),
276 Item.class.getMethod("setArrow", pArrow));
277 _Attrib.put("DotType", Item.class.getMethod("getDotType"),
278 Item.class.getMethod("setDotType", pDotType));
279 _Attrib.put("Filled", Item.class.getMethod("getFilled"),
280 Item.class.getMethod("setFilled", pBool));
281 _Attrib.put("Formula", Item.class.getMethod("getFormula"),
282 Item.class.getMethod("setFormula", pString));
283 _Attrib.put("Thickness", Item.class.getMethod("getThickness"),
284 Item.class.getMethod("setThickness", pFloat));
285// _Attrib.put("LineIDs", Item.class.getMethod("getLineIDs"),
286// Item.class.getMethod("setLineIDs", pString));
287// _Attrib.put("ConstraintIDs", Item.class.getMethod("getConstraintIDs"),
288// Item.class.getMethod("setConstraintIDs", pString));
289 _Attrib.put("Size", Item.class.getMethod("getSize"),
290 Item.class.getMethod("setSize", pFloat));
291 _Attrib.put("Save", Item.class.getMethod("getSave"),
292 Item.class.getMethod("setSave", pBool));
293 _Attrib.put("AutoStamp", Item.class.getMethod("getAutoStamp"),
294 Item.class.getMethod("setAutoStamp", pFloatO));
295 _Attrib.put("Width", Item.class.getMethod("getWidthToSave"),
296 Item.class.getMethod("setWidth", pIntO));
297 _Attrib.put("MinWidth", Item.class.getMethod("getMinWidthToSave"),
298 Item.class.getMethod("setMinWidth", pIntO));
299 _Attrib.put("X", null,
300 Item.class.getMethod("setX", pFloat));
301 _Attrib.put("Y", null,
302 Item.class.getMethod("setY", pFloat));
303 _Attrib.put("Tooltip", Item.class.getMethod("getTooltip"),
304 Item.class.getMethod("setTooltips", pList));
305 _Attrib.put("Permission", Item.class.getMethod("getPermission"),
306 Item.class.getMethod("setPermission", pPermission));
307 _Attrib.put("EncryptionLabel", Item.class.getMethod("getEncryptionLabel"),
308 Item.class.getMethod("setEncryptionLabel", pString));
309
310 // Text Items
311 _Attrib.put("Family", Text.class.getMethod("getFamily"),
312 Text.class.getMethod("setFamily", pString));
313 _Attrib.put("FontStyle", Text.class.getMethod("getFontStyle"),
314 Text.class.getMethod("setFontStyle", pString));
315 _Attrib.put("Justification", Text.class.getMethod("getJustification"),
316 Text.class.getMethod("setJustification", pJustification));
317 _Attrib.put("AutoWrap", Text.class.getMethod("getAutoWrapToSave"),
318 Text.class.getMethod("setAutoWrap", pBool));
319
320 _Attrib.put("LineSpacing", Text.class.getMethod("getSpacing"),
321 Text.class.getMethod("setSpacing", pFloat));
322
323 _Attrib.put("LetterSpacing", Text.class.getMethod("getLetterSpacing"),
324 Text.class.getMethod("setLetterSpacing", pFloat));
325 _Attrib.put("Mask", Text.class.getMethod("getMask"),
326 Text.class.getMethod("setMask", pIntO));
327 _Attrib.put("Placeholder", Text.class.getMethod("getPlaceholder"),
328 Text.class.getMethod("setPlaceholder", pString));
329 _Attrib.put("SingleLineOnly", Text.class.getMethod("isSingleLineOnly"),
330 Text.class.getMethod("setSingleLineOnly", pBool));
331 _Attrib.put("TabIndex", Text.class.getMethod("getTabIndex"),
332 Text.class.getMethod("setTabIndex", pInt));
333
334 // Aliases for attribute setting
335 _Attrib.alias("pos", "position");
336 _Attrib.alias("p", "position");
337 _Attrib.alias("xy", "position");
338 _Attrib.alias("a", "action");
339 _Attrib.alias("d", "data");
340 _Attrib.alias("f", "formula");
341 _Attrib.alias("font", "family");
342 _Attrib.alias("s", "size");
343 _Attrib.alias("l", "link");
344 _Attrib.alias("at", "anchortop");
345 _Attrib.alias("ab", "anchorbottom");
346 _Attrib.alias("al", "anchorleft");
347 _Attrib.alias("ar", "anchorright");
348 _Attrib.alias("t", "thickness");
349 // _Attrib.alias("c", "color"); // breaks circle creation
350 _Attrib.alias("bgc", "backgroundcolor");
351 _Attrib.alias("bc", "bordercolor");
352 _Attrib.alias("fc", "fillcolor");
353 _Attrib.alias("gc", "gradientcolor");
354 _Attrib.alias("ga", "gradientangle");
355 _Attrib.alias("fp", "fillpattern");
356 _Attrib.alias("lm", "linkmark");
357 _Attrib.alias("am", "actionmark");
358 _Attrib.alias("dt", "dottype");
359 _Attrib.alias("fill", "filled");
360 _Attrib.alias("lp", "linepattern");
361 _Attrib.alias("lf", "linkframeset");
362 _Attrib.alias("lt", "linktemplate");
363 _Attrib.alias("face", "fontstyle");
364 _Attrib.alias("j", "justification");
365 _Attrib.alias("w", "width");
366 _Attrib.alias("mw", "minwidth");
367 _Attrib.alias("as", "autostamp");
368 } catch (SecurityException e) {
369 // TODO Auto-generated catch block
370 e.printStackTrace();
371 } catch (NoSuchMethodException e) {
372 // TODO Auto-generated catch block
373 e.printStackTrace();
374 }
375 }
376
377 /**
378 * Extracts a list of attributes from the given Item. Any method that
379 * starts with <code>get</code>, takes no arguments and is not found in
380 * the Ignore list will be run, All the attributes are then put into a Text
381 * Item of the form <Name>:<Value> If the value returned by the get method
382 * is null, then the attribute will not be included, unless the name of the
383 * method is found in the AllowNull list.
384 *
385 * @param toExtract
386 * The Object from which to extract the attributes
387 * @return A Text Item containing the extracted Attributes.
388 */
389 public static Item extractAttributes(Object toExtract) {
390
391 // System.out.println(toExtract);
392
393 if (toExtract == null) {
394 return null;
395 }
396
397 // Ensure the lists are populated
398 ensureReady();
399
400 AttributeSet attribSet = null;
401 if(toExtract instanceof Frame) {
402 attribSet = _FrameAttrib;
403 } else if(toExtract instanceof Item) {
404 attribSet = _Attrib;
405 } else {
406 throw new IncorrectTypeException("toExtract", "Item | Frame");
407 }
408
409 // StringBuffer to store all the extracted Attribute:Value pairs
410 StringBuffer attributes = new StringBuffer();
411
412 // iterate through the list of methods
413 for (String prop : attribSet.keys) {
414
415 Attribute a = attribSet.get(prop);
416 // Make sure the classes of the methods match the item
417 if (a != null && a.getter != null && a.getter.getDeclaringClass().isAssignableFrom(toExtract.getClass())) {
418 try {
419 String s = getValue(prop, a, toExtract, true);
420 if (s == null) {
421 continue;
422 }
423 // Append the attributes
424 attributes.append(a.displayName)
425 .append(AttributeValuePair.SEPARATOR_STRING)
426 .append(s).append('\n');
427 } catch (Exception e) {
428 // TODO Auto-generated catch block
429 e.printStackTrace();
430 }
431 }
432 }
433
434 // if no attributes were extracted
435 if (attributes.length() <= 0) {
436 return null;
437 }
438
439 while (attributes.charAt(attributes.length() - 1) == '\n') {
440 attributes.delete(attributes.length() - 1, attributes.length());
441 }
442
443 // create the text Item
444 Frame current = DisplayController.getCurrentFrame();
445 Item attribs = current.getStatsTextItem(attributes.toString());
446 return attribs;
447 }
448
449 /**
450 * Gets a string form of the value for a given item get method.
451 * @param method
452 * @param item
453 * @param ignore true if the attributes in the IGNORE list should be ignored
454 * @return
455 */
456 private static String getValue(String name, Attribute a, Object item, boolean ignore) {
457 // assert(method.getName().startsWith("get"));
458
459 Object o = null;
460 try {
461 o = a.getter.invoke(item, (Object[]) null);
462 } catch (IllegalArgumentException e) {
463 e.printStackTrace();
464 return null;
465 } catch (IllegalAccessException e) {
466 e.printStackTrace();
467 return null;
468 } catch (InvocationTargetException e) {
469 e.printStackTrace();
470 return null;
471 }
472
473 if (o == null) {
474 // methods that return null are only included if they
475 // are in the AllowNull list
476 if (_AllowNull.contains(a.getter)) {
477 if (name.equals("color")) {
478 o = "default";
479 } else if (name.equals("backgroundcolor")) {
480 o = "transparent";
481 } else if (name.equals("foregroundcolor")) {
482 o = "auto";
483 } else {
484 o = "";
485 }
486 } else {
487 return null;
488 }
489 }
490 // skip methods that are in the ignore lists
491 if (ignore && _IgnoreGet.contains(name)) {
492 return null;
493 }
494
495 if (o instanceof Integer) {
496 Integer i = (Integer) o;
497 if (i == Item.DEFAULT_INTEGER) {
498 return null;
499 }
500 if (a.getter.getName().endsWith("Justification")
501 && ((Justification) o).toString() != null) {
502 o = ((Justification) o).toString();
503 // -1 indicates default value
504 } else {
505 o = i;
506 }
507 } else if (o instanceof Float) {
508 if (((Float) o) < -0.0001)
509 {
510 return null;
511 // Null indicates default
512 // o = Math.round((Float) o);
513 }
514 } else if (o instanceof Double) {
515 // -1 indicates default value
516 if (((Double) o) < 0.0001) {
517 return null;
518 }
519 } else if (o instanceof Colour) {
520 // converts the color to the Expeditee code
521 o = Conversion.getExpediteeColorCode((Colour) o);
522 if (o == null) {
523 return null;
524 }
525 } else if (o instanceof Point) {
526 Point p = (Point) o;
527 o = Math.round(p.getX()) + " " + Math.round(p.getY());
528 } else if (o instanceof Font) {
529 Font f = (Font) o;
530
531 String s = f.getFamilyName() + "-";
532 if (f.isPlain()) {
533 s += "Plain";
534 }
535
536 if (f.isBold()) {
537 s += "Bold";
538 }
539
540 if (f.isItalic()) {
541 s += "Italic";
542 }
543
544 s += "-" + f.getSize();
545 o = s;
546 } else if (o instanceof Text) {
547 o = ((Text) o).getFirstLine();
548 } else if (o instanceof List) {
549 List list = (List) o;
550 StringBuffer sb = new StringBuffer();
551 for (Object ob : list) {
552 // TODO check that this works ok
553 if (sb.length() == 0) {
554 sb.append(ob);
555 } else {
556 sb.append('\n').append(a.displayName).append(AttributeValuePair.SEPARATOR_STRING).append(ob);
557 }
558 }
559 return sb.toString();
560 } else if (o instanceof int[]) {
561 StringBuffer sb = new StringBuffer();
562 int[] values = (int[]) o;
563 for (int i = 0; i < values.length; i++) {
564 sb.append(values[i]).append(' ');
565 }
566 sb.deleteCharAt(sb.length() - 1);
567 o = sb.toString();
568 } else if (o instanceof Boolean) {
569 // true is the default for boolean values
570 if (((Boolean) o).booleanValue()) {
571 return null;
572 }
573 }
574 return o.toString();
575 }
576
577 /**
578 * Attempts to set the attribute in the given attribute: value pair. The
579 * value string should be formatted as follows:
580 * <code> Attribute: Value </code> Multiple values can be used if they are
581 * separated by spaces
582 *
583 * @param toSet
584 * The Item or Frame to set the attribute of
585 * @param attribs
586 * The Text item that contains the list of attributes to set
587 * @return True if the attribute(s) were sucessfully set, false otherwise
588 */
589 public static boolean setAttribute(Object toSet, Text attribs) {
590 return setAttribute(toSet, attribs, 1);
591 }
592
593 public static boolean setAttribute(Object toSet, Text attribs,
594 int minAttributeLength) {
595 // error checking
596 if (toSet == null || attribs == null) {
597 return false;
598 }
599
600 ensureReady();
601
602 AttributeSet attribSet = null;
603 if(toSet instanceof Frame) {
604 attribSet = _FrameAttrib;
605 } else if(toSet instanceof Item) {
606 attribSet = _Attrib;
607 } else {
608 throw new IncorrectTypeException("toExtract", "Item | Frame");
609 }
610
611 // if(attribs.isAnnotation())
612 // return false;
613
614 // get the list of attribute: value pairs
615 List<String> values = attribs.getTextList();
616 // if no pairs exist, we are done
617 if (values == null || values.size() == 0) {
618 return false;
619 }
620
621 // loop through all attribute: value pairs
622 for (int i = 0; i < values.size(); i++) {
623 AttributeValuePair avp = new AttributeValuePair(values.get(i),
624 false);
625
626 // If the first is not an attribute value pair then don't do
627 // attribute merging
628 if (!avp.hasAttribute()
629 || avp.getAttribute().length() < minAttributeLength) {
630 return false;
631 }
632
633 // check if the next string is another attribute to merge or a
634 // continuation
635 for (; i < values.size() - 1; i++) {
636 AttributeValuePair nextAvp = new AttributeValuePair(values
637 .get(i + 1), false);
638
639 // if the next String has a colon, then it may be another
640 // attribute
641 if (nextAvp.hasAttribute()) {
642 // if the attribute is the same as v, then it is a
643 // continuation
644 if (nextAvp.getAttribute().equals(avp.getAttribute())) {
645 // strip the attribute from next
646 avp.appendValue(nextAvp.getValue() + "\n");
647
648 // if the attribute is not the same, then it may be a
649 // new method
650 } else {
651 break;
652 }
653 }
654
655 // v.append("\n").append(next);
656 }
657
658 try {
659 if (!setAttribute(toSet, avp, values.size() > 1)) {
660
661 String stripped = avp.getAttribute();
662 if (!avp.hasPair()) {
663 // This happens when there is an attribute at the start
664 // Then a bunch of plain text
665 return false;
666 } else if (_IgnoreSet.contains(stripped)) {
667 return false;
668 } else {
669 Attribute a = attribSet.get(stripped);
670 if(a == null || a.setter == null) {
671 return false;
672 }
673 String types = "";
674 for (Class<?> c : a.setter.getParameterTypes()) {
675 types += c.getSimpleName() + " ";
676 }
677 MessageBay.warningMessage("Wrong arguments for: '"
678 + avp.getAttribute() + "' expecting "
679 + types.trim() + " found '" + avp.getValue() + "'");
680 }
681 }
682 } catch (AttributeException e) {
683 MessageBay.errorMessage(e.getMessage());
684 }
685 }
686
687 return true;
688 }
689
690 /**
691 * Sets a single attribute of a frame or item.
692 *
693 * @param toSet
694 * @param avp
695 * @param isAttributeList
696 * some properties are ignored when attribute list are injected
697 * into an item. These properties are ignored if this param is
698 * true
699 * @return
700 * @throws NoSuchAttributeException
701 */
702 private static boolean setAttribute(Object toSet, AttributeValuePair avp,
703 boolean isAttributeList) throws AttributeException {
704
705 assert (avp.hasAttribute());
706
707 // separate attribute and value from string
708 String attribute = avp.getAttribute().toLowerCase();
709
710 String value = avp.getValue();
711 assert (value != null);
712
713 AttributeSet attribSet = null;
714 if(toSet instanceof Frame) {
715 attribSet = _FrameAttrib;
716 } else if(toSet instanceof Item) {
717 attribSet = _Attrib;
718 } else {
719 throw new IncorrectTypeException("toExtract", "Item | Frame");
720 }
721
722 // Some properties are ignored when multiple attributes are being set on
723 // an item at the same time
724 if (isAttributeList && _IgnoreSet.contains(attribute)) {
725 // System.out.println("Attribute ignored: " + attribute);
726 return true;
727 }
728
729 // Separate multiple values if required
730
731 Attribute a = attribSet.get(attribute);
732 // if this is not the name of a method, it may be the name of an agent
733 if (a == null || a.setter == null) {
734 // System.out.println("Attrib not found for: " + attribute);
735 return false;
736 }
737
738 // if there are duplicate methods with the same name
739 List<Method> possibles = new LinkedList<Method>();
740 if (a.setter.getDeclaringClass().isInstance(toSet)) {
741 possibles.add(a.setter);
742 }
743 int i = 0;
744 while (attribSet.containsKey(attribute + i)) {
745 Method m = attribSet.get(attribute + i).setter;
746 if(m == null) {
747 break;
748 }
749 if (m.getDeclaringClass().isAssignableFrom(toSet.getClass())) {
750 possibles.add(m);
751 }
752 i++;
753 }
754
755 for (Method possible : possibles) {
756 Object current = invokeAttributeGetMethod(avp.getAttribute(), toSet);
757 // find the corresponding get method for this set method
758 // and get the current value of the attribute
759
760 try {
761 Object[] params = Conversion.Convert(possible, value, current);
762
763 try {
764 possible.invoke(toSet, params);
765 return true;
766 } catch (IllegalArgumentException e) {
767 // TODO Auto-generated catch block
768 e.printStackTrace();
769 } catch (IllegalAccessException e) {
770 // TODO Auto-generated catch block
771 e.printStackTrace();
772 } catch (InvocationTargetException e) {
773 MessageBay.displayMessage(toSet.getClass().getSimpleName()
774 + " type does not support that attribute.");
775 // e.printStackTrace();
776 }
777 } catch (NumberFormatException e) {
778
779 }
780 }
781
782 if(possibles.size() == 0){
783 if(invokeAttributeGetMethod(avp.getAttribute(), toSet) == null) {
784 throw new NoSuchAttributeException(avp.getAttribute(), toSet.getClass().getSimpleName());
785 }
786 throw new ReadOnlyAttributeException(avp.getAttribute(), toSet.getClass().getSimpleName());
787 }
788
789 return false;
790 }
791
792 private static Object invokeAttributeGetMethod(String name, Object toSet) {
793
794 AttributeSet attribSet = null;
795 if(toSet instanceof Frame) {
796 attribSet = _FrameAttrib;
797 } else if(toSet instanceof Item) {
798 attribSet = _Attrib;
799 } else {
800 throw new IncorrectTypeException("toExtract", "Item | Frame");
801 }
802
803 Attribute a = attribSet.get(name.toLowerCase());
804 if(a == null) {
805 return null;
806 }
807 try {
808 return a.getter.invoke(toSet);
809 } catch (Exception e) {
810 e.printStackTrace();
811 }
812 return null;
813 }
814
815 /**
816 * Replaces the current value for the text item with the new value.
817 *
818 * @param text
819 * the item whos value is to be changed
820 * @param newValue
821 * the new value for the item
822 */
823 public static void replaceValue(Text text, String newValue) {
824 assert (newValue != null);
825
826 AttributeValuePair avp = new AttributeValuePair(text.getText());
827
828 if (avp.getAttribute() == null) {
829 avp.setAttribute(avp.getValue());
830 }
831 avp.setValue(newValue);
832 text.setText(avp.toString());
833 }
834
835 public static String getAttribute(Item item, String attribute) {
836
837 // ensure the lists are populated
838 ensureReady();
839
840 // separate attribute and value from string
841 String lowerAttribute = attribute.trim().toLowerCase();
842
843 Attribute a = _Attrib.get(lowerAttribute);
844 if(a == null) {
845 MessageBay.errorMessage("Could no extract unknown attribute value: " + attribute);
846 return null;
847 }
848 return a.displayName + AttributeValuePair.SEPARATOR_STRING + getValue(lowerAttribute, a, item, false);
849 }
850}
Note: See TracBrowser for help on using the repository browser.