samer@0
|
1 /*
|
samer@0
|
2 * X.java
|
samer@0
|
3 *
|
samer@0
|
4 * Copyright (c) 2001, Samer Abdallah, King's College London.
|
samer@0
|
5 * All rights reserved.
|
samer@0
|
6 *
|
samer@0
|
7 * This software is provided AS IS and WITHOUT ANY WARRANTY;
|
samer@0
|
8 * without even the implied warranty of MERCHANTABILITY or
|
samer@0
|
9 * FITNESS FOR A PARTICULAR PURPOSE.
|
samer@0
|
10 */
|
samer@0
|
11
|
samer@0
|
12 package samer.core;
|
samer@0
|
13 import java.io.StringWriter;
|
samer@0
|
14 import java.util.StringTokenizer;
|
samer@0
|
15 import java.awt.Font;
|
samer@0
|
16 import java.awt.Rectangle;
|
samer@0
|
17 import java.awt.Color;
|
samer@0
|
18 import java.awt.SystemColor;
|
samer@0
|
19
|
samer@0
|
20 import samer.core.Environment.Datum;
|
samer@0
|
21 import samer.core.Environment.Codec;
|
samer@0
|
22 import samer.core.Environment.Autocoder;
|
samer@0
|
23
|
samer@0
|
24 /**
|
samer@0
|
25 Static methods for converting objects and extracting correctly typed
|
samer@0
|
26 values from Environments. Short name
|
samer@0
|
27 because of expected frequent use! Also, contains
|
samer@0
|
28 several Codec classes.
|
samer@0
|
29 @see samer.core.Environment
|
samer@0
|
30 @see samer.core.Environment.Datum
|
samer@0
|
31 @see samer.core.Environment.Autocoder
|
samer@0
|
32 */
|
samer@0
|
33
|
samer@0
|
34 public class X
|
samer@0
|
35 {
|
samer@0
|
36 /** Tries to extract an Object from the given Datum, throws Exception in failure */
|
samer@0
|
37 public static Object object(Datum b) throws Exception {
|
samer@0
|
38 Object ret=b.get(ObjectCodec,null);
|
samer@0
|
39 if (ret==null) throw new Exception("no data");
|
samer@0
|
40 return ret;
|
samer@0
|
41 }
|
samer@0
|
42
|
samer@0
|
43 /** Tries to extract a String given Datum */
|
samer@0
|
44 public static String string(Datum b) throws Exception {
|
samer@0
|
45 String ret=(String)b.get(StringCodec,null);
|
samer@0
|
46 if (ret==null) throw new Exception("datum has no value");
|
samer@0
|
47 return ret;
|
samer@0
|
48 }
|
samer@0
|
49
|
samer@0
|
50 /** Tries to extract a Font given Datum. If this fails, tries
|
samer@0
|
51 to decode def using FontCodec. def can be a Font or a String. */
|
samer@0
|
52 public static Font font(Datum b, Object def) {
|
samer@0
|
53 return (Font)b.get(FontCodec,def);
|
samer@0
|
54 }
|
samer@0
|
55
|
samer@0
|
56 /** Tries to extract a Rectangle from given Datum. If this fails, tries
|
samer@0
|
57 to decode def as a rectangle. */
|
samer@0
|
58 public static Rectangle rect(Datum b, Rectangle def) {
|
samer@0
|
59 return (Rectangle)b.get(RectangleCodec,def);
|
samer@0
|
60 }
|
samer@0
|
61
|
samer@0
|
62 /** Get String from Datum, returning def if this fails */
|
samer@0
|
63 public static String string(Datum b,String def) {
|
samer@0
|
64 return (String)b.get(StringCodec,def);
|
samer@0
|
65 }
|
samer@0
|
66
|
samer@0
|
67 /** Get Color from Datum, decoding def if this fails. def can
|
samer@0
|
68 be a Color or a String. See ColorCodec. */
|
samer@0
|
69 public static Color color(Datum b, Object def) {
|
samer@0
|
70 return (Color)b.get(ColorCodec,def);
|
samer@0
|
71 }
|
samer@0
|
72
|
samer@0
|
73 /** Extract int from Datum */
|
samer@0
|
74 public static int _int(Datum b,int def) {
|
samer@0
|
75 return ((Integer)b.get(IntegerCodec,new Integer(def))).intValue();
|
samer@0
|
76 }
|
samer@0
|
77 /** Extract double from Datum */
|
samer@0
|
78 public static double _double(Datum b,double def) {
|
samer@0
|
79 return ((Double)b.get(DoubleCodec,new Double(def))).doubleValue();
|
samer@0
|
80 }
|
samer@0
|
81 /** Extract boolean from Datum */
|
samer@0
|
82 public static boolean _bool(Datum b,boolean def) {
|
samer@0
|
83 return ((Boolean)b.get(BooleanCodec,new Boolean(def))).booleanValue();
|
samer@0
|
84 }
|
samer@0
|
85
|
samer@0
|
86 /** store given object to current environment */
|
samer@0
|
87 public static void store(String name, Object value) {
|
samer@0
|
88 Shell.env().store(name,value,codec(value));
|
samer@0
|
89 }
|
samer@0
|
90
|
samer@0
|
91 /** Extracts an integer array from a string. Valid strings are, eg
|
samer@0
|
92 "(1,2,3)", "(4 5 6)", "7 8 9", "10, 11, 12" */
|
samer@0
|
93 public static int[] parseIntArray(String s, int n)
|
samer@0
|
94 {
|
samer@0
|
95 StringTokenizer token = new StringTokenizer(s,"(), ");
|
samer@0
|
96 int[] a=new int[n];
|
samer@0
|
97
|
samer@0
|
98 for (int i=0; i<n; i++) {
|
samer@0
|
99 a[i]=Integer.parseInt(token.nextToken());
|
samer@0
|
100 }
|
samer@0
|
101 return a;
|
samer@0
|
102 }
|
samer@0
|
103
|
samer@0
|
104 /** @see samer.core.X.parseIntArray */
|
samer@0
|
105 public static double[] doubleArray(String s, int n)
|
samer@0
|
106 {
|
samer@0
|
107 StringTokenizer token = new StringTokenizer(s,"(), ");
|
samer@0
|
108 double[] a=new double[n];
|
samer@0
|
109
|
samer@0
|
110 for (int i=0; i<n; i++) {
|
samer@0
|
111 a[i]=parseDouble(token.nextToken());
|
samer@0
|
112 }
|
samer@0
|
113 return a;
|
samer@0
|
114 }
|
samer@0
|
115
|
samer@0
|
116 /** Sets each integer in the int array to the numeric value of the corresponding
|
samer@0
|
117 Objects in the Object array (they have to be subclasses of Numbe).
|
samer@0
|
118 */
|
samer@0
|
119 public static void setIntArray(int[] a, Object[] b) {
|
samer@0
|
120 for (int i=0; i<a.length; i++)
|
samer@0
|
121 a[i]=((Number)b[i]).intValue();
|
samer@0
|
122 }
|
samer@0
|
123
|
samer@0
|
124 /** Base class for objects that can convert some type to and from String or
|
samer@0
|
125 Object. @see samer.core.Environment.Codec */
|
samer@0
|
126 public static class BaseCodec implements Codec
|
samer@0
|
127 {
|
samer@0
|
128 public Class targetClass() { return Object.class; }
|
samer@0
|
129
|
samer@0
|
130 /** convert to string using object's toString() method (a reasonable default) */
|
samer@0
|
131 public String string(Object o) { return o.toString(); }
|
samer@0
|
132
|
samer@0
|
133 /** Convert to object by returning original object. This might be OK for
|
samer@0
|
134 * immutable objects, but should be overriden for mutable ones, perhaps
|
samer@0
|
135 * returning a clone of the original or an object of a different class altogether.
|
samer@0
|
136 */
|
samer@0
|
137 public Object object(Object o) { return o; }
|
samer@0
|
138
|
samer@0
|
139 /** Decode given object to by return it the given object itself. */
|
samer@0
|
140 public Object decode(Object o) { return o; }
|
samer@0
|
141 };
|
samer@0
|
142
|
samer@0
|
143 public static Codec ObjectCodec = new BaseCodec();
|
samer@0
|
144
|
samer@0
|
145 /** Can decode numbers in Integer, Number, or String form */
|
samer@0
|
146 public static Codec IntegerCodec = new BaseCodec()
|
samer@0
|
147 {
|
samer@0
|
148 public Class targetClass() { return Integer.class; }
|
samer@0
|
149
|
samer@0
|
150 /** If given object is any subclass of java.lang.Number, then its
|
samer@0
|
151 numerical value is returned as an Integer. If it is a string,
|
samer@0
|
152 the string is parsed to extract an integer value. Any other
|
samer@0
|
153 class will probably cause this function to barf.
|
samer@0
|
154 */
|
samer@0
|
155
|
samer@0
|
156 public Object decode(Object o) {
|
samer@0
|
157 // if (o==null) return null;
|
samer@0
|
158 if (o instanceof Integer) return o;
|
samer@0
|
159 if (o instanceof String) return Integer.decode(o.toString());
|
samer@0
|
160 return new Integer(((Number)o).intValue());
|
samer@0
|
161 }
|
samer@0
|
162 };
|
samer@0
|
163
|
samer@0
|
164 private static DoubleFormat fmt=new DoubleFormat(3);
|
samer@0
|
165
|
samer@0
|
166 /** Convert double to string using the (private) current DoubleFormat object */
|
samer@0
|
167 public static String string(double v) { return fmt._format(v); }
|
samer@0
|
168
|
samer@0
|
169 /** Convert string to double */
|
samer@0
|
170 public static double parseDouble(String s) {
|
samer@0
|
171 return Double.valueOf(s).doubleValue();
|
samer@0
|
172 }
|
samer@0
|
173
|
samer@0
|
174 /** Can decode numbers in Double, Number, or String form */
|
samer@0
|
175 public static Codec DoubleCodec = new BaseCodec()
|
samer@0
|
176 {
|
samer@0
|
177 public Class targetClass() { return Double.class; }
|
samer@0
|
178
|
samer@0
|
179 public String string(Object o) { return fmt._format(((Number)o).doubleValue()); }
|
samer@0
|
180
|
samer@0
|
181 /** Can decode String or any subclass of Number */
|
samer@0
|
182 public Object decode(Object o) {
|
samer@0
|
183 // if (o==null) return null;
|
samer@0
|
184 if (o instanceof Double) return o;
|
samer@0
|
185 if (o instanceof String) return Double.valueOf(o.toString());
|
samer@0
|
186 return new Double(((Number)o).doubleValue());
|
samer@0
|
187 }
|
samer@0
|
188
|
samer@0
|
189 };
|
samer@0
|
190
|
samer@0
|
191 /** Can decode Boolean or String ("true" or "false") form */
|
samer@0
|
192 public static Codec BooleanCodec = new BaseCodec()
|
samer@0
|
193 {
|
samer@0
|
194 public Class targetClass() { return Boolean.class; }
|
samer@0
|
195 public Object decode(Object o) {
|
samer@0
|
196 // if (o==null) return null;
|
samer@0
|
197 if (o instanceof Boolean) return o;
|
samer@0
|
198 return Boolean.valueOf(o.toString());
|
samer@0
|
199 }
|
samer@0
|
200 };
|
samer@0
|
201
|
samer@0
|
202 public static Codec StringCodec = new BaseCodec()
|
samer@0
|
203 {
|
samer@0
|
204 public Class targetClass() { return String.class; }
|
samer@0
|
205 public Object decode(Object o) {
|
samer@0
|
206 // if (o==null) return null;
|
samer@0
|
207 if (o instanceof String) return o;
|
samer@0
|
208 else return o.toString();
|
samer@0
|
209 }
|
samer@0
|
210 };
|
samer@0
|
211
|
samer@0
|
212
|
samer@0
|
213 /** Can decode Color or String form
|
samer@0
|
214 String can be "#rrggbb" where rrggbb are hex,
|
samer@0
|
215 or "(r,g,b)" or "(r g b)" where r, g, b are integers,
|
samer@0
|
216 or "$bg", which evaluates to SystemColor.control, the
|
samer@0
|
217 default background color for components,
|
samer@0
|
218 or "$fg", which evaluates to SystemColor.controlText,
|
samer@0
|
219 the default foreground color.
|
samer@0
|
220 */
|
samer@0
|
221
|
samer@0
|
222 public static Codec ColorCodec = new Codec()
|
samer@0
|
223 {
|
samer@0
|
224 public Class targetClass() { return Color.class; }
|
samer@0
|
225 public Object object(Object o) { return o; }
|
samer@0
|
226 public String string(Object o) {
|
samer@0
|
227 StringBuffer buf=new StringBuffer("#");
|
samer@0
|
228 buf.append(Integer.toHexString(((Color)o).getRGB() & 0xffffff));
|
samer@0
|
229 return buf.toString();
|
samer@0
|
230 }
|
samer@0
|
231 public Object decode(Object o) {
|
samer@0
|
232 // if (o==null) return null;
|
samer@0
|
233 if (o instanceof Color) return o;
|
samer@0
|
234
|
samer@0
|
235 String s=o.toString();
|
samer@0
|
236 if (s.startsWith("(")) {
|
samer@0
|
237 int[] a=parseIntArray(s,3);
|
samer@0
|
238 return new Color(a[0],a[1],a[2]);
|
samer@0
|
239 }
|
samer@0
|
240 if (s.equals("$bg")) return SystemColor.control;
|
samer@0
|
241 if (s.equals("$fg")) return SystemColor.controlText;
|
samer@0
|
242 return Color.decode(s);
|
samer@0
|
243 }
|
samer@0
|
244 };
|
samer@0
|
245
|
samer@0
|
246 /** Can decode Font or String, using Font.decode(),
|
samer@0
|
247 eg "Helvetica-PLAIN-12" */
|
samer@0
|
248 public static Codec FontCodec = new Codec()
|
samer@0
|
249 {
|
samer@0
|
250 public Class targetClass() { return Font.class; }
|
samer@0
|
251 public Object object(Object o) { return o; }
|
samer@0
|
252 public String string(Object o) { return o.toString(); }
|
samer@0
|
253 public Object decode(Object o) {
|
samer@0
|
254 // if (o==null) return null;
|
samer@0
|
255 if (o instanceof Font) return o;
|
samer@0
|
256 return Font.decode(o.toString());
|
samer@0
|
257 }
|
samer@0
|
258 };
|
samer@0
|
259
|
samer@0
|
260 public static Codec RectangleCodec = new Codec()
|
samer@0
|
261 {
|
samer@0
|
262 public Class targetClass() { return Font.class; }
|
samer@0
|
263 public Object object(Object o) { return o; }
|
samer@0
|
264 public String string(Object o) {
|
samer@0
|
265 Rectangle r=(Rectangle)o;
|
samer@0
|
266 StringBuffer buf=new StringBuffer();
|
samer@0
|
267
|
samer@0
|
268 buf.append('(');
|
samer@0
|
269 buf.append(String.valueOf(r.x)); buf.append(',');
|
samer@0
|
270 buf.append(String.valueOf(r.y)); buf.append(',');
|
samer@0
|
271 buf.append(String.valueOf(r.width)); buf.append(',');
|
samer@0
|
272 buf.append(String.valueOf(r.height));
|
samer@0
|
273 buf.append(')');
|
samer@0
|
274 return buf.toString();
|
samer@0
|
275 }
|
samer@0
|
276
|
samer@0
|
277 public Object decode(Object o) {
|
samer@0
|
278 // if (o==null) return null;
|
samer@0
|
279 if (o instanceof Rectangle) return o;
|
samer@0
|
280
|
samer@0
|
281 int[] a=parseIntArray(o.toString(),4);
|
samer@0
|
282 return new Rectangle(a[0],a[1],a[2],a[3]);
|
samer@0
|
283 }
|
samer@0
|
284 };
|
samer@0
|
285
|
samer@0
|
286 public static Codec codec(Object o) { return codec(o.getClass()); }
|
samer@0
|
287 public static Codec codec(Class c)
|
samer@0
|
288 {
|
samer@0
|
289 for (int i=classes.length-1; i>0; i--) {
|
samer@0
|
290 if (classes[i].isAssignableFrom(c)) return codecs[i];
|
samer@0
|
291 }
|
samer@0
|
292 return codecs[0];
|
samer@0
|
293 }
|
samer@0
|
294
|
samer@0
|
295 private static Class[] classes = {
|
samer@0
|
296 Object.class,
|
samer@0
|
297 Font.class,
|
samer@0
|
298 Rectangle.class,
|
samer@0
|
299 Color.class,
|
samer@0
|
300 String.class,
|
samer@0
|
301 Boolean.class,
|
samer@0
|
302 Integer.class,
|
samer@0
|
303 Double.class
|
samer@0
|
304 };
|
samer@0
|
305
|
samer@0
|
306 private static Codec[] codecs = {
|
samer@0
|
307 ObjectCodec,
|
samer@0
|
308 FontCodec,
|
samer@0
|
309 RectangleCodec,
|
samer@0
|
310 ColorCodec,
|
samer@0
|
311 StringCodec,
|
samer@0
|
312 BooleanCodec,
|
samer@0
|
313 IntegerCodec,
|
samer@0
|
314 DoubleCodec
|
samer@0
|
315 };
|
samer@0
|
316 }
|
samer@0
|
317
|