1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.cosylab.application.state.impl;
21
22 import com.cosylab.application.state.*;
23
24 import com.cosylab.util.StringUtilities;
25
26 import java.awt.Color;
27 import java.awt.Dimension;
28 import java.awt.Font;
29 import java.awt.Rectangle;
30
31 import java.io.IOException;
32 import java.io.Serializable;
33 import java.io.Writer;
34
35 import java.util.Iterator;
36 import java.util.LinkedHashMap;
37 import java.util.Set;
38
39
40
41
42
43
44
45
46
47
48
49
50 public class DefaultState implements State, Serializable
51 {
52 private static final String keyID = "ID";
53 private static boolean typed = false;
54 private static final String typeMark = ".type";
55 protected LinkedHashMap map = new LinkedHashMap();
56
57
58
59
60
61
62
63
64
65 public static void setTyped(boolean typed)
66 {
67 DefaultState.typed = typed;
68 }
69
70
71
72
73 public DefaultState()
74 {
75 super();
76 }
77
78 private void checkKeyName(String name) {
79 if (name==null) {
80 throw new IllegalArgumentException("Key name can not be 'null'.");
81 }
82 int i= name.indexOf(' ');
83 if (i>=0) {
84 throw new IllegalArgumentException("Key name '"+name+"' can not contain whitespace character(s).");
85 }
86 i= name.indexOf('*');
87 if (i>=0) {
88 throw new IllegalArgumentException("Key name '"+name+"' can not contain '*' character(s).");
89 }
90 }
91
92
93
94
95 public void putState(String key, State state)
96 {
97 if (state != null) {
98 checkKeyName(key);
99 map.put(key, state);
100 }
101 }
102
103
104
105
106 public State createState(String key)
107 {
108 checkKeyName(key);
109 State s = new DefaultState();
110 map.put(key, s);
111
112 return s;
113 }
114
115
116
117
118 public boolean getBoolean(String key, boolean defaultValue)
119 {
120 String val = getString(key, null);
121
122 if (val == null) {
123 return defaultValue;
124 }
125
126 return Boolean.valueOf(val).booleanValue();
127 }
128
129
130
131
132 public State getState(String key)
133 {
134 Object obj = map.get(key);
135
136 if (obj == null) {
137 return null;
138 }
139
140 if (!(obj instanceof State)) {
141 return null;
142 }
143
144 return (State)obj;
145 }
146
147
148
149
150 public Class getClass(String key)
151 {
152 String value = getString(key, null);
153
154 if (value == null) {
155 return null;
156 }
157
158 try {
159 return Class.forName(value);
160 } catch (ClassNotFoundException e) {
161 return null;
162 }
163 }
164
165
166
167
168 public Color getColor(String key)
169 {
170 String value = getString(key, null);
171
172 if (value == null) {
173 return null;
174 }
175
176 try {
177 int rgb = (int)Long.parseLong(value, 16);
178 return new Color(rgb, true);
179 } catch (NumberFormatException e) {
180 return null;
181 }
182 }
183
184
185
186
187 public Dimension getDimension(String key)
188 {
189
190 Object obj = map.get(key + ".width");
191
192 if (obj == null) {
193 return null;
194 }
195
196 Dimension dim = new Dimension();
197 dim.width = getInt(key + ".width", 0);
198 dim.height = getInt(key + ".height", 0);
199
200 return dim;
201 }
202
203
204
205
206 public double getDouble(String key, double defaultValue)
207 {
208 Object obj = map.get(key);
209
210 if (obj == null) {
211 return defaultValue;
212 }
213
214 if (obj instanceof Number) {
215 return ((Number)obj).doubleValue();
216 }
217
218 return Double.parseDouble(obj.toString());
219 }
220
221
222
223
224 public double[] getDoubleSeq(String key)
225 {
226 int length = getInt(key + ".length", -1);
227
228 if (length == -1) {
229 return null;
230 }
231
232 double[] retVal = new double[length];
233
234 for (int i = 0; i < retVal.length; i++) {
235 retVal[i] = getDouble(key + '_' + i + '_', Double.NaN);
236 }
237
238 return retVal;
239 }
240
241 public Color[] getColorSeq(String key)
242 {
243 int length = getInt(key + ".length", -1);
244
245 if (length < 0) {
246 return null;
247 }
248
249 Color[] retVal = new Color[length];
250
251 for (int i = 0; i < retVal.length; i++) {
252 retVal[i] = getColor(key + '_' + i + '_');
253 }
254
255 return retVal;
256 }
257
258
259
260
261 public Font getFont(String key)
262 {
263 String value = getString(key, null);
264
265 if (value == null) {
266 return null;
267 }
268
269 Font f;
270
271 try {
272 f = Font.decode(value);
273 } catch (NumberFormatException e) {
274 return null;
275 }
276
277 return f;
278 }
279
280 public Font[] getFontSeq(String key)
281 {
282 int length = getInt(key + ".length", -1);
283
284 if (length < 0) {
285 return null;
286 }
287
288 Font[] retVal = new Font[length];
289
290 for (int i = 0; i < retVal.length; i++) {
291 retVal[i] = getFont(key + '_' + i + '_');
292 }
293
294 return retVal;
295 }
296
297
298
299
300 public String getID()
301 {
302 return getString(keyID, null);
303 }
304
305
306
307
308 public int getInt(String key, int defaultValue)
309 {
310 Object obj = map.get(key);
311
312 if (obj == null) {
313 return defaultValue;
314 }
315
316 if (obj instanceof Number) {
317 return ((Number)obj).intValue();
318 }
319
320 return Integer.parseInt(obj.toString());
321 }
322
323
324
325
326 public int[] getIntSeq(String key)
327 {
328 int length = getInt(key + ".length", -1);
329
330 if (length == -1) {
331 return null;
332 }
333
334 int[] retVal = new int[length];
335
336 for (int i = 0; i < retVal.length; i++) {
337 retVal[i] = getInt(key + '_' + i + '_', Integer.MAX_VALUE);
338 }
339
340 return retVal;
341 }
342
343
344
345
346 public Object getObject(String key)
347 {
348 return map.get(key);
349 }
350
351
352
353
354 public Class getType(String key)
355 {
356 String className = getString(key + typeMark, null);
357
358 if (className == null) {
359 return null;
360 }
361
362 try {
363 return StringUtilities.classFromString(className);
364 } catch (Exception e) {
365
366 }
367
368 return null;
369 }
370
371
372
373
374 public Rectangle getRectangle(String key)
375 {
376
377 Object obj = map.get(key + ".x");
378
379 if (obj == null) {
380 return null;
381 }
382
383 Rectangle r = new Rectangle();
384 r.x = getInt(key + ".x", 0);
385 r.y = getInt(key + ".y", 0);
386 r.width = getInt(key + ".width", 0);
387 r.height = getInt(key + ".height", 0);
388
389 return r;
390 }
391
392
393
394
395 public String getString(String key, String defaultValue)
396 {
397 Object obj = map.get(key);
398
399 if (obj == null) {
400 return defaultValue;
401 }
402
403 return obj.toString();
404 }
405
406
407
408
409 public String[] getStringSeq(String key)
410 {
411 int length = getInt(key + ".length", -1);
412
413 if (length == -1) {
414 return null;
415 }
416
417 String[] retVal = new String[length];
418
419 for (int i = 0; i < retVal.length; i++) {
420 retVal[i] = getString(key + '_' + i + '_', null);
421 }
422
423 return retVal;
424 }
425
426
427
428
429 public Set keySet()
430 {
431 return map.keySet();
432 }
433
434
435
436
437 public void putBoolean(String key, boolean value)
438 {
439 putString(key, Boolean.toString(value));
440
441 if (DefaultState.typed) {
442 map.put(key + typeMark, Boolean.TYPE);
443 }
444 }
445
446
447
448
449 public void putClass(String key, Class value)
450 {
451 if (value == null) {
452 return;
453 }
454
455 putString(key, value.getName());
456
457 if (DefaultState.typed) {
458 map.put(key + typeMark, value.getClass().getName());
459 }
460 }
461
462
463
464
465 public void putColor(String key, Color value)
466 {
467 if (value == null) {
468 return;
469 }
470
471 putString(key, Integer.toHexString(value.getRGB()));
472
473 if (DefaultState.typed) {
474 map.put(key + typeMark, value.getClass().getName());
475 }
476 }
477
478
479
480
481 public void putDimension(String key, Dimension value)
482 {
483 if (value == null) {
484 return;
485 }
486
487 putInt(key + ".width", value.width);
488 putInt(key + ".height", value.height);
489
490 if (DefaultState.typed) {
491 map.put(key + typeMark, value.getClass().getName());
492 }
493 }
494
495
496
497
498 public void putDouble(String key, double value)
499 {
500 checkKeyName(key);
501 map.put(key, new Double(value));
502
503 if (DefaultState.typed) {
504 map.put(key + typeMark, Double.TYPE.getName());
505 }
506 }
507
508
509
510
511 public void putDoubleSeq(String key, double[] value)
512 {
513 if (value == null) {
514 return;
515 }
516
517 putInt(key + ".length", value.length);
518
519 for (int i = 0; i < value.length; i++) {
520 putDouble(key + '_' + i + '_', value[i]);
521 }
522
523 if (DefaultState.typed) {
524 map.put(key + typeMark, value.getClass().getName());
525 }
526 }
527
528
529
530
531 public void putColorSeq(String key, Color[] value)
532 {
533 if (value == null) {
534 return;
535 }
536
537 putInt(key + ".length", value.length);
538
539 for (int i = 0; i < value.length; i++) {
540 putColor(key + '_' + i + '_', value[i]);
541 }
542
543 if (DefaultState.typed) {
544 map.put(key + typeMark, value.getClass().getName());
545 }
546 }
547
548
549
550
551 public void putFont(String key, Font value)
552 {
553 if (value == null) {
554 return;
555 }
556
557 String strStyle;
558
559 if (value.isBold()) {
560 strStyle = value.isItalic() ? "bolditalic" : "bold";
561 } else {
562 strStyle = value.isItalic() ? "italic" : "plain";
563 }
564
565 putString(key, value.getName() + "-" + strStyle + "-" + value.getSize());
566
567 if (DefaultState.typed) {
568 map.put(key + typeMark, value.getClass().getName());
569 }
570 }
571
572 public void putFontSeq(String key, Font[] value)
573 {
574 if (value == null) {
575 return;
576 }
577
578 putInt(key + ".length", value.length);
579
580 for (int i = 0; i < value.length; i++) {
581 putFont(key + '_' + i + '_', value[i]);
582 }
583
584 if (DefaultState.typed) {
585 map.put(key + typeMark, value.getClass().getName());
586 }
587 }
588
589
590
591
592 public void putInt(String key, int value)
593 {
594 checkKeyName(key);
595 map.put(key, new Integer(value));
596
597 if (DefaultState.typed) {
598 map.put(key + typeMark, Integer.TYPE.getName());
599 }
600 }
601
602
603
604
605 public void putIntSeq(String key, int[] value)
606 {
607 if (value == null) {
608 return;
609 }
610
611 putInt(key + ".length", value.length);
612
613 for (int i = 0; i < value.length; i++) {
614 putInt(key + '_' + i + '_', value[i]);
615 }
616
617 if (DefaultState.typed) {
618 map.put(key + typeMark, value.getClass().getName());
619 }
620 }
621
622
623
624
625 public void putRectangle(String key, Rectangle value)
626 {
627 if (value == null) {
628 return;
629 }
630
631 putInt(key + ".x", value.x);
632 putInt(key + ".y", value.y);
633 putInt(key + ".width", value.width);
634 putInt(key + ".height", value.height);
635
636 if (DefaultState.typed) {
637 map.put(key + typeMark, value.getClass().getName());
638 }
639 }
640
641
642
643
644 public void putString(String key, String value)
645 {
646 if (value == null) {
647 return;
648 }
649
650 checkKeyName(key);
651 map.put(key, value);
652
653 if (DefaultState.typed) {
654 map.put(key + typeMark, value.getClass().getName());
655 }
656 }
657
658
659
660
661 public void putStringSeq(String key, String[] value)
662 {
663 if (value == null) {
664 return;
665 }
666
667 putInt(key + ".length", value.length);
668
669 for (int i = 0; i < value.length; i++) {
670 putString(key + '_' + i + '_', value[i]);
671 }
672
673 if (DefaultState.typed) {
674 map.put(key + typeMark, value.getClass().getName());
675 }
676 }
677
678
679
680
681 public void setID(String ID)
682 {
683 putString(keyID, ID);
684 }
685
686 private String processValueString(String inString) {
687 if (inString==null) return "null";
688 int len=inString.length();
689 StringBuffer retBuf=new StringBuffer();
690 for (int i = 0; i < len; i++) {
691 char c=inString.charAt(i);
692 if (c>127 || c=='&' || c=='"' || c=='<' || c=='>') {
693 retBuf.append("&#"+((int)c)+";");
694 } else {
695 retBuf.append(c);
696 }
697 }
698 return retBuf.toString();
699 }
700
701 private void writeState(Writer writer, String name, State state, String linePrefix)
702 throws IOException
703 {
704 boolean hasChilds = false;
705 writer.write(linePrefix+"<" + name);
706
707 Iterator iter = state.keySet().iterator();
708
709 while (iter.hasNext()) {
710 String key = (String)iter.next();
711 Object value = state.getObject(key);
712
713 if (value instanceof State) {
714 hasChilds = true;
715
716 continue;
717 }
718
719 String aa = processValueString(value.toString());
720 writer.write(" " + key + "=\"" + aa + "\" ");
721 }
722
723 if (hasChilds) {
724 writer.write(">\n");
725 } else {
726 writer.write("/>\n");
727 }
728
729 iter = state.keySet().iterator();
730
731 while (iter.hasNext()) {
732 String key = (String)iter.next();
733 Object value = state.getObject(key);
734
735 if (value instanceof State) {
736 writeState(writer, key, (State)value, linePrefix+" ");
737
738 continue;
739 }
740 }
741
742 if (hasChilds) {
743 writer.write(linePrefix+"</" + name + ">\n");
744 }
745 }
746
747
748
749
750 public void writeXML(Writer writer) throws IOException
751 {
752 writer.write("<?xml version=\"1.0\" standalone=\"yes\"?>\n<states>\n");
753 writeState(writer, "state", this, "");
754 writer.write("</states>\n");
755 writer.close();
756 }
757
758
759
760
761 public String toString()
762 {
763 StringBuffer sb = new StringBuffer();
764 Iterator iter = map.keySet().iterator();
765 sb.append("ID=" + getID());
766 sb.append('\n');
767
768 while (iter.hasNext()) {
769 Object key = iter.next();
770 Object value = map.get(key);
771 sb.append(key.toString());
772 sb.append('=');
773 sb.append(value.toString());
774 sb.append('\n');
775 }
776
777 sb.append('\n');
778
779 return new String(sb);
780 }
781 }
782
783