Java tutorial
/* PreferencesMap - A Map<String, String> with some useful features to handle preferences. Part of the Arduino project - http://www.arduino.cc/ Copyright (c) 2014 Cristian Maglie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package processing.app.helpers; import org.apache.commons.compress.utils.IOUtils; import processing.app.legacy.PApplet; import java.io.*; import java.util.LinkedHashMap; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; @SuppressWarnings("serial") public class PreferencesMap extends LinkedHashMap<String, String> { public PreferencesMap(Map<String, String> table) { super(table); } /** * Create a PreferencesMap and load the content of the file passed as * argument. * * Is equivalent to: * * <pre> * PreferencesMap map = new PreferencesMap(); * map.load(file); * </pre> * * @param file * @throws IOException */ public PreferencesMap(File file) throws IOException { super(); load(file); } public PreferencesMap() { super(); } /** * Parse a property list file and put kev/value pairs into the Map * * @param file * @throws FileNotFoundException * @throws IOException */ public void load(File file) throws IOException { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(file); load(fileInputStream); } finally { IOUtils.closeQuietly(fileInputStream); } } protected String processPlatformSuffix(String key, String suffix, boolean isCurrentPlatform) { if (key == null) return null; // Key does not end with the given suffix? Process as normal if (!key.endsWith(suffix)) return key; // Not the current platform? Ignore this key if (!isCurrentPlatform) return null; // Strip the suffix from the key return key.substring(0, key.length() - suffix.length()); } /** * Parse a property list stream and put key/value pairs into the Map * * @param input * @throws IOException */ public void load(InputStream input) throws IOException { String[] lines = PApplet.loadStrings(input); for (String line : lines) { if (line.length() == 0 || line.charAt(0) == '#') continue; int equals = line.indexOf('='); if (equals != -1) { String key = line.substring(0, equals).trim(); String value = line.substring(equals + 1).trim(); key = processPlatformSuffix(key, ".linux", OSUtils.isLinux()); key = processPlatformSuffix(key, ".windows", OSUtils.isWindows()); key = processPlatformSuffix(key, ".macosx", OSUtils.isMacOS()); if (key != null) put(key, value); } } } /** * Create a new PreferenceMap that contains all the top level pairs of the * current mapping. E.g. the folowing mapping:<br /> * * <pre> * Map ( * alpha = Alpha * alpha.some.keys = v1 * alpha.other.keys = v2 * beta = Beta * beta.some.keys = v3 * ) * </pre> * * will generate the following result: * * <pre> * Map ( * alpha = Alpha * beta = Beta * ) * </pre> * * @return */ public PreferencesMap topLevelMap() { PreferencesMap res = new PreferencesMap(); for (String key : keySet()) { if (key.contains(".")) continue; res.put(key, get(key)); } return res; } /** * Create a new Map<String, PreferenceMap> where keys are the first level of * the current mapping. Top level pairs are discarded. E.g. the folowing * mapping:<br /> * * <pre> * Map ( * alpha = Alpha * alpha.some.keys = v1 * alpha.other.keys = v2 * beta = Beta * beta.some.keys = v3 * ) * </pre> * * will generate the following result: * * <pre> * alpha = Map( * some.keys = v1 * other.keys = v2 * ) * beta = Map( * some.keys = v3 * ) * </pre> * * @return */ public Map<String, PreferencesMap> firstLevelMap() { Map<String, PreferencesMap> res = new LinkedHashMap<>(); for (String key : keySet()) { int dot = key.indexOf('.'); if (dot == -1) continue; String parent = key.substring(0, dot); String child = key.substring(dot + 1); if (!res.containsKey(parent)) res.put(parent, new PreferencesMap()); res.get(parent).put(child, get(key)); } return res; } /** * Create a new PreferenceMap using a subtree of the current mapping. Top * level pairs are ignored. E.g. with the following mapping:<br /> * * <pre> * Map ( * alpha = Alpha * alpha.some.keys = v1 * alpha.other.keys = v2 * beta = Beta * beta.some.keys = v3 * ) * </pre> * * a call to createSubTree("alpha") will generate the following result: * * <pre> * Map( * some.keys = v1 * other.keys = v2 * ) * </pre> * * @param parent * @return */ public PreferencesMap subTree(String parent) { return subTree(parent, -1); } public PreferencesMap subTree(String parent, int sublevels) { PreferencesMap res = new PreferencesMap(); parent += "."; int parentLen = parent.length(); for (String key : keySet()) { if (key.startsWith(parent)) { String newKey = key.substring(parentLen); int keySubLevels = newKey.split("\\.").length; if (sublevels == -1 || keySubLevels == sublevels) { res.put(newKey, get(key)); } } } return res; } public String toString(String indent) { String res = indent + "{\n"; SortedSet<String> treeSet = new TreeSet<>(keySet()); for (String k : treeSet) res += indent + " " + k + " = " + get(k) + "\n"; res += indent + "}\n"; return res; } /** * Returns the value to which the specified key is mapped, or throws a * PreferencesMapException if not found * * @param k * the key whose associated value is to be returned * @return the value to which the specified key is mapped * @throws PreferencesMapException */ public String getOrExcept(String k) throws PreferencesMapException { String r = get(k); if (r == null) throw new PreferencesMapException(k); return r; } @Override public String toString() { return toString(""); } /** * Creates a new File instance by converting the value of the key into an * abstract pathname. If the the given key doesn't exists or his value is the * empty string, the result is <b>null</b>. * * @param key * @return */ public File getFile(String key) { if (!containsKey(key)) return null; String path = get(key).trim(); if (path.length() == 0) return null; return new File(path); } /** * Creates a new File instance by converting the value of the key into an * abstract pathname with the specified sub folder. If the the given key * doesn't exists or his value is the empty string, the result is <b>null</b>. * * @param key * @param subFolder * @return */ public File getFile(String key, String subFolder) { File file = getFile(key); if (file == null) return null; return new File(file, subFolder); } /** * Return the value of the specified key as boolean. * * @param key * @return <b>true</b> if the value of the key is the string "true" (case * insensitive compared), <b>false</b> in any other case */ public boolean getBoolean(String key) { return Boolean.valueOf(get(key)); } /** * Sets the value of the specified key to the string <b>"true"</b> or * <b>"false"</b> based on value of the boolean parameter * * @param key * @param value * @return <b>true</b> if the previous value of the key was the string "true" * (case insensitive compared), <b>false</b> in any other case */ public boolean putBoolean(String key, boolean value) { String prev = put(key, value ? "true" : "false"); return new Boolean(prev); } public String get(String key, String defaultValue) { String value = get(key); if (value != null) { return value; } return defaultValue; } }