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

Last change on this file since 1506 was 1506, checked in by bnemhaus, 4 years ago

Permissions for encrypting frames are now respected. (Group level permissions still need testing and maybe implementation)

The current implementation of Hetrogeneous Owner requires that the owner of the frame specify the available labels. Injecting the property "HetrogeneousEncryptionLabels: <label name>" into the frame name item adds the specified label to the list of labels that those with 'Hetrogeneous (Owner)' permission are able to use.

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