Mercurial > hg > jslab
diff src/samer/core_/X.java @ 0:bf79fb79ee13
Initial Mercurial check in.
author | samer |
---|---|
date | Tue, 17 Jan 2012 17:50:20 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/samer/core_/X.java Tue Jan 17 17:50:20 2012 +0000 @@ -0,0 +1,317 @@ +/* + * X.java + * + * Copyright (c) 2001, Samer Abdallah, King's College London. + * All rights reserved. + * + * This software is provided AS IS and WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +package samer.core; +import java.io.StringWriter; +import java.util.StringTokenizer; +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.Color; +import java.awt.SystemColor; + +import samer.core.Environment.Datum; +import samer.core.Environment.Codec; +import samer.core.Environment.Autocoder; + +/** + Static methods for converting objects and extracting correctly typed + values from Environments. Short name + because of expected frequent use! Also, contains + several Codec classes. + @see samer.core.Environment + @see samer.core.Environment.Datum + @see samer.core.Environment.Autocoder + */ + +public class X +{ + /** Tries to extract an Object from the given Datum, throws Exception in failure */ + public static Object object(Datum b) throws Exception { + Object ret=b.get(ObjectCodec,null); + if (ret==null) throw new Exception("no data"); + return ret; + } + + /** Tries to extract a String given Datum */ + public static String string(Datum b) throws Exception { + String ret=(String)b.get(StringCodec,null); + if (ret==null) throw new Exception("datum has no value"); + return ret; + } + + /** Tries to extract a Font given Datum. If this fails, tries + to decode def using FontCodec. def can be a Font or a String. */ + public static Font font(Datum b, Object def) { + return (Font)b.get(FontCodec,def); + } + + /** Tries to extract a Rectangle from given Datum. If this fails, tries + to decode def as a rectangle. */ + public static Rectangle rect(Datum b, Rectangle def) { + return (Rectangle)b.get(RectangleCodec,def); + } + + /** Get String from Datum, returning def if this fails */ + public static String string(Datum b,String def) { + return (String)b.get(StringCodec,def); + } + + /** Get Color from Datum, decoding def if this fails. def can + be a Color or a String. See ColorCodec. */ + public static Color color(Datum b, Object def) { + return (Color)b.get(ColorCodec,def); + } + + /** Extract int from Datum */ + public static int _int(Datum b,int def) { + return ((Integer)b.get(IntegerCodec,new Integer(def))).intValue(); + } + /** Extract double from Datum */ + public static double _double(Datum b,double def) { + return ((Double)b.get(DoubleCodec,new Double(def))).doubleValue(); + } + /** Extract boolean from Datum */ + public static boolean _bool(Datum b,boolean def) { + return ((Boolean)b.get(BooleanCodec,new Boolean(def))).booleanValue(); + } + + /** store given object to current environment */ + public static void store(String name, Object value) { + Shell.env().store(name,value,codec(value)); + } + + /** Extracts an integer array from a string. Valid strings are, eg + "(1,2,3)", "(4 5 6)", "7 8 9", "10, 11, 12" */ + public static int[] parseIntArray(String s, int n) + { + StringTokenizer token = new StringTokenizer(s,"(), "); + int[] a=new int[n]; + + for (int i=0; i<n; i++) { + a[i]=Integer.parseInt(token.nextToken()); + } + return a; + } + + /** @see samer.core.X.parseIntArray */ + public static double[] doubleArray(String s, int n) + { + StringTokenizer token = new StringTokenizer(s,"(), "); + double[] a=new double[n]; + + for (int i=0; i<n; i++) { + a[i]=parseDouble(token.nextToken()); + } + return a; + } + + /** Sets each integer in the int array to the numeric value of the corresponding + Objects in the Object array (they have to be subclasses of Numbe). + */ + public static void setIntArray(int[] a, Object[] b) { + for (int i=0; i<a.length; i++) + a[i]=((Number)b[i]).intValue(); + } + + /** Base class for objects that can convert some type to and from String or + Object. @see samer.core.Environment.Codec */ + public static class BaseCodec implements Codec + { + public Class targetClass() { return Object.class; } + + /** convert to string using object's toString() method (a reasonable default) */ + public String string(Object o) { return o.toString(); } + + /** Convert to object by returning original object. This might be OK for + * immutable objects, but should be overriden for mutable ones, perhaps + * returning a clone of the original or an object of a different class altogether. + */ + public Object object(Object o) { return o; } + + /** Decode given object to by return it the given object itself. */ + public Object decode(Object o) { return o; } + }; + + public static Codec ObjectCodec = new BaseCodec(); + + /** Can decode numbers in Integer, Number, or String form */ + public static Codec IntegerCodec = new BaseCodec() + { + public Class targetClass() { return Integer.class; } + + /** If given object is any subclass of java.lang.Number, then its + numerical value is returned as an Integer. If it is a string, + the string is parsed to extract an integer value. Any other + class will probably cause this function to barf. + */ + + public Object decode(Object o) { +// if (o==null) return null; + if (o instanceof Integer) return o; + if (o instanceof String) return Integer.decode(o.toString()); + return new Integer(((Number)o).intValue()); + } + }; + + private static DoubleFormat fmt=new DoubleFormat(3); + + /** Convert double to string using the (private) current DoubleFormat object */ + public static String string(double v) { return fmt._format(v); } + + /** Convert string to double */ + public static double parseDouble(String s) { + return Double.valueOf(s).doubleValue(); + } + + /** Can decode numbers in Double, Number, or String form */ + public static Codec DoubleCodec = new BaseCodec() + { + public Class targetClass() { return Double.class; } + + public String string(Object o) { return fmt._format(((Number)o).doubleValue()); } + + /** Can decode String or any subclass of Number */ + public Object decode(Object o) { +// if (o==null) return null; + if (o instanceof Double) return o; + if (o instanceof String) return Double.valueOf(o.toString()); + return new Double(((Number)o).doubleValue()); + } + + }; + + /** Can decode Boolean or String ("true" or "false") form */ + public static Codec BooleanCodec = new BaseCodec() + { + public Class targetClass() { return Boolean.class; } + public Object decode(Object o) { +// if (o==null) return null; + if (o instanceof Boolean) return o; + return Boolean.valueOf(o.toString()); + } + }; + + public static Codec StringCodec = new BaseCodec() + { + public Class targetClass() { return String.class; } + public Object decode(Object o) { +// if (o==null) return null; + if (o instanceof String) return o; + else return o.toString(); + } + }; + + + /** Can decode Color or String form + String can be "#rrggbb" where rrggbb are hex, + or "(r,g,b)" or "(r g b)" where r, g, b are integers, + or "$bg", which evaluates to SystemColor.control, the + default background color for components, + or "$fg", which evaluates to SystemColor.controlText, + the default foreground color. + */ + + public static Codec ColorCodec = new Codec() + { + public Class targetClass() { return Color.class; } + public Object object(Object o) { return o; } + public String string(Object o) { + StringBuffer buf=new StringBuffer("#"); + buf.append(Integer.toHexString(((Color)o).getRGB() & 0xffffff)); + return buf.toString(); + } + public Object decode(Object o) { +// if (o==null) return null; + if (o instanceof Color) return o; + + String s=o.toString(); + if (s.startsWith("(")) { + int[] a=parseIntArray(s,3); + return new Color(a[0],a[1],a[2]); + } + if (s.equals("$bg")) return SystemColor.control; + if (s.equals("$fg")) return SystemColor.controlText; + return Color.decode(s); + } + }; + + /** Can decode Font or String, using Font.decode(), + eg "Helvetica-PLAIN-12" */ + public static Codec FontCodec = new Codec() + { + public Class targetClass() { return Font.class; } + public Object object(Object o) { return o; } + public String string(Object o) { return o.toString(); } + public Object decode(Object o) { +// if (o==null) return null; + if (o instanceof Font) return o; + return Font.decode(o.toString()); + } + }; + + public static Codec RectangleCodec = new Codec() + { + public Class targetClass() { return Font.class; } + public Object object(Object o) { return o; } + public String string(Object o) { + Rectangle r=(Rectangle)o; + StringBuffer buf=new StringBuffer(); + + buf.append('('); + buf.append(String.valueOf(r.x)); buf.append(','); + buf.append(String.valueOf(r.y)); buf.append(','); + buf.append(String.valueOf(r.width)); buf.append(','); + buf.append(String.valueOf(r.height)); + buf.append(')'); + return buf.toString(); + } + + public Object decode(Object o) { +// if (o==null) return null; + if (o instanceof Rectangle) return o; + + int[] a=parseIntArray(o.toString(),4); + return new Rectangle(a[0],a[1],a[2],a[3]); + } + }; + + public static Codec codec(Object o) { return codec(o.getClass()); } + public static Codec codec(Class c) + { + for (int i=classes.length-1; i>0; i--) { + if (classes[i].isAssignableFrom(c)) return codecs[i]; + } + return codecs[0]; + } + + private static Class[] classes = { + Object.class, + Font.class, + Rectangle.class, + Color.class, + String.class, + Boolean.class, + Integer.class, + Double.class + }; + + private static Codec[] codecs = { + ObjectCodec, + FontCodec, + RectangleCodec, + ColorCodec, + StringCodec, + BooleanCodec, + IntegerCodec, + DoubleCodec + }; +} +