package com.felix.util; import java.io.File; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.StringTokenizer; import java.util.Vector; /** * Class for key values, might be read from string, e.g. * "key1:value1, key2:value2, etc" * * * * @author felix * */ public class KeyValues { private KeyValue[] _keyValues; private HashMap<String, String> _hm; private Locale _locale = null; /** * a vector to store file lines of config file in order to keep also the * comment lines. **/ private Vector<String> _fileLines; private String _pathBase = "", _filePath = "", _keyValueSeparator = ""; /** * Constructor from a String, e.g. "key1:value1, key2:value2, etc". * * @param s * @param pairSeparator * Separates the pairs. * @param keyValueSeparator * Separates key from value. */ public KeyValues(String s, String pairSeparator, String keyValueSeparator) { try { _keyValueSeparator = keyValueSeparator; StringTokenizer st = new StringTokenizer(s, pairSeparator); Vector<String> tmp = new Vector<String>(); while (st.hasMoreTokens()) { String object = st.nextToken(); if (!FileUtil.isCommentOrEmpty(object)) { tmp.add(object); } } readKeyValues(tmp, false); tmp = null; } catch (Exception e) { e.printStackTrace(); } } /** * Return the path base. * * @return The path base. */ public String getPathBase() { return _pathBase; } public void setLocale(Locale locale) { _locale = locale; } /** * Set the path base. * * @param pathBase */ public void setPathBase(String pathBase) { _pathBase = pathBase; } /** * Constructor from a vector, containing key-value description strings. * * @param keyValueStrings * @param keyValueSeparator * Separates key from value. */ public KeyValues(Vector<String> keyValueStrings, String keyValueSeparator) { _keyValueSeparator = keyValueSeparator; readKeyValues(keyValueStrings, false); } /** * Constructor from an input stream, each line containing key-value * description strings. * * @param inputStream * @param keyValueSeparator * Separates key from value. */ public KeyValues(InputStream inputStream, String keyValueSeparator) { _keyValueSeparator = keyValueSeparator; try { Vector<String> filelines = FileUtil.getFileLines(inputStream); readKeyValues(filelines, false); } catch (Exception e) { e.printStackTrace(); } } /** * Constructor from an input stream, each line containing key-value * description strings. * * @param inputStream * The Input Stream * @param keyValueSeparator * The key-value separator * @param charEnc * The character encoding */ public KeyValues(InputStream inputStream, String keyValueSeparator, String charEnc) { _keyValueSeparator = keyValueSeparator; try { Vector<String> filelines = FileUtil.getFileLines(inputStream, charEnc); readKeyValues(filelines, false); } catch (Exception e) { e.printStackTrace(); } } /** * Constructor from a file name, each line containing key-value description * strings. * * @param filename * @param keyValueSeparator * Separates key from value. */ public KeyValues(String filename, String keyValueSeparator) { _keyValueSeparator = keyValueSeparator; try { _filePath = filename; _fileLines = FileUtil.getFileLines(filename); readKeyValues(_fileLines, false); } catch (Exception e) { System.err.println("ERROR on filename: " + filename); e.printStackTrace(); } } public KeyValues(String filename) { _keyValueSeparator = "="; try { _filePath = filename; _fileLines = FileUtil.getFileLines(filename); readKeyValues(_fileLines, false); } catch (Exception e) { System.err.println("ERROR on filename: " + filename); e.printStackTrace(); } } /** * Constructor from a file name, each line containing key-value description * * @param file * The file. * @param keyValueSeparator * The Keyvalue Separator. * @param charEnc * The Character Encoding, e.g. "UTF-8" */ public KeyValues(File file, String keyValueSeparator, String charEnc) { _keyValueSeparator = keyValueSeparator; try { _fileLines = FileUtil.getFileLines(file, charEnc); readKeyValues(_fileLines, false); } catch (Exception e) { System.err.println("ERROR on filename: " + file.getName()); e.printStackTrace(); } } /** * Return all keys as Strings in a vector. Crashes if no keyvalues are * initialized. * * @return The vector or empty. */ public Vector<String> getKeysAsVector() { Vector<String> retV = new Vector<String>(); for (KeyValue kv : _keyValues) { retV.add(kv.getKey()); } return retV; } /** * Add key-values from a file to existing ones. * * @param filename * @param keyValueSeparator * Separates key from value. * @return The new key values. */ public KeyValues addKeyValues(String filename, String keyValueSeparator) { _keyValueSeparator = keyValueSeparator; try { Vector<String> filelines = FileUtil.getFileLines(filename); readKeyValues(filelines, true); } catch (Exception e) { System.err.println("ERROR on filename: " + filename); e.printStackTrace(); } return this; } /** * Add key-values from a String to existing ones. * * @param s * @param pairSeparator * Separates the pairs. * @param keyValueSeparator * Separates key from value. * @return The new Key values. */ public KeyValues addKeyValues(String s, String pairSeparator, String keyValueSeparator) { _keyValueSeparator = keyValueSeparator; try { StringTokenizer st = new StringTokenizer(s, pairSeparator); Vector<String> tmp = new Vector<String>(); while (st.hasMoreTokens()) { String object = st.nextToken(); if (!FileUtil.isCommentOrEmpty(object)) { tmp.add(object); } } readKeyValues(tmp, true); tmp = null; } catch (Exception e) { e.printStackTrace(); } return this; } /** * Return array of KeyValues. * * @return The array of KeyValues. */ public KeyValue[] getKeyValues() { return _keyValues; } /** * Return keyValues as Vector. * * @return The vector. */ public Vector<KeyValue> getKeyValuesVector() { Vector<KeyValue> retVec = new Vector<KeyValue>(); for (KeyValue k : _keyValues) retVec.add(k); return retVec; } /** * Return a vector of values for a specific key; * * @param key * The key. * @return The value vector. */ public Vector<String> getValuesForKey(String key) { Vector<String> retVec = new Vector<String>(); for (KeyValue k : _keyValues) { if (k.getKey().compareTo(key) == 0) retVec.add(k.getValue()); } return retVec; } /** * Return values as blank-separated string or "null". * * @return The values or "null". */ public String getValuesAsString() { if (_keyValues == null) return "null"; String ret = ""; for (int i = 0; i < _keyValues.length; i++) { ret += _keyValues[i].getValue() + " "; } return ret.trim(); } /** * Return unique list (ignoring doublettes) of values as blank separated * string. * * @return The list. */ public String getUniqValuesAsString() { Vector<String> contained = new Vector<String>(); if (_keyValues == null) return "null"; String ret = ""; for (int i = 0; i < _keyValues.length; i++) { String val = _keyValues[i].getValue(); if (!StringUtil.isStringInVector(val, contained)) { ret += val + " "; } contained.add(val); } return ret.trim(); } /** * Return unique list (ignoring doublettes) of values as String array. * * @return The unique list. */ public String[] getUniqValuesAsArray() { String uv = getUniqValuesAsString(); StringTokenizer st = new StringTokenizer(uv); String[] ret = new String[st.countTokens()]; int i = 0; while (st.hasMoreTokens()) { ret[i++] = st.nextToken(); } return ret; } /** * Return String array of blank separated tokens. string. * * @return The String array. */ public String[] getValueAsStringArray(String key) { String val = this.getHashMap().get(key); StringTokenizer st = new StringTokenizer(val); String[] ret = new String[st.countTokens()]; int i = 0; while (st.hasMoreTokens()) { ret[i++] = st.nextToken(); } return ret; } /** * Return keys as blank separated String. * * @return The keys as blank separated String. */ public String getKeysAsString() { if (_keyValues == null) return "null"; String ret = ""; for (int i = 0; i < _keyValues.length; i++) { ret += _keyValues[i].getKey() + " "; } return ret.trim(); } /** * Return unique list (ignoring doublettes) of keys as blank separated * string. * * @return A unique list. */ public String getUniqKeysAsString() { Vector<String> contained = new Vector<String>(); if (_keyValues == null) return "null"; String ret = ""; for (int i = 0; i < _keyValues.length; i++) { String val = _keyValues[i].getKey(); if (!StringUtil.isStringInVector(val, contained)) { ret += val + " "; } contained.add(val); } return ret.trim(); } /** * Return KeyValue descriptions as newline separated list. */ public String toString() { if (_keyValues == null) return "null"; String ret = ""; for (int i = 0; i < _keyValues.length; i++) { ret += _keyValues[i].toString() + "\n"; } return ret; } /** * Store in file. */ public void fileStore() { try { Vector<String> storeVec = new Vector<String>(); for (int i = 0; i < _keyValues.length; i++) { storeVec.add(_keyValues[i].getKey() + _keyValueSeparator + _keyValues[i].getValue()); } FileUtil.writeFileContent(_filePath, storeVec, FileUtil.STD_ENCODING); } catch (Exception e) { e.printStackTrace(); } } /** * Store in file including original comments.. */ public void fileStoreWithComments() { try { Vector<String> storeVec = new Vector<String>(); for (int j = 0; j < _fileLines.size(); j++) { String line = _fileLines.elementAt(j); StringTokenizer st = new StringTokenizer(line, _keyValueSeparator); boolean found = false; try { String keyC = st.nextToken(); for (int i = 0; i < _keyValues.length; i++) { String key = _keyValues[i].getKey(); String value = _keyValues[i].getValue(); if (keyC.compareTo(key) == 0) { storeVec.add(key + _keyValueSeparator + value); found = true; break; } } } catch (Exception e) { // was no key value } if (!found) { storeVec.add(line); } } FileUtil.writeFileContent(_filePath, storeVec, FileUtil.STD_ENCODING); } catch (Exception e) { e.printStackTrace(); } } /** * Store in file including original comments.. */ public void fileStoreWithComments(String fileName) { try { Vector<String> storeVec = new Vector<String>(); for (int j = 0; j < _fileLines.size(); j++) { String line = _fileLines.elementAt(j); StringTokenizer st = new StringTokenizer(line, _keyValueSeparator); String keyC = st.nextToken(); boolean found = false; for (int i = 0; i < _keyValues.length; i++) { String key = _keyValues[i].getKey(); String value = _keyValues[i].getValue(); if (keyC.compareTo(key) == 0) { storeVec.add(key + _keyValueSeparator + value); found = true; break; } } if (!found) { storeVec.add(line); } } FileUtil.writeFileContent(fileName, storeVec, FileUtil.STD_ENCODING); } catch (Exception e) { e.printStackTrace(); } } /** * Store in file. */ public void fileStore(String fileName) { try { Vector<String> storeVec = new Vector<String>(); for (int i = 0; i < _keyValues.length; i++) { storeVec.add(_keyValues[i].getKey() + _keyValueSeparator + _keyValues[i].getValue()); } FileUtil.writeFileContent(fileName, storeVec, FileUtil.STD_ENCODING); } catch (Exception e) { e.printStackTrace(); } } /** * Retrieve the value for a specific key. * * @param key * @return The value for a specific key or null if not contained. */ public String getString(String key) { String val = this.getHashMap().get(key); if (val == null) { System.err.println("WARNING: no value for " + key); } return val; } /** * Get a string suffixed by the locale's langage. * * @param key * The key * @return The vale + language, e.g. "value_de" * @throws Exception * If locale is null. */ public String getStringLocalized(String key) throws Exception { return getString(key) + "_" + _locale.getLanguage(); } /** * Set a new value for a key. * * @param key * @param newValue */ public void setValue(String key, String newValue) { boolean found = false; for (int i = 0; i < _keyValues.length; i++) { if (_keyValues[i].getKey().compareTo(key) == 0) { _keyValues[i].setValue(newValue); found = true; break; } } if (!found) { System.err.println("WARNING: no key for " + key + ", adding it."); addKeyValue(new KeyValue(key, newValue)); } else { reloadHashmap(); } } /** * Test a String value. * * @param key * The key. * @param tval * The supposed value. * @return True if value for key is test value. */ public boolean isString(String key, String tval) { String val = this.getHashMap().get(key); if (val == null) { System.err.println("WARNING: no value for " + key); } if (val.trim().equalsIgnoreCase(tval.trim())) { return true; } return false; } /** * Retrieve the value for a specific key for Booleans. * * @param key * The key. * @return True if values parses as boolean true. */ public boolean getBool(String key) { String val = this.getHashMap().get(key); if (val == null) { System.err.println("WARNING: no value for " + key); } return Boolean.parseBoolean(val); } /** * Retrieve the value for a specific key for integers. * * @param key * The key. * @return The value as integer. */ public int getInt(String key) { String val = this.getHashMap().get(key); if (val == null) { System.err.println("WARNING: no value for " + key); } return Integer.parseInt(val); } /** * Retrieve the value for a specific key for a string array. E.g. point 13 * 2341 constructs new Dimension(13, 2341) * * @param key * The key. * @param sep * The separator string, e.g. " " or ",". * @return The value a String array. */ public String[] getStringArray(String key, String sep) { String val = this.getHashMap().get(key); if (val == null) { System.err.println("WARNING: no value for " + key); } return StringUtil.stringToArray(val.trim(), sep); } /** * Retrieve the value for a specific key for a string array. E.g. point 13 * 2341 constructs new Dimension(13, 2341). Separator is a blank. * * @param key * The key. * @return */ public String[] getStringArray(String key) { String val = this.getHashMap().get(key); if (val == null) { System.err.println("WARNING: no value for " + key); } return StringUtil.stringToArray(val.trim(), " "); } /** * Retrieve the value for a specific key for doubles. * * @param key * The key. * @return The value as double. */ public double getDouble(String key) { String val = this.getHashMap().get(key); if (val == null) { System.err.println("WARNING: no value for " + key); } return Double.parseDouble(val); } /** * Retrieve the value for a specific key as a file path. * * @param key * The key. * @return The value fronted by the pathBase. */ public String getPathValue(String key) { String val = this.getHashMap().get(key); if (val == null) { System.err.println("WARNING: no value for " + key); } if (Util.isEmpty(val)) { return ""; } if (Util.isEmpty(_pathBase)) return val; return _pathBase + File.separator + val; } /** * Get a path value suffixed by the locale's langage. * * @param key * The key * @return The vale + language, e.g. "value_de" * @throws Exception * If locale is null. */ public String getPathValueLocalized(String key) throws Exception { return getPathValue(key) + "_" + _locale.getLanguage(); } /** * Retrieve the value for a specific key as an absolute file path. * * @param key * The key. * @return The value taken as a file. */ public String getAbsPath(String key) { String val = this.getHashMap().get(key); if (val == null) { System.err.println("WARNING: no value for " + key); } return new File(val).getAbsolutePath(); } /** * Retrieve the value for a specific key as a file handler based on absolute * path. * * @param key * The key. * @return The value taken as a file. */ public File getFileHandler(String key) { String val = this.getHashMap().get(key); if (val == null) { System.err.println("WARNING: no value for " + key); } return new File(getPathValue(key)); } /** * Get number of KeyValues. * * @return The number of key values. */ public int getSize() { return _keyValues.length; } private void readKeyValues(Vector<String> keyValueStrings, boolean add) { try { // temporary vector to filter comments and empty lines Vector<String> tmp = new Vector<String>(); for (Iterator<String> iterator = keyValueStrings.iterator(); iterator .hasNext();) { String object = (String) iterator.next(); if (!FileUtil.isCommentOrEmpty(object)) { tmp.add(object); } } int i = 0; if (!add) { _keyValues = new KeyValue[tmp.size()]; } else { i = _keyValues.length; KeyValue[] tmp2 = new KeyValue[_keyValues.length + tmp.size()]; System.arraycopy(_keyValues, 0, tmp2, 0, _keyValues.length); _keyValues = new KeyValue[_keyValues.length + tmp.size()]; System.arraycopy(tmp2, 0, _keyValues, 0, tmp2.length); } for (Iterator<String> iterator = tmp.iterator(); iterator.hasNext();) { String object = (String) iterator.next(); String key = ""; int sepIndex = object.indexOf(_keyValueSeparator); if (sepIndex < 0) { System.err.println("ignoring line without separator:" + object); } else { key = object.substring(0, sepIndex); String value = object.substring(sepIndex + 1, object.length()); // if (value.length() == 0) { // System.err.println("WARNING: empty value at " + key); // } _keyValues[i++] = new KeyValue(key, value); } } tmp = null; } catch (Exception e) { e.printStackTrace(); } } /** * Add a new KeyValue to the set of keyvalues. * * @param addition * The new KeyValue. */ public void addKeyValue(KeyValue addition) { KeyValue[] newKeyValues = new KeyValue[_keyValues.length + 1]; int i = 0; for (KeyValue kv : _keyValues) { newKeyValues[i++] = kv; } newKeyValues[i] = addition; _keyValues = newKeyValues; reloadHashmap(); } /** * Copy all keyvalues from another object to this one. * * @param moreKeyValues * The new KeyValues. */ public void addKeyValues(KeyValues moreKeyValues) { KeyValue[] newKeyValues = new KeyValue[_keyValues.length + moreKeyValues.getSize()]; int i = 0; for (KeyValue kv : _keyValues) { newKeyValues[i++] = kv; } for (KeyValue kv : moreKeyValues.getKeyValues()) { newKeyValues[i++] = kv; } _keyValues = newKeyValues; reloadHashmap(); } /** * Remove a certain KeyValue from the set. * * @param key * The key to the KeyValue to be removed. */ public void removeKeyValue(String key) { int origSize = getSize(); KeyValue[] newKeyValues = new KeyValue[origSize - 1]; int i = 0; try { for (KeyValue kv : _keyValues) { if (kv.getKey().compareTo(key) != 0) newKeyValues[i++] = kv; } } catch (Exception e) { System.err.println("Warning: Crashed while removing keyValue for " + key + ", possibly key not contained."); return; } _keyValues = newKeyValues; reloadHashmap(); if (origSize - 1 > i) { System.err.println("Warning: removed more than one keyValue for " + key); } } /** * Return keys and values as hash map (internally an array). * * @return The keys and values as hash map. */ public HashMap<String, String> getHashMap() { if (_hm == null) { _hm = new HashMap<String, String>(); for (int i = 0; i < _keyValues.length; i++) { _hm.put(_keyValues[i].getKey(), _keyValues[i].getValue()); } } return _hm; } private void reloadHashmap() { _hm = new HashMap<String, String>(); for (int i = 0; i < _keyValues.length; i++) { _hm.put(_keyValues[i].getKey(), _keyValues[i].getValue()); } } /** * Main method used for testing. * * @param args */ public static void main(String[] args) { KeyValues kv = new KeyValues("t1,t2;t3,\nt4,,;t5, \"t6 \";t6,", ";", ","); System.out.println(kv.toString()); System.out.println("value of t1: >" + kv.getString("t1") + "<"); System.out.println("value of t2: >" + kv.getString("t2") + "<"); System.out.println("value of t3: >" + kv.getString("t3") + "<"); System.out.println("value of t4: >" + kv.getString("t4") + "<"); System.out.println("value of t5: >" + kv.getString("t5") + "<"); System.out.println("value of t6: >" + kv.getString("t6") + "<"); kv = kv.addKeyValues("t8.t9:t10.t11", ":", "."); System.out.println("\nkv extended:\n" + kv.toString()); } }