--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+/*\r
+ * 28.6.2006\r
+ */\r
+package org.simantics.utils.ui.workbench;\r
+\r
+import java.io.UnsupportedEncodingException;\r
+import java.util.ArrayList;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.TreeMap;\r
+import java.util.Map.Entry;\r
+\r
+import org.eclipse.ui.IMemento;\r
+import org.simantics.utils.bytes.Base64;\r
+import org.simantics.utils.datastructures.Pair;\r
+import org.simantics.utils.strings.EString;\r
+\r
+\r
+/**\r
+ * StringMemento is IMemento implementation that \r
+ * handles all information in a single string.\r
+ * \r
+ * @author Toni Kalajainen\r
+ */\r
+public class StringMemento implements IMemento {\r
+\r
+ public final static String TAG_TEXTDATA = "org.simantics.utils.ui.workbench.StringMemento.TAG_TEXTDATA";\r
+\r
+ public final static String CHILD_TAG_CHAR = "#";\r
+ public final static String ESCAPE_SET = ",="+CHILD_TAG_CHAR;\r
+ public final static char ESCAPE_CHAR = '\\';\r
+\r
+ protected Map<String, String> values = new TreeMap<String, String>();\r
+ protected List<ChildType> types = new ArrayList<ChildType>();\r
+ protected String type = "";\r
+\r
+ class ChildType {\r
+ StringMemento memento;\r
+ public ChildType(StringMemento memento)\r
+ {\r
+ this.memento = memento;\r
+ }\r
+ }\r
+\r
+ public StringMemento()\r
+ {\r
+ }\r
+\r
+ public StringMemento(String data)\r
+ throws IllegalArgumentException\r
+ {\r
+ setStringData(data);\r
+ }\r
+\r
+ public IMemento createChild(String type) {\r
+ ChildType ct = new ChildType(new StringMemento());\r
+ ct.memento.type = type;\r
+ types.add(ct);\r
+ return ct.memento;\r
+ }\r
+\r
+ public IMemento createChild(String type, String id) {\r
+ IMemento result = createChild(type);\r
+ result.putString(IMemento.TAG_ID, id);\r
+ return result;\r
+ }\r
+\r
+ public IMemento getChild(String type) {\r
+ for (ChildType ct : types)\r
+ if (ct.memento.type.equals(type))\r
+ return ct.memento;\r
+ return null;\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see org.eclipse.ui.IMemento#getChildren()\r
+ * @since 3.8\r
+ */\r
+ public IMemento[] getChildren() {\r
+ List<IMemento> result = new ArrayList<IMemento>();\r
+ for (ChildType ct : types)\r
+ result.add(ct.memento);\r
+ return result.toArray(new IMemento[result.size()]);\r
+ }\r
+\r
+ public IMemento[] getChildren(String type) {\r
+ List<IMemento> result = new ArrayList<IMemento>();\r
+ for (ChildType ct : types)\r
+ if (ct.memento.type.equals(type))\r
+ result.add(ct.memento);\r
+ return result.toArray(new IMemento[result.size()]);\r
+ }\r
+\r
+ public Boolean getBoolean(String key) {\r
+ String value = getString(key);\r
+ if (value==null) return null;\r
+ return Boolean.valueOf(value);\r
+ }\r
+\r
+ public Float getFloat(String key) \r
+ {\r
+ String value = getString(key);\r
+ if (value==null) return null;\r
+ return new Float(value);\r
+ }\r
+\r
+ public Long getLong(String key) \r
+ {\r
+ String value = getString(key);\r
+ if (value==null) return null;\r
+ return new Long(value);\r
+ }\r
+\r
+ public String getType() {\r
+ return type;\r
+ }\r
+\r
+ public String getID() {\r
+ return getString(IMemento.TAG_ID);\r
+ }\r
+\r
+ public Integer getInteger(String key) {\r
+ String value = getString(key);\r
+ if (value==null) return null;\r
+ return new Integer(value);\r
+ }\r
+\r
+ public String getString(String key) {\r
+ return values.get(key);\r
+ }\r
+\r
+ public String getTextData() {\r
+ return getString(TAG_TEXTDATA);\r
+ }\r
+\r
+ public String[] getAttributeKeys() {\r
+ Set<String> keys = values.keySet();\r
+ return keys.toArray(new String[keys.size()]);\r
+ }\r
+\r
+ public void putFloat(String key, float value) {\r
+ putString(key, new Float(value).toString());\r
+ }\r
+\r
+ public void putInteger(String key, int value) {\r
+ putString(key, new Integer(value).toString());\r
+ }\r
+\r
+ public void putLong(String key, long value) {\r
+ putString(key, new Long(value).toString());\r
+ }\r
+\r
+ public void putBoolean(String key, boolean value) {\r
+ putString(key, String.valueOf(value));\r
+ }\r
+\r
+ public StringMemento clone()\r
+ {\r
+ return new StringMemento(toString());\r
+ }\r
+\r
+ public void putMemento(IMemento memento) {\r
+ StringMemento sm = ((StringMemento) memento);\r
+ addStringData(sm.toString());\r
+ }\r
+\r
+ /**\r
+ * Writes self to <code>dst</code>\r
+ * @param dst \r
+ */\r
+ public void writeToMemento(IMemento dst) {\r
+ for (Entry<String, String> e : values.entrySet())\r
+ {\r
+ dst.putString(e.getKey(), e.getValue());\r
+ }\r
+ for (ChildType c : types)\r
+ {\r
+ IMemento cdst = dst.createChild(c.memento.type);\r
+ c.memento.writeToMemento(cdst);\r
+ }\r
+ }\r
+\r
+ public void putString(String key, String value) {\r
+ values.put(key, value);\r
+ }\r
+\r
+ public void putTextData(String data) {\r
+ putString(TAG_TEXTDATA, data);\r
+ }\r
+\r
+ public boolean isEmpty() {\r
+ return values.isEmpty() && types.isEmpty();\r
+ }\r
+\r
+ // Serialization part //\r
+\r
+ protected String escapeString(String str)\r
+ {\r
+ return EString.escapeString(str, ESCAPE_SET, ESCAPE_CHAR);\r
+ }\r
+\r
+ protected String unescapeString(String str)\r
+ {\r
+ return EString.unescapeString(str, ESCAPE_CHAR);\r
+ }\r
+\r
+ private String scanEscapedString(String str, char endMark)\r
+ {\r
+ return EString.scanEscapedString(str, ESCAPE_CHAR, endMark);\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ StringBuilder sb = new StringBuilder(100);\r
+ for (Entry<String, String> e : values.entrySet())\r
+ {\r
+ // Add ,\r
+ if (sb.length()>0)\r
+ sb.append(",");\r
+ // Add key=value\r
+ if (e.getValue()==null) continue;\r
+ sb.append(escapeString(e.getKey())+"="+escapeString(e.getValue()));\r
+ }\r
+ \r
+ for (ChildType ct : types)\r
+ {\r
+ // Add ,\r
+ if (sb.length()>0)\r
+ sb.append(",");\r
+ sb.append(CHILD_TAG_CHAR+escapeString(ct.memento.type)+"="+escapeString(ct.memento.toString()));\r
+ }\r
+ \r
+ return sb.toString();\r
+ }\r
+ \r
+ /**\r
+ * Get keys\r
+ * @return\r
+ */\r
+ public Set<String> getKeys() {\r
+ return new HashSet<String>(values.keySet());\r
+ }\r
+\r
+ /**\r
+ * Parses string into memento variables and children\r
+ * @param data string data\r
+ * @throws IllegalArgumentException\r
+ */\r
+ public void setStringData(String data)\r
+ throws IllegalArgumentException\r
+ {\r
+ clear();\r
+ addStringData(data);\r
+ }\r
+ \r
+ /**\r
+ * Clears all data\r
+ */\r
+ public void clear()\r
+ {\r
+ values.clear();\r
+ types.clear();\r
+ }\r
+ \r
+ /**\r
+ * Parses string into memento variables and children\r
+ * @param data string data\r
+ * @throws IllegalArgumentException\r
+ */\r
+ public void addStringData(String data)\r
+ throws IllegalArgumentException\r
+ {\r
+ // key\==\=value,key2=value,key3=value,#type=(key\=value\,key2\=value)\r
+ for (Pair<String, String> pair : scanKeyValues(data))\r
+ {\r
+ String key = unescapeString(pair.first);\r
+ String value = unescapeString(pair.second);\r
+ \r
+ if (key.startsWith(CHILD_TAG_CHAR))\r
+ {\r
+ String type = key.substring(1);\r
+ StringMemento sm = new StringMemento(value);\r
+ sm.type = type;\r
+ ChildType ct = new ChildType(sm);\r
+ types.add(ct);\r
+ } else {\r
+ values.put(key, value);\r
+ }\r
+ }\r
+ } \r
+ \r
+ private List<Pair<String, String>> scanKeyValues(String str)\r
+ {\r
+ List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();\r
+ \r
+ while(str.length()>0)\r
+ {\r
+ // Get next key, value -pair\r
+ String chunk = scanEscapedString(str, ',');\r
+ // Crop the chunk\r
+ if (chunk.length()+1<str.length())\r
+ str = str.substring(chunk.length()+1);\r
+ else\r
+ str = "";\r
+ // break chunk into key and value\r
+ String key = scanEscapedString(chunk, '=');\r
+ if (key.length()+1<chunk.length())\r
+ chunk = chunk.substring(key.length()+1);\r
+ else\r
+ chunk = "";\r
+ String value = chunk;\r
+ \r
+ result.add(new Pair<String, String>(key, value));\r
+ }\r
+ \r
+ return result;\r
+ }\r
+\r
+\r
+ @SuppressWarnings("unused")\r
+ public static void main(String [] args)\r
+ {\r
+ \r
+ //StringMemento sm = new StringMemento("key\\==\\=value,key2=value,key3=value,#type=key\\=value\\,key2\\=value");\r
+ StringMemento sm = new StringMemento();\r
+ sm.putString("Level", "1");\r
+ StringMemento sm2 = (StringMemento) sm.createChild("Children");\r
+ sm2.putString("Level", "2");\r
+ StringMemento sm3 = (StringMemento) sm2.createChild("Children");\r
+ sm3.putString("Level", "3");\r
+ \r
+ StringMemento sm4 = new StringMemento(sm.toString());\r
+ System.out.println(sm.getChild("Children").getChild("Children").getString("Level"));\r
+ IMemento sms[] = sm.getChildren("Children");\r
+ System.out.println(sm.toString());\r
+\r
+ StringMemento sm5 = new StringMemento();\r
+ IMemento sm6 = sm5.createChild("argument");\r
+ sm6.putString("arg", "-server");\r
+ sm6.putString("value", "localhost:6668");\r
+ System.out.println("simantics link: " + sm5.toString());\r
+ try {\r
+ String b64 = Base64.encode(sm5.toString().getBytes("UTF-8"));\r
+ System.out.println("simantics link: " + b64);\r
+ } catch (UnsupportedEncodingException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+}\r