]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/MapList.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.utils.datastructures / src / org / simantics / utils / datastructures / MapList.java
diff --git a/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/MapList.java b/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/MapList.java
new file mode 100644 (file)
index 0000000..aeef0fd
--- /dev/null
@@ -0,0 +1,295 @@
+/*******************************************************************************\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
+ * 16.8.2006\r
+ */\r
+package org.simantics.utils.datastructures;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Map.Entry;\r
+import java.util.Set;\r
+\r
+/**\r
+ * MapList is a data structure with map on left side and arraylist on right side.\r
+ * <p>\r
+ * \r
+ * @author Toni Kalajainen\r
+ */\r
+public class MapList<L, R> {\r
+\r
+    @SuppressWarnings("rawtypes")\r
+    public static final MapList EMPTY_MAPLIST = new MapList() {\r
+        private static final String IMMUTABLE_MSG = "Cannot modify immutable empty MapList";\r
+\r
+        @Override\r
+        public void add(Object key) {\r
+            throw new UnsupportedOperationException(IMMUTABLE_MSG);\r
+        }\r
+        @Override\r
+        public void add(Object key, int index, Object value) {\r
+            throw new UnsupportedOperationException(IMMUTABLE_MSG);\r
+        }\r
+        @Override\r
+        public void add(Object key, Object value) {\r
+            throw new UnsupportedOperationException(IMMUTABLE_MSG);\r
+        }\r
+        @Override\r
+        public void addAll(Object key, Collection values) {\r
+            throw new UnsupportedOperationException(IMMUTABLE_MSG);\r
+        }\r
+        @Override\r
+        public void clear() {\r
+            throw new UnsupportedOperationException(IMMUTABLE_MSG);\r
+        }\r
+        @Override\r
+        public boolean remove(Object key) {\r
+            throw new UnsupportedOperationException(IMMUTABLE_MSG);\r
+        }\r
+        public boolean remove(Object key, Object value) {\r
+            throw new UnsupportedOperationException(IMMUTABLE_MSG);\r
+        }\r
+    };\r
+\r
+    @SuppressWarnings("unchecked")\r
+    public static <L, R> MapList<L, R> emptyMapList() {\r
+        return EMPTY_MAPLIST;\r
+    }\r
+\r
+    protected Map<L, List<R>> lists;\r
+\r
+    public MapList() {\r
+       lists = new THashMap<L, List<R>>();\r
+    }\r
+    \r
+    @SuppressWarnings("unchecked")\r
+       public MapList( Class<?> mapClass ) {\r
+       try {\r
+                       lists = (Map<L, List<R>>) mapClass.newInstance();\r
+               } catch (InstantiationException e) {\r
+                       throw new RuntimeException( e );\r
+               } catch (IllegalAccessException e) {\r
+                       throw new RuntimeException( e );\r
+               }\r
+    }\r
+\r
+    public MapList(MapList<L, R> copyFrom) {\r
+        for (Entry<L, List<R>> e : copyFrom.lists.entrySet())\r
+            lists.put( e.getKey(), new ArrayList<R>(e.getValue()) );\r
+    }\r
+\r
+       public static <L, R> MapList<L, R> use( Map<L, List<R>> map ) {\r
+               MapList<L, R> result = new MapList<L, R>();\r
+               result.lists = map;\r
+               return result;\r
+       }\r
+    \r
+    public void add(L key) {\r
+        getOrCreateList(key);\r
+    }\r
+\r
+    public void add(L key, R value)\r
+    {\r
+        List<R> list = getOrCreateList(key);\r
+        list.add(value);\r
+    }\r
+\r
+    public void add(L key, int index, R value)\r
+    {\r
+        ArrayList<R> list = getOrCreateList(key);\r
+        list.add(index, value);\r
+    }\r
+\r
+       public void addAll(L key, Collection<R> values) {\r
+               ArrayList<R> list = getOrCreateList(key);\r
+               list.addAll(values);\r
+       }\r
+    \r
+    private ArrayList<R> getOrCreateList(L key)\r
+    {\r
+        ArrayList<R> list = (ArrayList<R>) lists.get(key);\r
+        if (list==null) {\r
+            list = new ArrayList<R>(1);\r
+            lists.put(key, list);\r
+        }\r
+        return list;\r
+    }\r
+\r
+    private List<R> getList(L key)\r
+    {\r
+        return lists.get(key);\r
+    }\r
+\r
+    public boolean remove(L key, R value)\r
+    {\r
+        List<R> list = getList(key);\r
+        if (list==null) return false;\r
+        boolean result = list.remove(value);\r
+        if (list.size()==0)\r
+            lists.remove(key);\r
+        return result;\r
+    }\r
+\r
+    public boolean remove(L key)\r
+    {\r
+        List<R> list = getList(key);\r
+        if (list==null) return false;\r
+        lists.remove(key);\r
+        return true;\r
+    }\r
+\r
+    public void clear()\r
+    {\r
+        lists.clear();\r
+    }\r
+\r
+    public L[] getKeys(L[] list)\r
+    {\r
+        return lists.keySet().toArray(list);\r
+    }\r
+\r
+    public Set<L> getKeys()\r
+    {\r
+        return lists.keySet();\r
+    }\r
+\r
+    public int getKeySize() {\r
+        return lists.size();\r
+    }\r
+\r
+    public boolean containsKey(L key)\r
+    {\r
+        return lists.containsKey(key);\r
+    }\r
+\r
+    public boolean contains(L key, R obj)\r
+    {\r
+        List<R> l = lists.get(key);\r
+        if (l==null) return false;\r
+        return l.contains(obj);\r
+\r
+    }\r
+\r
+    public R[] getValues(L key, R[] list)\r
+    {\r
+        List<R> l = lists.get(key);\r
+        if (l==null) return null;\r
+        return l.toArray(list);\r
+    }\r
+\r
+    /**\r
+     * @param key\r
+     *            the key to get values for\r
+     * @param list\r
+     *            the list to fill with existing values for specified key. Fills\r
+     *            this array with at maximum as many values as there is room for\r
+     *            in the array even if there are more values available in the\r
+     *            maplist for the specified key.\r
+     * @return the amount of values existing for the key. May be smaller or\r
+     *         larger than the size of the provided list. If smaller, only the\r
+     *         first array indexes will be filled with data and if larger, all\r
+     *         array indexes will be filled with data.\r
+     */\r
+    public int getAtMostValues(L key, R[] list)\r
+    {\r
+        List<R> l = lists.get(key);\r
+        if (l==null) return 0;\r
+        int valueCount = l.size();\r
+        int size = Math.min(valueCount, list.length);\r
+        for (int i = 0; i < size; ++i)\r
+            list[i] = l.get(i);\r
+        return valueCount;\r
+    }\r
+\r
+    /**\r
+     * Returns a the internal list values for the specified key. The list is\r
+     * valid as long as it contains elements. The list should not be modified\r
+     * but the return value of this method does not enforce it like\r
+     * {@link #getValues(Object)} does. Use this method when you know you will\r
+     * not risk a 3rd party modifying the returned list and you want to avoid\r
+     * the cost of extra memory allocation through\r
+     * {@link Collections#unmodifiableList(List)}.\r
+     * \r
+     * @param key\r
+     *            the key to look values for\r
+     * @return empty unmodifiable list if there is no list with the specified\r
+     *         key, otherwise an unmodifiable version of the stored list\r
+     */\r
+    public List<R> getValuesUnsafe(L key)\r
+    {\r
+        List<R> l = lists.get(key);\r
+        return l != null ? l : Collections.<R>emptyList();\r
+    }\r
+\r
+    /**\r
+     * Returns a read-only reference to the values. The list is valid as long as\r
+     * it contains elements.\r
+     * \r
+     * @param key\r
+     * @return empty unmodifiable list if there is no list with the specified key,\r
+     *         otherwise an unmodifiable version of the stored list\r
+     */\r
+    public List<R> getValues(L key)\r
+    {\r
+        List<R> l = lists.get(key);\r
+        if (l==null) return Collections.emptyList();\r
+        return Collections.unmodifiableList(l);\r
+    }\r
+\r
+    /**\r
+     * Returns a copy of the values\r
+     * \r
+     * @param key\r
+     * @return empty unmodifiable list if there is no list with the specified key,\r
+     *         otherwise a copy of the stored list\r
+     */\r
+    public List<R> getValuesSnapshot(L key)\r
+    {\r
+        List<R> l = lists.get(key);\r
+        if (l==null) return Collections.emptyList();\r
+        return new ArrayList<R>(l);\r
+    }\r
+    \r
+    public List<R> getAllValuesSnapshot() \r
+    {\r
+        return getAllValuesSnapshot(null);\r
+    }\r
+\r
+    public List<R> getAllValuesSnapshot(List<R> result) \r
+    {\r
+        if (result == null)\r
+            result = new ArrayList<R>();\r
+        for (List<R> right : lists.values()) {\r
+            result.addAll(right);\r
+        }\r
+        return result;\r
+    }\r
+\r
+    public boolean isEmpty() {\r
+        return lists.isEmpty();\r
+    }\r
+\r
+    /**\r
+     * Makes _this_ maplist immutable.\r
+     */\r
+    public void makeImmutable() {\r
+        for (Entry<L, List<R>> e : lists.entrySet())\r
+            lists.put(e.getKey(), Collections.unmodifiableList(e.getValue()));\r
+        lists = Collections.unmodifiableMap(lists);\r
+    }\r
+\r
+}\r