/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * 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: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ /* * 28.6.2006 */ package org.simantics.utils.ui.workbench; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.Map.Entry; import org.eclipse.ui.IMemento; import org.simantics.utils.bytes.Base64; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.strings.EString; /** * StringMemento is IMemento implementation that * handles all information in a single string. * * @author Toni Kalajainen */ public class StringMemento implements IMemento { public final static String TAG_TEXTDATA = "org.simantics.utils.ui.workbench.StringMemento.TAG_TEXTDATA"; public final static String CHILD_TAG_CHAR = "#"; public final static String ESCAPE_SET = ",="+CHILD_TAG_CHAR; public final static char ESCAPE_CHAR = '\\'; protected Map values = new TreeMap(); protected List types = new ArrayList(); protected String type = ""; class ChildType { StringMemento memento; public ChildType(StringMemento memento) { this.memento = memento; } } public StringMemento() { } public StringMemento(String data) throws IllegalArgumentException { setStringData(data); } public IMemento createChild(String type) { ChildType ct = new ChildType(new StringMemento()); ct.memento.type = type; types.add(ct); return ct.memento; } public IMemento createChild(String type, String id) { IMemento result = createChild(type); result.putString(IMemento.TAG_ID, id); return result; } public IMemento getChild(String type) { for (ChildType ct : types) if (ct.memento.type.equals(type)) return ct.memento; return null; } /* (non-Javadoc) * @see org.eclipse.ui.IMemento#getChildren() * @since 3.8 */ public IMemento[] getChildren() { List result = new ArrayList(); for (ChildType ct : types) result.add(ct.memento); return result.toArray(new IMemento[result.size()]); } public IMemento[] getChildren(String type) { List result = new ArrayList(); for (ChildType ct : types) if (ct.memento.type.equals(type)) result.add(ct.memento); return result.toArray(new IMemento[result.size()]); } public Boolean getBoolean(String key) { String value = getString(key); if (value==null) return null; return Boolean.valueOf(value); } public Float getFloat(String key) { String value = getString(key); if (value==null) return null; return new Float(value); } public Long getLong(String key) { String value = getString(key); if (value==null) return null; return new Long(value); } public String getType() { return type; } public String getID() { return getString(IMemento.TAG_ID); } public Integer getInteger(String key) { String value = getString(key); if (value==null) return null; return new Integer(value); } public String getString(String key) { return values.get(key); } public String getTextData() { return getString(TAG_TEXTDATA); } public String[] getAttributeKeys() { Set keys = values.keySet(); return keys.toArray(new String[keys.size()]); } public void putFloat(String key, float value) { putString(key, new Float(value).toString()); } public void putInteger(String key, int value) { putString(key, new Integer(value).toString()); } public void putLong(String key, long value) { putString(key, new Long(value).toString()); } public void putBoolean(String key, boolean value) { putString(key, String.valueOf(value)); } public StringMemento clone() { return new StringMemento(toString()); } public void putMemento(IMemento memento) { StringMemento sm = ((StringMemento) memento); addStringData(sm.toString()); } /** * Writes self to dst * @param dst */ public void writeToMemento(IMemento dst) { for (Entry e : values.entrySet()) { dst.putString(e.getKey(), e.getValue()); } for (ChildType c : types) { IMemento cdst = dst.createChild(c.memento.type); c.memento.writeToMemento(cdst); } } public void putString(String key, String value) { values.put(key, value); } public void putTextData(String data) { putString(TAG_TEXTDATA, data); } public boolean isEmpty() { return values.isEmpty() && types.isEmpty(); } // Serialization part // protected String escapeString(String str) { return EString.escapeString(str, ESCAPE_SET, ESCAPE_CHAR); } protected String unescapeString(String str) { return EString.unescapeString(str, ESCAPE_CHAR); } private String scanEscapedString(String str, char endMark) { return EString.scanEscapedString(str, ESCAPE_CHAR, endMark); } @Override public String toString() { StringBuilder sb = new StringBuilder(100); for (Entry e : values.entrySet()) { // Add , if (sb.length()>0) sb.append(","); // Add key=value if (e.getValue()==null) continue; sb.append(escapeString(e.getKey())+"="+escapeString(e.getValue())); } for (ChildType ct : types) { // Add , if (sb.length()>0) sb.append(","); sb.append(CHILD_TAG_CHAR+escapeString(ct.memento.type)+"="+escapeString(ct.memento.toString())); } return sb.toString(); } /** * Get keys * @return */ public Set getKeys() { return new HashSet(values.keySet()); } /** * Parses string into memento variables and children * @param data string data * @throws IllegalArgumentException */ public void setStringData(String data) throws IllegalArgumentException { clear(); addStringData(data); } /** * Clears all data */ public void clear() { values.clear(); types.clear(); } /** * Parses string into memento variables and children * @param data string data * @throws IllegalArgumentException */ public void addStringData(String data) throws IllegalArgumentException { // key\==\=value,key2=value,key3=value,#type=(key\=value\,key2\=value) for (Pair pair : scanKeyValues(data)) { String key = unescapeString(pair.first); String value = unescapeString(pair.second); if (key.startsWith(CHILD_TAG_CHAR)) { String type = key.substring(1); StringMemento sm = new StringMemento(value); sm.type = type; ChildType ct = new ChildType(sm); types.add(ct); } else { values.put(key, value); } } } private List> scanKeyValues(String str) { List> result = new ArrayList>(); while(str.length()>0) { // Get next key, value -pair String chunk = scanEscapedString(str, ','); // Crop the chunk if (chunk.length()+1