--- /dev/null
+package com.vaadin.data.util;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashSet;\r
+import java.util.Iterator;\r
+\r
+/**\r
+ * ListSet is an internal Vaadin class which implements a combination of a List\r
+ * and a Set. The main purpose of this class is to provide a fast\r
+ * {@link #contains(Object)} method. Each inserted object must by unique (as\r
+ * specified by {@link #equals(Object)}).\r
+ * \r
+ * This class is subject to change and should not be used outside Vaadin core.\r
+ */\r
+public class ListSet<E> extends ArrayList<E> {\r
+ private HashSet<E> itemSet = null;\r
+\r
+ public ListSet() {\r
+ super();\r
+ itemSet = new HashSet<E>();\r
+ }\r
+\r
+ public ListSet(Collection<? extends E> c) {\r
+ super(c);\r
+ itemSet = new HashSet<E>(c.size());\r
+ itemSet.addAll(c);\r
+ }\r
+\r
+ public ListSet(int initialCapacity) {\r
+ super(initialCapacity);\r
+ itemSet = new HashSet<E>(initialCapacity);\r
+ }\r
+\r
+ // Delegate contains operations to the set\r
+ @Override\r
+ public boolean contains(Object o) {\r
+ return itemSet.contains(o);\r
+ }\r
+\r
+ @Override\r
+ public boolean containsAll(Collection<?> c) {\r
+ return itemSet.containsAll(c);\r
+ }\r
+\r
+ // Methods for updating the set when the list is updated.\r
+ @Override\r
+ public boolean add(E e) {\r
+ if (contains(e)) {\r
+ // Duplicates are not allowed\r
+ return false;\r
+ }\r
+\r
+ if (super.add(e)) {\r
+ itemSet.add(e);\r
+ return true;\r
+ } else {\r
+ return false;\r
+ }\r
+ };\r
+\r
+ /**\r
+ * Works as java.util.ArrayList#add(int, java.lang.Object) but returns\r
+ * immediately if the element is already in the ListSet.\r
+ */\r
+ @Override\r
+ public void add(int index, E element) {\r
+ if (contains(element)) {\r
+ // Duplicates are not allowed\r
+ return;\r
+ }\r
+\r
+ super.add(index, element);\r
+ itemSet.add(element);\r
+ }\r
+\r
+ @Override\r
+ public boolean addAll(Collection<? extends E> c) {\r
+ boolean modified = false;\r
+ Iterator<? extends E> i = c.iterator();\r
+ while (i.hasNext()) {\r
+ E e = i.next();\r
+ if (contains(e)) {\r
+ continue;\r
+ }\r
+\r
+ if (add(e)) {\r
+ itemSet.add(e);\r
+ modified = true;\r
+ }\r
+ }\r
+ return modified;\r
+ }\r
+\r
+ @Override\r
+ public boolean addAll(int index, Collection<? extends E> c) {\r
+ ensureCapacity(size() + c.size());\r
+\r
+ boolean modified = false;\r
+ Iterator<? extends E> i = c.iterator();\r
+ while (i.hasNext()) {\r
+ E e = i.next();\r
+ if (contains(e)) {\r
+ continue;\r
+ }\r
+\r
+ add(index++, e);\r
+ itemSet.add(e);\r
+ modified = true;\r
+ }\r
+\r
+ return modified;\r
+ }\r
+\r
+ @Override\r
+ public void clear() {\r
+ super.clear();\r
+ itemSet.clear();\r
+ }\r
+\r
+ @Override\r
+ public int indexOf(Object o) {\r
+ if (!contains(o)) {\r
+ return -1;\r
+ }\r
+\r
+ return super.indexOf(o);\r
+ }\r
+\r
+ @Override\r
+ public int lastIndexOf(Object o) {\r
+ if (!contains(o)) {\r
+ return -1;\r
+ }\r
+\r
+ return super.lastIndexOf(o);\r
+ }\r
+\r
+ @Override\r
+ public E remove(int index) {\r
+ E e = super.remove(index);\r
+\r
+ if (e != null) {\r
+ itemSet.remove(e);\r
+ }\r
+\r
+ return e;\r
+ }\r
+\r
+ @Override\r
+ public boolean remove(Object o) {\r
+ if (super.remove(o)) {\r
+ itemSet.remove(o);\r
+ return true;\r
+ } else {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ protected void removeRange(int fromIndex, int toIndex) {\r
+ HashSet<E> toRemove = new HashSet<E>();\r
+ for (int idx = fromIndex; idx < toIndex; idx++) {\r
+ toRemove.add(get(idx));\r
+ }\r
+ super.removeRange(fromIndex, toIndex);\r
+ itemSet.removeAll(toRemove);\r
+ }\r
+\r
+ @Override\r
+ public E set(int index, E element) {\r
+ if (contains(element)) {\r
+ // Element already exist in the list\r
+ if (get(index) == element) {\r
+ // At the same position, nothing to be done\r
+ return element;\r
+ } else {\r
+ // At another position, cannot set\r
+ return null;\r
+ }\r
+ }\r
+\r
+ E old = super.set(index, element);\r
+ itemSet.remove(old);\r
+ itemSet.add(element);\r
+\r
+ return old;\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ @Override\r
+ public Object clone() {\r
+ ListSet<E> v = (ListSet<E>) super.clone();\r
+ v.itemSet = new HashSet<E>(itemSet);\r
+ return v;\r
+ }\r
+\r
+}\r