diff options
author | Marc Dumais | 2015-03-13 10:39:35 +0000 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org | 2015-04-09 13:39:25 +0000 |
commit | e329e6a51802744656f7777347be74d79d7426bd (patch) | |
tree | 3af066396f99223ab544cd9c2cdcf26d2b84eebf /dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf | |
parent | 3855933de121b8f1f9f0a54a2371a910bae1cfd4 (diff) | |
download | org.eclipse.cdt-e329e6a51802744656f7777347be74d79d7426bd.tar.gz org.eclipse.cdt-e329e6a51802744656f7777347be74d79d7426bd.tar.xz org.eclipse.cdt-e329e6a51802744656f7777347be74d79d7426bd.zip |
Bug 462353 - [visualizer] Add support for persistent List<T> and
Map<String,T> parameters in PersistentSettingsManager
Change-Id: I64d44e112c3c9e2d24e7fcc62a3a6be7d865d6ac
Diffstat (limited to 'dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf')
2 files changed, 369 insertions, 59 deletions
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/utils/MementoUtils.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/utils/MementoUtils.java index 806665a6519..c30b054e14f 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/utils/MementoUtils.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/utils/MementoUtils.java @@ -37,20 +37,19 @@ import org.xml.sax.helpers.DefaultHandler; /** encodes and decodes memento to and from different data types; list, map, String*/ public class MementoUtils { - protected static final String ROOT_ELEMENT_TAGNAME = "root_element"; //$NON-NLS-1$ protected static final String ELEMENT_TAGNAME = "elem"; //$NON-NLS-1$ - protected static final String ATTRIBUTE_NAME = "value"; //$NON-NLS-1$ - + protected static final String ATTRIBUTE_KEY = "key"; //$NON-NLS-1$ + protected static final String ATTRIBUTE_VALUE = "value"; //$NON-NLS-1$ + /** Returns a XML memento, that encodes a single String parameter */ public static String encodeStringIntoMemento(String str) { - List<String> list = new ArrayList<String>(); + List<String> list = new ArrayList<>(); list.add(str); return encodeListIntoMemento(list); } - - + /** Returns a single String parameter, decoded from a XML memento */ public static String decodeStringFromMemento(String memento) { return decodeListFromMemento(memento).get(0); @@ -71,7 +70,9 @@ public class MementoUtils { // create one XML element per map entry for (String key : keyPairValues.keySet()) { Element elem = doc.createElement(ELEMENT_TAGNAME); - elem.setAttribute(key, keyPairValues.get(key)); + // store key and value as values of 2 attributes + elem.setAttribute(ATTRIBUTE_KEY, key); + elem.setAttribute(ATTRIBUTE_VALUE, keyPairValues.get(key)); rootElement.appendChild(elem); } @@ -96,7 +97,7 @@ public class MementoUtils { /** Returns a Map of Strings, decoded from a XML memento */ public static Map<String, String> decodeMapFromMemento(String memento) { - Map<String, String> keyPairValues = new HashMap<String, String>(); + Map<String, String> keyPairValues = new HashMap<>(); Element root = null; DocumentBuilder parser; @@ -110,20 +111,26 @@ public class MementoUtils { if (node.getNodeType() == Node.ELEMENT_NODE) { Element elem = (Element) node; NamedNodeMap nodeMap = elem.getAttributes(); + String key = null; + String value = null; for(int idx = 0; idx < nodeMap.getLength(); idx++) { Node attrNode = nodeMap.item(idx); if (attrNode.getNodeType() == Node.ATTRIBUTE_NODE) { Attr attr = (Attr) attrNode; - String key = attr.getName(); - String value = attr.getValue(); - if (key != null && value != null) { - keyPairValues.put(key, value); + if (attr.getName().equals(ATTRIBUTE_KEY)) { + key = attr.getValue(); } - else { - throw new Exception(); + else if (attr.getName().equals(ATTRIBUTE_VALUE)) { + value = attr.getValue(); } } } + if (key != null && value != null) { + keyPairValues.put(key, value); + } + else { + throw new Exception(); + } } } } catch (Exception e) { @@ -148,7 +155,7 @@ public class MementoUtils { // create one XML element per list entry to save for (String lbl : labels) { Element elem = doc.createElement(ELEMENT_TAGNAME); - elem.setAttribute(ATTRIBUTE_NAME, lbl); + elem.setAttribute(ATTRIBUTE_VALUE, lbl); rootElement.appendChild(elem); } @@ -172,7 +179,7 @@ public class MementoUtils { /** Returns a List of Strings, decoded from a XML memento */ public static List<String> decodeListFromMemento(String memento) { - List<String> list = new ArrayList<String>(); + List<String> list = new ArrayList<>(); Element root = null; DocumentBuilder parser; @@ -185,7 +192,7 @@ public class MementoUtils { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element elem = (Element) node; - String value = elem.getAttribute(ATTRIBUTE_NAME); + String value = elem.getAttribute(ATTRIBUTE_VALUE); if (value != null) { list.add(value); } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/utils/PersistentSettingsManager.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/utils/PersistentSettingsManager.java index f7a9364ed7f..168f884e1d8 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/utils/PersistentSettingsManager.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/utils/PersistentSettingsManager.java @@ -7,30 +7,100 @@ * * Contributors: * Marc Dumais (Ericsson) - initial API and implementation (bug 460837) + * Marc Dumais (Ericsson) - Bug 462353 *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.utils; + import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.MulticoreVisualizerUIPlugin; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.osgi.service.prefs.BackingStoreException; -/** This class manages one or more PersistentSetting objects, using a commmon - * name-space and optionally an instance id so that multiple instances can - * each have their own version of the parameter persisted */ + +/** + * This class manages one or more PersistentParameter, PersistentListParameter, + * PersistentMapParameter objects, using a common name-space and optionally an + * instance id so that multiple instances can each have their own version of + * the parameter persisted + */ public class PersistentSettingsManager { - // TODO: add a way to notify clients that the value of a global (shared) parameter - // has been updated, and that they should re-read it. - /** Class for a specific persistent parameter */ - public class PersistentParameter<T> { - private String m_storeKey; + /** Base class for a persistent parameter */ + private abstract class AbstractPersistentParameter<T> { + protected final Class<T> myClazz; + protected final boolean m_perInstance; + protected final String m_storeKey; + + /** Constructor */ + public AbstractPersistentParameter(Class<T> clazz, boolean perInstance, String storeKey) { + myClazz = clazz; + m_perInstance = perInstance; + m_storeKey = storeKey; + } + + // accessors + + /** Returns whether this parameter is persisted independently for each client instance */ + public boolean isPerInstance() { + return m_perInstance; + } + + /** Returns the class of the parameter */ + public Class<T> getClazz() { + return myClazz; + } + + protected String getStoreKey() { + return m_storeKey; + } + + // misc + + @SuppressWarnings("unchecked") + /** Converts a value from a String to its expected generic type. This is a base + * implementation that converts some base types - Use/Override as needed for more complex + * types, such as List or Map of these types */ + protected T convertToT(String val) { + // TODO: Add other types? Float, etc + if (String.class.isAssignableFrom(getClazz())) { + return (T) val; + } + else if (Integer.class.isAssignableFrom(getClazz())) { + return (T) Integer.valueOf(val); + } + else if (Boolean.class.isAssignableFrom(getClazz())) { + return (T) Boolean.valueOf(val); + } + return null; + } + + /** Returns whether the wanted Class type is supported, to use as a persistent parameter */ + protected boolean isTypeSupported(Class<T> clazz) { + // TODO: Add other types? Float, etc + if (String.class.isAssignableFrom(clazz) || + Integer.class.isAssignableFrom(clazz) || + Boolean.class.isAssignableFrom(clazz)) + { + return true; + } + return false; + } + + // TODO: add a way to notify clients that the value of a global (shared) parameter + // has been updated, and that they should re-read it. + } + + /** Class for a persistent parameter */ + public class PersistentParameter<T> extends AbstractPersistentParameter<T> { private T m_value; private T m_defaultValue; - private Class<T> myClazz; - private boolean m_perInstance; /** * Constructor @@ -40,9 +110,7 @@ public class PersistentSettingsManager { * @param storeKey : The key used to store the parameter in the store */ public PersistentParameter(Class<T> clazz, boolean perInstance, String storeKey) { - myClazz = clazz; - m_perInstance = perInstance; - m_storeKey = storeKey; + super(clazz, perInstance, storeKey); } /** Sets the default value to use if no persistent @@ -51,36 +119,46 @@ public class PersistentSettingsManager { m_defaultValue = defaultValue; } - /** Sets the persistent value to set */ + /** Sets the value to persist */ public void set(T value) { m_value = value; // save value in preference store persistParameter(value); } - /** Gets the persistent value, if found, else the default value */ + /** Returns the persistent value, if found, else the default value */ public T value() { if (m_value == null) { // attempt to get the value from the preference store m_value = restoreParameter(); } // parameter has one value for any/all instances - else if(!m_perInstance) { + else if(!isPerInstance()) { // do not rely on cached value, since another instance might have // changed it - reread from data store m_value = restoreParameter(); } - return (m_value!=null)? m_value : m_defaultValue; + return (m_value == null)? m_defaultValue : m_value; + } + + /** + * Gets the persistent value, optionally forcing re-reading stored value + * @param forceRefresh whether to force to re-read memento in case value changed + */ + public T value(boolean forceRefresh) { + if (forceRefresh) { + m_value = null; + } + return value(); } /** Attempts to find the parameter in the preference store. Returns null if not found */ private T restoreParameter() { IEclipsePreferences store = MulticoreVisualizerUIPlugin.getEclipsePreferenceStore(); - String memento = store.get(m_storeKey, null); + String memento = store.get(getStoreKey(), null); if (memento == null) return null; String val = MementoUtils.decodeStringFromMemento(memento); - T convertedVal = convertToT(val); return convertedVal; } @@ -93,7 +171,7 @@ public class PersistentSettingsManager { // save memento in store if (memento != null) { IEclipsePreferences store = MulticoreVisualizerUIPlugin.getEclipsePreferenceStore(); - store.put(m_storeKey, memento); + store.put(getStoreKey(), memento); try { store.flush(); } catch (BackingStoreException e) { @@ -101,22 +179,208 @@ public class PersistentSettingsManager { } } } + } + + /** Class for a persistent {@literal List<T>} parameter */ + public class PersistentListParameter<T> extends AbstractPersistentParameter<T> { + private List<T> m_value; + private List<T> m_defaultValue; - @SuppressWarnings("unchecked") - /** Converts the stored value from a String to its expected type */ - private T convertToT(String val) { - // TODO: Add other types? Float, etc - if (String.class.isAssignableFrom(myClazz)) { - return (T) val; + public PersistentListParameter(Class<T> clazz, boolean perInstance, String storeKey) { + super(clazz, perInstance, storeKey); + } + + /** Sets the default value to use if no persistent + * value is found for this parameter */ + public void setDefault(List<T> defaultValues) { + m_defaultValue = defaultValues; + } + + /** Sets the value to persist */ + public void set(List<T> values) { + m_value = values; + // save value in preference store + persistParameter(values); + } + + /** Returns the persistent value, if found, else the default value */ + public List<T> value() { + if (m_value == null) { + // attempt to get the value from the preference store + m_value = restoreParameter(); } - else if (Integer.class.isAssignableFrom(myClazz)) { - return (T) Integer.valueOf(val); + // parameter has one value for any/all instances + else if(!isPerInstance()) { + // do not rely on cached value, since another instance might have + // changed it - reread from data store + m_value = restoreParameter(); } - else if (Boolean.class.isAssignableFrom(myClazz)) { - return (T) Boolean.valueOf(val); + return (m_value == null)? m_defaultValue : m_value ; + } + + /** + * Gets the persistent value, optionally forcing re-reading stored value + * @param forceRefresh whether to force to re-read memento in case value changed + */ + public List<T> value(boolean forceRefresh) { + if (forceRefresh) { + m_value = null; } + return value(); + } + + /** Attempts to find the parameter in the preference store. Returns null if not found */ + private List<T> restoreParameter() { + IEclipsePreferences store = MulticoreVisualizerUIPlugin.getEclipsePreferenceStore(); + String memento = store.get(getStoreKey(), null); + if (memento == null) return null; - return null; + List<String> vals = MementoUtils.decodeListFromMemento(memento); + // convert from List<String> to List<T> + List<T> convertedVal = convertToT(vals); + return convertedVal; + } + + /** Saves parameter's value in preference store */ + private void persistParameter(List<T> values) { + // Convert List<T> to List<String> + List<String> strList = convertTListToStringList(values); + // create memento from List<String> + String memento = MementoUtils.encodeListIntoMemento(strList); + + // save memento in store + if (memento != null) { + IEclipsePreferences store = MulticoreVisualizerUIPlugin.getEclipsePreferenceStore(); + store.put(getStoreKey(), memento); + try { + store.flush(); + } catch (BackingStoreException e) { + e.printStackTrace(); + } + } + } + + /** For list parameters, converts the restored values from String + * to its expected generic type */ + private List<T> convertToT(List<String> vals) { + List<T> convertedList = new ArrayList<>(); + + for(String val : vals) { + convertedList.add(convertToT(val)); + } + return convertedList; + } + + /** Converts a list of generic type to a list of String */ + private List<String> convertTListToStringList(List<T> tList) { + List<String> strList = new ArrayList<>(); + // convert list to list of String + for(T elem : tList) { + strList.add(elem.toString()); + } + return strList; + } + } + + + /** Class for a persistent {@literal Map<String,T>} parameter */ + public class PersistentMapParameter<T> extends AbstractPersistentParameter<T> { + private Map<String,T> m_value; + private Map<String,T> m_defaultValue; + + public PersistentMapParameter(Class<T> clazz, boolean perInstance, String storeKey) { + super(clazz, perInstance, storeKey); + } + + /** Sets the default value to use if no persistent + * value is found for this parameter */ + public void setDefault(Map<String,T> defaultValues) { + m_defaultValue = defaultValues; + } + + /** Sets the value to persist */ + public void set(Map<String,T> values) { + m_value = values; + // save value in preference store + persistParameter(values); + } + + /** Returns the persistent value, if found, else the default value */ + public Map<String,T> value() { + if (m_value == null) { + // attempt to get the value from the preference store + m_value = restoreParameter(); + } + // parameter has one value for any/all instances + else if(!isPerInstance()) { + // do not rely on cached value, since another instance might have + // changed it - reread from data store + m_value = restoreParameter(); + } + return (m_value == null)? m_defaultValue : m_value ; + } + + /** + * Gets the persistent value, optionally forcing re-reading stored value + * @param forceRefresh whether to force to re-read memento in case value changed + */ + public Map<String,T> value(boolean forceRefresh) { + if (forceRefresh) { + m_value = null; + } + return value(); + } + + /** Attempts to find the parameter in the preference store. Returns null if not found */ + private Map<String,T> restoreParameter() { + IEclipsePreferences store = MulticoreVisualizerUIPlugin.getEclipsePreferenceStore(); + String memento = store.get(getStoreKey(), null); + if (memento == null) return null; + + Map<String,String> vals = MementoUtils.decodeMapFromMemento(memento); + // convert from Map<String,String> to Map<String,T> + Map<String,T> convertedVal = convertToT(vals); + return convertedVal; + } + + /** Saves parameter's value in preference store */ + private void persistParameter(Map<String,T> values) { + // Convert Map<String,T> to Map<String,String> + Map<String,String> strMap = convertTMapToStringMap(values); + // create memento from Map + String memento = MementoUtils.encodeMapIntoMemento(strMap); + + // save memento in store + if (memento != null) { + IEclipsePreferences store = MulticoreVisualizerUIPlugin.getEclipsePreferenceStore(); + store.put(getStoreKey(), memento); + try { + store.flush(); + } catch (BackingStoreException e) { + e.printStackTrace(); + } + } + } + + /** For Map parameters, converts the restored values from {@literal Map<String,String>} + * to {@literal Map<String, T>} */ + private Map<String,T> convertToT(Map<String,String> vals) { + Map<String,T> convertedMap = new HashMap<>(); + + for(String key : vals.keySet()) { + convertedMap.put(key, convertToT(vals.get(key))); + } + return convertedMap; + } + + /** Converts a {@literal Map<String,T>} to a {@literal Map<String,String>} */ + private Map<String,String> convertTMapToStringMap(Map<String,T> map) { + Map<String,String> strMap = new HashMap<>(); + // convert each entry + for(String key : map.keySet()) { + strMap.put(key, map.get(key).toString()); + } + return strMap; } } @@ -165,17 +429,56 @@ public class PersistentSettingsManager { * @param defaultValue: default value to use (mandatory) */ public <T> PersistentParameter<T> getNewParameter(Class<T> clazz, String label, boolean perInstance, T defaultValue) { + PersistentParameter<T> setting; + // build the final store key with category, parameter label and specific instance, if applicable + setting = new PersistentParameter<T>(clazz, perInstance, getStorageKey(perInstance) + "." + label); //$NON-NLS-1$ // check that we're dealing with one of a few supported types - // TODO: Add other types? Float, etc - if (String.class.isAssignableFrom(clazz) || - Integer.class.isAssignableFrom(clazz) || - Boolean.class.isAssignableFrom(clazz)) - { - PersistentParameter<T> setting; - // build the final store key with category, parameter label and specific instance, if applicable - setting = new PersistentParameter<T>(clazz, perInstance, getStorageKey(perInstance) + "." + label); //$NON-NLS-1$ + if (setting.isTypeSupported(clazz)) { + setting.setDefault(defaultValue); + return setting; + } + else { + throw new InvalidParameterException("Unsupported class type: " + clazz.toString()); //$NON-NLS-1$ + } + } + + /** + * Creates a new persistent {@literal List<T>} parameter, using the namespace and instance id of this manager. + * @param clazz: the class of the persistent parameter List (e.g. List of that type). Supported types: String, Integer, Boolean + * @param label: unique label that identifies this parameter. + * @param perInstance: whether the parameter's value should be persisted per client instance or + * globally (one common shared stored value for all instances) + * @param defaultValue: default value to use (mandatory). + */ + public <T> PersistentListParameter<T> getNewListParameter(Class<T> clazz, String label, boolean perInstance, List<T> defaultValue) { + PersistentListParameter<T> setting; + // build the final store key with category, parameter label and specific instance, if applicable + setting = new PersistentListParameter<T>(clazz, perInstance, getStorageKey(perInstance) + "." + label); //$NON-NLS-1$ + // check that we're dealing with one of a few supported types + if (setting.isTypeSupported(clazz)) { + setting.setDefault(defaultValue); + return setting; + } + else { + throw new InvalidParameterException("Unsupported class type: " + clazz.toString()); //$NON-NLS-1$ + } + } + + /** + * Creates a new persistent {@literal Map<String,T>} parameter, using the namespace and instance id of this manager. + * @param clazz: the class of the persistent parameter List (e.g. List of that type). Supported types: String, Integer, Boolean + * @param label: unique label that identifies this parameter. + * @param perInstance: whether the parameter's value should be persisted per client instance or + * globally (one common shared stored value for all instances) + * @param defaultValue: default value to use (mandatory). + */ + public <T> PersistentMapParameter<T> getNewMapParameter(Class<T> clazz, String label, boolean perInstance, Map<String,T> defaultValue) { + PersistentMapParameter<T> setting; + // build the final store key with category, parameter label and specific instance, if applicable + setting = new PersistentMapParameter<T>(clazz, perInstance, getStorageKey(perInstance) + "." + label); //$NON-NLS-1$ + // check that we're dealing with one of a few supported types + if (setting.isTypeSupported(clazz)) { setting.setDefault(defaultValue); - return setting; } else { @@ -183,11 +486,11 @@ public class PersistentSettingsManager { } } + // ---- misc ---- /** Returns the key to be used to save parameter, taking into account the * instance id, if applicable */ private String getStorageKey(boolean perInstance) { return (perInstance ? m_instance : "") + (!m_category.equals("") ? "." + m_category : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } - -} +}
\ No newline at end of file |