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