package AngioTool; import Utils.Misc; import Utils.ByteVectorOutputStream; import Utils.RefVector; import Pixels.Rgb; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; import java.util.Date; import java.lang.reflect.Field; public class ATPreferences { public static void savePreferences(Object params, String fileName) { StringBuilder sb = new StringBuilder(); sb.append("# " + AngioTool.VERSION + " Preferences\n"); sb.append("# " + new Date() + "\n\n"); Field[] fields = params.getClass().getDeclaredFields(); try { for (Field f : fields) { if (!Misc.shouldPersistField(f)) continue; String name = f.getName(); String type = f.getType().getSimpleName(); sb.append('.'); sb.append(name); sb.append('.'); sb.append(type); sb.append('='); sb.append(getStringOfArrayOrObject(f.get(params))); sb.append('\n'); } } catch (IllegalAccessException ex) { Misc.showExceptionInDialogBox(ex); return; } try { File path = new File(getPrefsDir(), fileName); FileOutputStream out = new FileOutputStream(path); out.write(sb.toString().getBytes()); out.close(); } catch (IOException ex) { Misc.showExceptionInDialogBox(ex); } } public static RefVector loadPreferences(Object params, Class contextClass, String fileName) throws IOException { File atFolder = getPrefsDir(); String text = ""; try (InputStream in = new FileInputStream(new File(atFolder, fileName))) { ByteVectorOutputStream vec = Misc.readFullyAsVector(in); text = vec.toString(); } HashMap map = new HashMap<>(); Field[] fields = params.getClass().getDeclaredFields(); for (Field f : fields) map.put(f.getName(), f); RefVector errors = new RefVector<>(String.class); String[] lines = text.split("\n"); for (String l : lines) { if (l.length() < 2 || l.charAt(0) == '#') continue; int nameStartIdx = l.charAt(0) == '.' ? 1 : 0; int typeStartIdx = l.indexOf('.', nameStartIdx) + 1; int valueStartIdx = l.indexOf('=') + 1; if (nameStartIdx < 0 || typeStartIdx <= 0 || valueStartIdx <= 0) continue; String name = l.substring(1, typeStartIdx - 1); String type = l.substring(typeStartIdx, valueStartIdx - 1); String valueStr = l.substring(valueStartIdx); Field f = map.get(name); if (f != null) { Object value; try { if (type.endsWith("[]")) value = parseArray(valueStr, type); else if (type.equals("Rgb")) value = new Rgb(valueStr); else if (type.equals("boolean") || type.equals("bool")) value = parseBool(valueStr); else if (type.equals("int")) value = Integer.parseInt(valueStr); else if (type.equals("double")) value = Double.parseDouble(valueStr); else value = valueStr; } catch (Exception ex) { String message = ex.getMessage(); message = message != null ? message : ex.getClass().getSimpleName(); errors.add(message); continue; } try { f.set(params, value); } catch (IllegalAccessException ex) { String message = ex.getMessage(); message = message != null ? message : ex.getClass().getSimpleName(); errors.add(message); continue; } } } return errors; } public static String getStringOfArrayOrObject(Object obj) { ByteVectorOutputStream bv = new ByteVectorOutputStream(); writeArrayToString(bv, obj); return bv.toString(); } public static void writeArrayToString(ByteVectorOutputStream bv, Object obj) { if (obj instanceof String) { bv.add((String)obj); } else if (obj instanceof Object[]) { Object[] objs = (Object[])obj; bv.add('['); for (int i = 0; i < objs.length; i++) writeArrayToString(bv, objs[i]); bv.add(']'); } else if (obj instanceof boolean[]) { boolean[] bools = (boolean[])obj; bv.add('['); for (int i = 0; i < bools.length; i++) { if (i > 0) bv.add(", "); bv.add(bools[i] ? 'T' : 'F'); } bv.add(']'); } else if (obj instanceof byte[]) bv.add(Arrays.toString((byte[])obj)); else if (obj instanceof char[]) bv.add(Arrays.toString((char[])obj)); else if (obj instanceof short[]) bv.add(Arrays.toString((short[])obj)); else if (obj instanceof int[]) bv.add(Arrays.toString((int[])obj)); else if (obj instanceof long[]) bv.add(Arrays.toString((long[])obj)); else if (obj instanceof float[]) bv.add(Arrays.toString((float[])obj)); else if (obj instanceof double[]) bv.add(Arrays.toString((double[])obj)); else bv.add(obj != null ? obj.toString() : "null"); } public static Object parseArray(String value, String type) throws Exception { Object array; if (type.equals("double[]")) { array = Misc.getSomeDoubles(value); } else if (type.equals("int[]")) { array = Misc.getSomeInts(value); } else { throw new Exception("ATPreferences.parseArray() only works with \"double[]\" and \"int[]\", not \"" + type + "\""); } return array; } public static Boolean parseBool(String value) { char c = value.charAt(0); c = c >= 'A' && c <= 'Z' ? (char)(c + 0x20) : c; return c == 't' || c == 'y'; } public static File getPrefsDir() throws IOException { File atFolder = new File(System.getProperty("user.home"), "AngioTool2"); if (!atFolder.exists()) atFolder.mkdir(); return atFolder; } }