Source code: com/port80/util/attr/AttrTable.java
1 //
2 // Copyright(c) 2002, Chris Leung
3 //
4
5 package com.port80.util.attr;
6
7 import java.util.HashMap;
8 import java.util.Iterator;
9 import java.util.Map;
10 import java.util.Set;
11 import java.util.TreeSet;
12
13 import com.port80.util.msg;
14
15 /** A base class to access an attribute table.
16 *
17 * . Attribute table always store attributes in their native format,
18 * eg. color as Color object. Clients accessing the attribute table
19 * should knows the attribute type it is accessing.
20 * . For convenient, attributes can always be get/store through a
21 * String representation. attrString() always return the String
22 * representation of the attribute object and createAttr() method
23 * converts the String to the appropriate object type by consulting
24 * the AttrRegistry.
25 *
26 * @see IAttrTable
27 */
28 public class AttrTable implements IAttrTable {
29
30 // Static fields ///////////////////////////////////////////////////////
31 //
32
33 private static final String NAME = "AttrTable";
34 private static final String PACKAGENAME = "com.port80.graph";
35 private static final String CLASSNAME = PACKAGENAME + "." + NAME;
36 private static final int VERSION = 0x0001;
37 private static final String VERSIONNAME = "0.1";
38 private static boolean DEBUG = false;
39
40 // Instance fields /////////////////////////////////////////////////////
41 //
42
43 protected IAttrTable parentAttrTable = null;
44 private IAttrRegistry attrRegistry = null;
45 private Map attrTable = new HashMap(3);
46
47 // Constructors ////////////////////////////////////////////////////////
48 //
49
50 public AttrTable(IAttrTable parent) {
51 parentAttrTable = parent;
52 }
53
54 public AttrTable(IAttrTable parent, IAttrRegistry r) {
55 parentAttrTable = parent;
56 attrRegistry=r;
57 }
58
59 // Instance methods ////////////////////////////////////////////////////
60 //
61
62 public IAttrRegistry getAttrRegistry() {
63 if (parentAttrTable != null)
64 return parentAttrTable.getAttrRegistry();
65 return attrRegistry;
66 }
67
68 ////////////////////////////////////////////////////////////////////////
69
70 /** Get attribute. Automatically get the default attribute if
71 * local attribute is not defined.
72 */
73 public Object getAttr(String name) {
74 Object ret = attrTable.get(name);
75 if (ret != null)
76 return ret;
77 if (parentAttrTable != null)
78 return parentAttrTable.getAttr(name);
79 return ret;
80 }
81
82 public String getAttrString(String name) {
83 String ret = (String) attrTable.get(name);
84 if (ret != null)
85 return ret;
86 if (parentAttrTable != null)
87 return parentAttrTable.getAttrString(name);
88 return null;
89 }
90
91 public boolean getAttrBool(String name) {
92 Boolean ret = (Boolean) attrTable.get(name);
93 if (ret != null)
94 return ret.booleanValue();
95 if (parentAttrTable != null)
96 return parentAttrTable.getAttrBool(name);
97 return false;
98 }
99
100 public int getAttrInt(String name) {
101 Integer ret = (Integer) attrTable.get(name);
102 if (ret != null)
103 return ret.intValue();
104 if (parentAttrTable != null)
105 return parentAttrTable.getAttrInt(name);
106 msg.err("AttrTable.getAttrInt(): failed: name=" + name);
107 return -1;
108 }
109
110 public long getAttrLong(String name) {
111 Long ret = (Long) attrTable.get(name);
112 if (ret != null)
113 return ret.longValue();
114 if (parentAttrTable != null)
115 return parentAttrTable.getAttrLong(name);
116 msg.err("AttrTable.getAttrLong(): failed: name=" + name);
117 return -1L;
118 }
119
120 public float getAttrFloat(String name) {
121 Float ret = (Float) attrTable.get(name);
122 if (ret != null)
123 return ret.floatValue();
124 if (parentAttrTable != null)
125 return parentAttrTable.getAttrFloat(name);
126 msg.err("AttrTable.getAttrFloat(): failed: name=" + name);
127 return -1f;
128 }
129
130 public double getAttrDouble(String name) {
131 Double ret = (Double) attrTable.get(name);
132 if (ret != null)
133 return ret.doubleValue();
134 if (parentAttrTable != null)
135 return parentAttrTable.getAttrDouble(name);
136 msg.err("AttrTable.getAttrDouble(): failed: name=" + name);
137 return -1;
138 }
139
140 ////////////////////////////////////////////////////////////////////////
141
142 public boolean getAttrBool(String name, boolean def) {
143 Boolean ret = (Boolean) attrTable.get(name);
144 if (ret != null)
145 return ret.booleanValue();
146 if (parentAttrTable != null)
147 return parentAttrTable.getAttrBool(name, def);
148 return def;
149 }
150
151 public int getAttrInt(String name, int def) {
152 Integer ret = (Integer) attrTable.get(name);
153 if (ret != null)
154 return ret.intValue();
155 if (parentAttrTable != null)
156 return parentAttrTable.getAttrInt(name, def);
157 return def;
158 }
159
160 public long getAttrLong(String name, long def) {
161 Long ret = (Long) attrTable.get(name);
162 if (ret != null)
163 return ret.longValue();
164 if (parentAttrTable != null)
165 return parentAttrTable.getAttrLong(name, def);
166 return def;
167 }
168
169 public float getAttrFloat(String name, float def) {
170 Float ret = (Float) attrTable.get(name);
171 if (ret != null)
172 return ret.floatValue();
173 if (parentAttrTable != null)
174 return parentAttrTable.getAttrFloat(name, def);
175 return def;
176 }
177
178 public double getAttrDouble(String name, double def) {
179 Double ret = (Double) attrTable.get(name);
180 if (ret != null)
181 return ret.doubleValue();
182 if (parentAttrTable != null)
183 return parentAttrTable.getAttrDouble(name, def);
184 return def;
185 }
186
187 ////////////////////////////////////////////////////////////////////////
188
189 /**
190 * Setting attributes always affect the local table only.
191 * If attribute name is registered, attribute value must match the registered type.
192 * Unregistered attribute values can be any type.
193 */
194
195 public Object setAttr(String name, Object value) {
196 IAttrRegistry r = getAttrRegistry();
197 if (r != null) {
198 IAttrFactory f = r.get(name);
199 if (f != null && !f.isValid(value))
200 msg.err(
201 NAME
202 + ".setAttr(object): invalid value"
203 + ": attrname="
204 + name
205 + ": attrFactory="
206 + f);
207 }
208 return attrTable.put(name, value);
209 }
210
211 public Object setAttr(String name, boolean value) {
212 IAttrRegistry r = getAttrRegistry();
213 if (r != null) {
214 IAttrFactory f = r.get(name);
215 if (f!=null && !(f instanceof BooleanAttrFactory))
216 msg.err(
217 NAME
218 + ".setAttr(boolean): expected BooleanAttrFactory"
219 + ": attrname="
220 + name
221 + ": attrFactory="
222 + f);
223 }
224 return attrTable.put(name, new Boolean(value));
225 }
226
227 public Object setAttr(String name, int value) {
228 IAttrRegistry r = getAttrRegistry();
229 if (r != null) {
230 IAttrFactory f = r.get(name);
231 if (f!=null && !(f instanceof IntAttrFactory))
232 msg.err(
233 NAME
234 + ".setAttr(int): expected IntAttrFactory"
235 + ": attrname="
236 + name
237 + ": attrFactory="
238 + f);
239 }
240 return attrTable.put(name, new Integer(value));
241 }
242
243 public Object setAttr(String name, long value) {
244 IAttrRegistry r = getAttrRegistry();
245 if (r != null) {
246 IAttrFactory f = r.get(name);
247 if (f!=null && !(f instanceof LongAttrFactory))
248 msg.err(
249 NAME
250 + ".setAttr(long): expected LongAttrFactory"
251 + ": attrname="
252 + name
253 + ": attrFactory="
254 + f);
255 }
256 return attrTable.put(name, new Long(value));
257 }
258
259 public Object setAttr(String name, float value) {
260 IAttrRegistry r = getAttrRegistry();
261 if (r != null) {
262 IAttrFactory f = r.get(name);
263 if (f!=null && !(f instanceof FloatAttrFactory))
264 msg.err(
265 NAME
266 + ".setAttr(float): expected FloatAttrFactory"
267 + ": attrname="
268 + name
269 + ": attrFactory="
270 + f);
271 }
272 return attrTable.put(name, new Float(value));
273 }
274
275 public Object setAttr(String name, double value) {
276 IAttrRegistry r = getAttrRegistry();
277 if (r != null) {
278 IAttrFactory f = r.get(name);
279 if (f!=null && !(f instanceof DoubleAttrFactory))
280 msg.err(
281 NAME
282 + ".setAttr(Double): expected DoubleAttrFactory"
283 + ": attrname="
284 + name
285 + ": attrFactory="
286 + f);
287 }
288 return attrTable.put(name, new Double(value));
289 }
290
291 ////////////////////////////////////////////////////////////////////////
292
293 public boolean hasAttr(String name) {
294 return attrTable.containsKey(name);
295 }
296
297 public Set attrKeySet() {
298 return attrTable.keySet();
299 }
300
301 public Object removeAttr(String name) {
302 return attrTable.remove(name);
303 }
304
305 /**
306 * Remove all unregistered attributes. Remove everything if no attribute registry defined.
307 */
308 public void removeUnregisteredAttrs() {
309 IAttrRegistry r = getAttrRegistry();
310 if (r == null)
311 attrTable.clear();
312 else {
313 for (Iterator it = attrTable.keySet().iterator(); it.hasNext();) {
314 String attrname = (String) it.next();
315 if (r.get(attrname) == null)
316 it.remove();
317 }
318 }
319 }
320
321 public void clearAttrs() {
322 attrTable.clear();
323 }
324
325 ////////////////////////////////////////////////////////////////////////
326
327 /**
328 * Get and cache an object attribute from a string attribute, eg. -pos and pos.
329 */
330 public Object getAttrCached(String name) {
331 String cachedname = "-" + name;
332 Object attr = getAttr(cachedname);
333 if (attr == null) {
334 String str = getAttrString(name);
335 if (str != null)
336 attr = setAttrFromString(cachedname, str);
337 }
338 return attr;
339 }
340
341 /**
342 * Return a String representation of the specified attribute object.
343 */
344 public String getAttrAsString(String name) {
345 Object attr = attrTable.get(name);
346 if (attr != null) {
347 IAttrRegistry r = getAttrRegistry();
348 if (r != null) {
349 IAttrFactory f = r.get(name);
350 if (f != null)
351 return f.toString(attr);
352 } else
353 // If attribute have no defined type, assume it is a String.
354 return attr.toString();
355 }
356 if (parentAttrTable != null)
357 return parentAttrTable.getAttrAsString(name);
358 return null;
359 }
360
361 /**
362 * @return Object created from the string value or null if object not created.
363 */
364 public Object setAttrFromString(String name, String value) {
365 IAttrRegistry r = getAttrRegistry();
366 if (r != null) {
367 IAttrFactory f = r.get(name);
368 if (f != null) {
369 Object ret = f.createObject(value);
370 attrTable.put(name, ret);
371 return ret;
372 }
373 }
374 // If no attribute factory, assume attribute type is String.
375 attrTable.put(name, value);
376 return value;
377 }
378
379 // Helper for setting up registry //////////////////////////////////////
380
381 public void initAttr(String name, IAttrFactory factory) {
382 Object ret = getAttrRegistry().put(name, factory);
383 checkOverwritting("IAttrFactory,Object",name,ret,factory);
384 }
385
386 public void initAttr(String name, IAttrFactory factory, Object value) {
387 Object ret = getAttrRegistry().put(name, factory);
388 attrTable.put(name, value);
389 checkOverwritting("IAttrFactory,Object",name,ret,factory);
390 }
391
392 public void initAttr(String name, String value) {
393 IAttrFactory factory=StringAttrFactory.getInstance();
394 Object ret=getAttrRegistry().put(name, factory);
395 attrTable.put(name, value);
396 checkOverwritting("String",name,ret,factory);
397 }
398
399 public void initAttr(String name, boolean value) {
400 IAttrFactory factory=BooleanAttrFactory.getInstance();
401 Object ret=getAttrRegistry().put(name, factory);
402 attrTable.put(name, new Boolean(value));
403 checkOverwritting("boolean",name,ret,factory);
404 }
405
406 public void initAttr(String name, int value) {
407 IAttrFactory factory=IntAttrFactory.getInstance();
408 Object ret=getAttrRegistry().put(name, factory);
409 attrTable.put(name, new Integer(value));
410 checkOverwritting("int",name,ret,factory);
411 }
412
413 public void initAttr(String name, long value) {
414 IAttrFactory factory=LongAttrFactory.getInstance();
415 Object ret=getAttrRegistry().put(name, factory);
416 attrTable.put(name, new Long(value));
417 checkOverwritting("long",name,ret,factory);
418 }
419
420 public void initAttr(String name, float value) {
421 IAttrFactory factory=FloatAttrFactory.getInstance();
422 Object ret=getAttrRegistry().put(name, factory);
423 attrTable.put(name, new Float(value));
424 checkOverwritting("float",name,ret,factory);
425 }
426
427 public void initAttr(String name, double value) {
428 IAttrFactory factory=DoubleAttrFactory.getInstance();
429 Object ret=getAttrRegistry().put(name, factory);
430 attrTable.put(name, new Double(value));
431 checkOverwritting("double",name,ret,factory);
432 }
433
434 private void checkOverwritting(String methodname, String attrname, Object oldfactory, IAttrFactory newfactory) {
435 if (oldfactory != null)
436 msg.err(
437 NAME
438 + ".initAttr("+methodname+"): registry already initialized: attr name="
439 + attrname
440 + ", old factory="
441 + oldfactory
442 + ", new factor="
443 + newfactory);
444 }
445
446 ////////////////////////////////////////////////////////////////////////
447
448 }