/***************************************************************** * Copyright (c) 2011, 2015 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Wind River Systems - initial API and implementation *****************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel; import java.util.Map; import java.util.TreeMap; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.ui.IMemento; import org.eclipse.ui.IPersistableElement; /** * Generic persistable for storing a map of simple values. * <br> * Currently supported value types are {@link Integer} and {@link String}. * * @since 2.5 */ public class SimpleMapPersistable<V> implements IPersistableElement, IAdaptable { private static final String KEY_TYPE = "type"; //$NON-NLS-1$ private static final String KEY_NAME = "name"; //$NON-NLS-1$ private static final String KEY_VALUE = "value"; //$NON-NLS-1$ private Class<V> fType; private Map<String, V> fValues = new TreeMap<String, V>(); @SuppressWarnings("unchecked") public SimpleMapPersistable(IMemento memento) throws CoreException { IMemento type = memento.getChild(KEY_TYPE); if (type == null) { throw new CoreException(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Missing key for type.", null)); //$NON-NLS-1$ } try { fType = (Class<V>)Class.forName(type.getTextData()); } catch (ClassNotFoundException e) { throw new CoreException(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, e.getMessage(), e)); } IMemento[] list = memento.getChildren(KEY_NAME); Map<String, V> values = new TreeMap<String, V>(); for (IMemento elem : list) { values.put(elem.getID(), getValue(elem)); } synchronized(fValues) { // We should not assign 'values' directly to 'fValues' // if we want synchronization to work. Instead, we must use // the same map as before for 'fValues' fValues.clear(); fValues.putAll(values); } } public SimpleMapPersistable(Class<V> type) { fType = type; } @Override public void saveState(IMemento memento) { Map<String, V> values = null; synchronized (fValues) { values = new TreeMap<String, V>(fValues); } IMemento type = memento.createChild(KEY_TYPE); synchronized (fType) { type.putTextData(fType.getName()); } for (Map.Entry<String, V> entry : values.entrySet()) { IMemento value = memento.createChild(KEY_NAME, entry.getKey()); putValue(value, entry.getValue()); } } private void putValue(IMemento memento, Object value) { if (value instanceof String) { memento.putString(KEY_VALUE, (String)value); } else if (value instanceof Integer) { memento.putInteger(KEY_VALUE, (Integer)value); } else { assert false; } } @SuppressWarnings("unchecked") private V getValue(IMemento memento) { synchronized (fType) { if (String.class.equals(fType)) { return (V)memento.getString(KEY_VALUE); } else if (Integer.class.equals(fType)) { return (V)memento.getInteger(KEY_VALUE); } else { assert false; } } return null; } public V getValue(String key) { if (key == null) return null; synchronized (fValues) { return fValues.get(key); } } public void setValue(String key, V value) { synchronized (fValues) { if (value == null) { fValues.remove(key); } else { fValues.put(key, value); } } } @Override public String getFactoryId() { return SimpleMapPersistableFactory.getFactoryId(); } @SuppressWarnings("unchecked") @Override public <T> T getAdapter(Class<T> adapter) { if (adapter.isInstance(this)) { return (T)this; } return null; } }