// This file is part of PleoCommand: // Interactively control Pleo with psychobiological parameters // // Copyright (C) 2010 Oliver Hoffmann - Hoffmann_Oliver@gmx.de // // 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., 51 Franklin Street, Boston, USA. package pleocmd.cfg; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import pleocmd.exc.ConfigurationException; import pleocmd.exc.InternalException; public abstract class ConfigMap<K extends Comparable<? super K>, V> extends ConfigValue { private final Map<K, List<V>> content; public ConfigMap(final String label) { super(label); content = new HashMap<K, List<V>>(); } public final Set<K> getAllKeys() { return Collections.unmodifiableSet(content.keySet()); } public final List<K> getAllKeysSorted() { final List<K> list = new ArrayList<K>(content.size()); for (final K k : content.keySet()) list.add(k); Collections.sort(list); return list; } @Override public final Map<K, List<V>> getContent() { return Collections.unmodifiableMap(content); } public final List<V> getContent(final K key) { final List<V> list = content.get(key); return Collections.unmodifiableList(list == null ? new ArrayList<V>(0) : list); } public final boolean hasContent(final K key) { return content.containsKey(key); } public final void setContent(final K key, final List<V> list) throws ConfigurationException { checkValidString(convertKey(key), false); for (final V v : list) checkValidString(convertValue(v), false); content.put(key, list); contentChanged(); } public final void renameContent(final K key, final K newKey) throws ConfigurationException { checkValidString(convertKey(newKey), false); final List<V> list = content.remove(key); if (list == null) { contentChanged(); throw new IllegalArgumentException(String.format( "Key '%s' was not in the map", key)); } content.put(newKey, list); contentChanged(); } public final void addContent(final K key, final V value) throws ConfigurationException { List<V> list = content.get(key); if (list == null) { checkValidString(convertKey(key), false); list = new ArrayList<V>(); content.put(key, list); } checkValidString(convertValue(value), false); list.add(value); contentChanged(); } public final void createContent(final K key) throws ConfigurationException { if (!content.containsKey(key)) { checkValidString(convertKey(key), false); content.put(key, new ArrayList<V>()); contentChanged(); } } public final void removeContent(final K key) { content.remove(key); contentChanged(); } public final void clearContent(final K key) { final List<V> list = content.get(key); if (list != null) list.clear(); contentChanged(); } public final void clearContent() { content.clear(); contentChanged(); } public final <F extends K, W extends V> void assignFrom( final ConfigMap<F, W> map) { clearContent(); try { for (final F key : map.getAllKeys()) { createContent(key); for (final W v : map.getContent(key)) addContent(key, v); } } catch (final ConfigurationException e) { throw new InternalException(e); } } @Override public final String asString() { final StringBuilder sb = new StringBuilder(""); for (final K key : getAllKeysSorted()) { sb.append(convertKey(key)); sb.append(" => "); final List<V> vals = getContent(key); if (vals.isEmpty()) sb.append("<empty>"); else if (vals.size() <= 1) sb.append(convertValue(vals.get(0))); else { sb.append("{"); for (final V val : vals) { sb.append(convertValue(val)); sb.append(", "); } sb.deleteCharAt(sb.length() - 1); sb.deleteCharAt(sb.length() - 1); sb.append("}"); } sb.append("\n"); } if (!content.isEmpty()) sb.deleteCharAt(sb.length() - 1); return sb.toString(); } @Override public final void setFromString(final String string) { throw new UnsupportedOperationException(); } @Override final List<String> asStrings() { final List<String> res = new ArrayList<String>(); for (final Entry<K, List<V>> entry : content.entrySet()) { res.add(convertKey(entry.getKey()) + " =>"); for (final V s : entry.getValue()) res.add("\t" + convertValue(s)); } return res; } @Override final void setFromStrings(final List<String> strings) throws ConfigurationException { clearContent(); List<V> list = null; for (final String str : strings) if (str.endsWith("=>")) { list = new ArrayList<V>(); setContent( createKey(str.substring(0, str.length() - 2).trim()), list); } else { if (list == null) throw new ConfigurationException("Found list entries " + "before the first key"); list.add(createValue(str)); } } protected abstract K createKey(String keyAsString) throws ConfigurationException; protected abstract V createValue(String valueAsString) throws ConfigurationException; protected abstract String convertKey(K key); protected abstract String convertValue(V value); protected abstract void contentChanged(); @Override public final String getIdentifier() { return null; } @Override final boolean isSingleLined() { return false; } }