1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.collections; 27 28 import java.util.Collection; 29 import java.util.Iterator; 30 import java.util.List; 31 import java.util.ListIterator; 32 33 /** 34 * Abstract class that serves as a base class for {@link ObservableList} implementations that are modifiable. 35 * 36 * To implement a modifiable {@code ObservableList} class, you just need to implement the following set of methods: 37 * <ul> 38 * <li> {@link #get(int) get(int)} 39 * <li> {@link #size() size()} 40 * <li> {@link #doAdd(int, java.lang.Object) doAdd(int, Object)} 41 * <li> {@link #doRemove(int) doRemove(int)} 42 * <li> {@link #doSet(int, java.lang.Object) doSet(int, Object)} 43 * </ul> 44 * 45 * and the notifications and built and fired automatically for you. 46 * 47 * <p>Example of a simple {@code ObservableList} delegating to another {@code List} would look like this: 48 * 49 * <pre> 50 * 51 * <strong>public class</strong> ArrayObservableList<E> <strong>extends</strong> ModifiableObservableList<E> { 52 * 53 * <strong>private final List</strong><E> delegate = new <strong>ArrayList</strong><>(); 54 * 55 * <strong>public E</strong> get(int index) { 56 * <strong>return</strong> delegate.get(index); 57 * } 58 * 59 * <strong>public int</strong> size() { 60 * <strong>return</strong> delegate.size(); 61 * } 62 * 63 * <strong>protected void</strong> doAdd(<strong>int</strong> index, <strong>E</strong> element) { 64 * delegate.add(index, element); 65 * } 66 * 67 * <strong>protected E</strong> doSet(<strong>int</strong> index, <strong>E</strong> element) { 68 * <strong>return</strong> delegate.set(index, element); 69 * } 70 * 71 * <strong>protected E</strong> doRemove(<strong>int</strong> index) { 72 * <strong>return</strong> delegate.remove(index); 73 * } 74 * 75 * </pre> 76 * 77 * @param <E> the type of the elements contained in the List 78 * @see ObservableListBase 79 * @since JavaFX 8.0 80 */ 81 public abstract class ModifiableObservableListBase<E> extends ObservableListBase<E> { 82 83 @Override 84 public boolean setAll(Collection<? extends E> col) { 85 beginChange(); 86 try { 87 clear(); 88 addAll(col); 89 } finally { 90 endChange(); 91 } 92 return true; 93 } 94 95 @Override 96 public boolean addAll(Collection<? extends E> c) { 97 beginChange(); 98 try { 99 boolean res = super.addAll(c); 100 return res; 101 } finally { 102 endChange(); 103 } 104 } 105 106 @Override 107 public boolean addAll(int index, Collection<? extends E> c) { 108 beginChange(); 109 try { 110 boolean res = super.addAll(index, c); 111 return res; 112 } finally { 113 endChange(); 114 } 115 } 116 117 @Override 118 protected void removeRange(int fromIndex, int toIndex) { 119 beginChange(); 120 try { 121 super.removeRange(fromIndex, toIndex); 122 } finally { 123 endChange(); 124 } 125 } 126 127 @Override 128 public boolean removeAll(Collection<?> c) { 129 beginChange(); 130 try { 131 boolean res = super.removeAll(c); 132 return res; 133 } finally { 134 endChange(); 135 } 136 } 137 138 @Override 139 public boolean retainAll(Collection<?> c) { 140 beginChange(); 141 try { 142 boolean res = super.retainAll(c); 143 return res; 144 } finally { 145 endChange(); 146 } 147 } 148 149 @Override 150 public void add(int index, E element) { 151 doAdd(index, element); 152 beginChange(); 153 nextAdd(index, index + 1); 154 ++modCount; 155 endChange(); 156 } 157 158 @Override 159 public E set(int index, E element) { 160 E old = doSet(index, element); 161 beginChange(); 162 nextSet(index, old); 163 endChange(); 164 return old; 165 } 166 167 @Override 168 public boolean remove(Object o) { 169 int i = indexOf(o); 170 if (i != - 1) { 171 remove(i); 172 return true; 173 } 174 return false; 175 } 176 177 @Override 178 public E remove(int index) { 179 E old = doRemove(index); 180 beginChange(); 181 nextRemove(index, old); 182 ++modCount; 183 endChange(); 184 return old; 185 } 186 187 @Override 188 public List<E> subList(int fromIndex, int toIndex) { 189 return new SubObservableList(super.subList(fromIndex, toIndex)); 190 } 191 192 @Override 193 public abstract E get(int index); 194 195 @Override 196 public abstract int size(); 197 198 /** 199 * Adds the {@code element} to the List at the position of {@code index}. 200 * 201 * <p>For the description of possible exceptions, please refer to the documentation 202 * of {@link #add(java.lang.Object) } method. 203 * 204 * @param index the position where to add the element 205 * @param element the element that will be added 206 207 * @throws ClassCastException 208 * @throws NullPointerException 209 * @throws IllegalArgumentException 210 * @throws IndexOutOfBoundsException if the index is out of range 211 * (<tt>index < 0 || index > size()</tt>) 212 */ 213 protected abstract void doAdd(int index, E element); 214 215 /** 216 * Sets the {@code element} in the List at the position of {@code index}. 217 * 218 * <p>For the description of possible exceptions, please refer to the documentation 219 * of {@link #set(int, java.lang.Object) } method. 220 * 221 * @param index the position where to set the element 222 * @param element the element that will be set at the specified position 223 * @return the old element at the specified position 224 * 225 * @throws ClassCastException 226 * @throws NullPointerException 227 * @throws IllegalArgumentException 228 * @throws IndexOutOfBoundsException if the index is out of range 229 * (<tt>index < 0 || index >= size()</tt>) 230 */ 231 protected abstract E doSet(int index, E element); 232 233 /** 234 * Removes the element at position of {@code index}. 235 * 236 * @param index the index of the removed element 237 * @return the removed element 238 * 239 * @throws IndexOutOfBoundsException if the index is out of range 240 * (<tt>index < 0 || index >= size()</tt>) 241 */ 242 protected abstract E doRemove(int index); 243 244 private class SubObservableList implements List<E> { 245 246 public SubObservableList(List<E> sublist) { 247 this.sublist = sublist; 248 } 249 private List<E> sublist; 250 251 @Override 252 public int size() { 253 return sublist.size(); 254 } 255 256 @Override 257 public boolean isEmpty() { 258 return sublist.isEmpty(); 259 } 260 261 @Override 262 public boolean contains(Object o) { 263 return sublist.contains(o); 264 } 265 266 @Override 267 public Iterator<E> iterator() { 268 return sublist.iterator(); 269 } 270 271 @Override 272 public Object[] toArray() { 273 return sublist.toArray(); 274 } 275 276 @Override 277 public <T> T[] toArray(T[] a) { 278 return sublist.toArray(a); 279 } 280 281 @Override 282 public boolean add(E e) { 283 return sublist.add(e); 284 } 285 286 @Override 287 public boolean remove(Object o) { 288 return sublist.remove(o); 289 } 290 291 @Override 292 public boolean containsAll(Collection<?> c) { 293 return sublist.containsAll(c); 294 } 295 296 @Override 297 public boolean addAll(Collection<? extends E> c) { 298 beginChange(); 299 try { 300 boolean res = sublist.addAll(c); 301 return res; 302 } finally { 303 endChange(); 304 } 305 } 306 307 @Override 308 public boolean addAll(int index, Collection<? extends E> c) { 309 beginChange(); 310 try { 311 boolean res = sublist.addAll(index, c); 312 return res; 313 } finally { 314 endChange(); 315 } 316 } 317 318 @Override 319 public boolean removeAll(Collection<?> c) { 320 beginChange(); 321 try { 322 boolean res = sublist.removeAll(c); 323 return res; 324 } finally { 325 endChange(); 326 } 327 } 328 329 @Override 330 public boolean retainAll(Collection<?> c) { 331 beginChange(); 332 try { 333 boolean res = sublist.retainAll(c); 334 return res; 335 } finally { 336 endChange(); 337 } 338 } 339 340 @Override 341 public void clear() { 342 beginChange(); 343 try { 344 sublist.clear(); 345 } finally { 346 endChange(); 347 } 348 } 349 350 @Override 351 public E get(int index) { 352 return sublist.get(index); 353 } 354 355 @Override 356 public E set(int index, E element) { 357 return sublist.set(index, element); 358 } 359 360 @Override 361 public void add(int index, E element) { 362 sublist.add(index, element); 363 } 364 365 @Override 366 public E remove(int index) { 367 return sublist.remove(index); 368 } 369 370 @Override 371 public int indexOf(Object o) { 372 return sublist.indexOf(o); 373 } 374 375 @Override 376 public int lastIndexOf(Object o) { 377 return sublist.lastIndexOf(o); 378 } 379 380 @Override 381 public ListIterator<E> listIterator() { 382 return sublist.listIterator(); 383 } 384 385 @Override 386 public ListIterator<E> listIterator(int index) { 387 return sublist.listIterator(index); 388 } 389 390 @Override 391 public List<E> subList(int fromIndex, int toIndex) { 392 return new SubObservableList(sublist.subList(fromIndex, toIndex)); 393 } 394 395 @Override 396 public boolean equals(Object obj) { 397 return sublist.equals(obj); 398 } 399 400 @Override 401 public int hashCode() { 402 return sublist.hashCode(); 403 } 404 405 @Override 406 public String toString() { 407 return sublist.toString(); 408 } 409 } 410 }