Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.collections; 027 028import com.sun.javafx.collections.ListListenerHelper; 029import com.sun.javafx.collections.MapListenerHelper; 030import com.sun.javafx.collections.SetListenerHelper; 031import java.lang.reflect.Array; 032import java.util.AbstractList; 033import java.util.AbstractMap; 034import java.util.AbstractSet; 035import java.util.ArrayList; 036import java.util.Arrays; 037import java.util.Collection; 038import java.util.Collections; 039import java.util.Comparator; 040import java.util.HashMap; 041import java.util.HashSet; 042import java.util.Iterator; 043import java.util.List; 044import java.util.ListIterator; 045import java.util.Map; 046import java.util.NoSuchElementException; 047import java.util.Random; 048import java.util.Set; 049 050import javafx.beans.InvalidationListener; 051 052import com.sun.javafx.collections.ObservableListWrapper; 053import com.sun.javafx.collections.ObservableMapWrapper; 054import com.sun.javafx.collections.ObservableSetWrapper; 055import com.sun.javafx.collections.MapAdapterChange; 056import com.sun.javafx.collections.ObservableFloatArrayImpl; 057import com.sun.javafx.collections.ObservableIntegerArrayImpl; 058import com.sun.javafx.collections.ObservableSequentialListWrapper; 059import com.sun.javafx.collections.SetAdapterChange; 060import com.sun.javafx.collections.SortableList; 061import com.sun.javafx.collections.SourceAdapterChange; 062import com.sun.javafx.collections.annotations.ReturnsUnmodifiableCollection; 063import java.util.RandomAccess; 064import javafx.beans.Observable; 065import javafx.collections.ListChangeListener.Change; 066import javafx.util.Callback; 067 068/** 069 * Utility class that consists of static methods that are 1:1 copies of java.util.Collections methods. 070 * <br><br> 071 * The wrapper methods (like synchronizedObservableList or emptyObservableList) has exactly the same 072 * functionality as the methods in Collections, with exception that they return ObservableList and are 073 * therefore suitable for methods that require ObservableList on input. 074 * <br><br> 075 * The utility methods are here mainly for performance reasons. All methods are optimized in a way that 076 * they yield only limited number of notifications. On the other hand, java.util.Collections methods 077 * might call "modification methods" on an ObservableList multiple times, resulting in a number of notifications. 078 * 079 */ 080public class FXCollections { 081 /** Not to be instantiated. */ 082 private FXCollections() { } 083 084 /** 085 * Constructs an ObservableList that is backed by the specified list. 086 * Mutation operations on the ObservableList instance will be reported 087 * to observers that have registered on that instance.<br> 088 * Note that mutation operations made directly to the underlying list are 089 * <em>not</em> reported to observers of any ObservableList that 090 * wraps it. 091 * 092 * @param list a concrete List that backs this ObservableList 093 * @return a newly created ObservableList 094 */ 095 public static <E> ObservableList<E> observableList(List<E> list) { 096 if (list == null) { 097 throw new NullPointerException(); 098 } 099 return list instanceof RandomAccess ? new ObservableListWrapper<E>(list) : 100 new ObservableSequentialListWrapper<E>(list); 101 } 102 103 /** 104 * Constructs an ObservableList that is backed by the specified list. 105 * Mutation operations on the ObservableList instance will be reported 106 * to observers that have registered on that instance.<br> 107 * Note that mutation operations made directly to the underlying list are 108 * <em>not</em> reported to observers of any ObservableList that 109 * wraps it. 110 * <br> 111 * This list also reports mutations of the elements in it by using <code>extractor</code>. 112 * Observable objects returned by extractor (applied to each list element) are listened for changes 113 * and transformed into "update" change of ListChangeListener. 114 * 115 * @param list a concrete List that backs this ObservableList 116 * @param extractor element to Observable[] convertor 117 * @since 2.1 118 * @return a newly created ObservableList 119 */ 120 public static <E> ObservableList<E> observableList(List<E> list, Callback<E, Observable[]> extractor) { 121 if (list == null || extractor == null) { 122 throw new NullPointerException(); 123 } 124 return list instanceof RandomAccess ? new ObservableListWrapper<E>(list, extractor) : 125 new ObservableSequentialListWrapper<E>(list, extractor); 126 } 127 128 /** 129 * Constructs an ObservableMap that is backed by the specified map. 130 * Mutation operations on the ObservableMap instance will be reported 131 * to observers that have registered on that instance.<br> 132 * Note that mutation operations made directly to the underlying map are <em>not</em> 133 * reported to observers of any ObservableMap that wraps it. 134 * @param map a Map that backs this ObservableMap 135 * @return a newly created ObservableMap 136 */ 137 public static <K, V> ObservableMap<K, V> observableMap(Map<K, V> map) { 138 if (map == null) { 139 throw new NullPointerException(); 140 } 141 return new ObservableMapWrapper<K, V>(map); 142 } 143 144 /** 145 * Constructs an ObservableSet that is backed by the specified set. 146 * Mutation operations on the ObservableSet instance will be reported 147 * to observers that have registered on that instance.<br> 148 * Note that mutation operations made directly to the underlying set are <em>not</em> 149 * reported to observers of any ObservableSet that wraps it. 150 * @param set a Set that backs this ObservableSet 151 * @return a newly created ObservableSet 152 */ 153 public static <E> ObservableSet<E> observableSet(Set<E> set) { 154 if (set == null) { 155 throw new NullPointerException(); 156 } 157 return new ObservableSetWrapper<E>(set); 158 } 159 160 /** 161 * Constructs an ObservableSet that contains all the specified elements. 162 * @param elements elements that will be added into returned ObservableSet 163 * @return a newly created ObservableSet 164 */ 165 public static <E> ObservableSet<E> observableSet(E... elements) { 166 if (elements == null) { 167 throw new NullPointerException(); 168 } 169 Set<E> set = new HashSet<E>(elements.length); 170 Collections.addAll(set, elements); 171 return new ObservableSetWrapper<E>(set); 172 } 173 174 /** 175 * Constructs a read-only interface to the specified ObservableMap. Only 176 * mutation operations made to the underlying ObservableMap will be reported 177 * to observers that have registered on the unmodifiable instance. This allows 178 * clients to track changes in a Map but disallows the ability to modify it. 179 * @param map an ObservableMap that is to be monitored by this interface 180 * @return a newly created UnmodifiableObservableMap 181 */ 182 @ReturnsUnmodifiableCollection 183 public static <K, V> ObservableMap<K, V> unmodifiableObservableMap(ObservableMap<K, V> map) { 184 if (map == null) { 185 throw new NullPointerException(); 186 } 187 return new com.sun.javafx.collections.UnmodifiableObservableMap<K, V>(map); 188 } 189 190 /** 191 * Creates and returns a typesafe wrapper on top of provided observable map. 192 * @param map an Observable map to be wrapped 193 * @param keyType the type of key that {@code map} is permitted to hold 194 * @param valueType the type of value that {@code map} is permitted to hold 195 * @return a dynamically typesafe view of the specified map 196 * @see Collections#checkedMap(java.util.Map, java.lang.Class) 197 */ 198 public static <K, V> ObservableMap<K, V> checkedObservableMap(ObservableMap<K, V> map, Class<K> keyType, Class<V> valueType) { 199 if (map == null || keyType == null || valueType == null) { 200 throw new NullPointerException(); 201 } 202 return new CheckedObservableMap<K, V>(map, keyType, valueType); 203 } 204 205 /** 206 * Creates and returns a synchronized wrapper on top of provided observable map. 207 * @param map the map to be "wrapped" in a synchronized map. 208 * @return A synchronized version of the observable map 209 * @see Collections#synchronizedMap(java.util.Map) 210 */ 211 public static <K, V> ObservableMap<K, V> synchronizedObservableMap(ObservableMap<K, V> map) { 212 if (map == null) { 213 throw new NullPointerException(); 214 } 215 return new SynchronizedObservableMap<K, V>(map); 216 } 217 218 private static ObservableMap EMPTY_OBSERVABLE_MAP = new EmptyObservableMap(); 219 220 /** 221 * Creates and empty unmodifiable observable map. 222 * @return An empty unmodifiable observable map 223 * @see Collections#emptyMap() 224 */ 225 @SuppressWarnings("unchecked") 226 @ReturnsUnmodifiableCollection 227 public static <K, V> ObservableMap<K, V> emptyObservableMap() { 228 return EMPTY_OBSERVABLE_MAP; 229 } 230 231 /** 232 * Creates a new empty observable integer array. 233 * @return a newly created ObservableIntegerArray 234 */ 235 public static ObservableIntegerArray observableIntegerArray() { 236 return new ObservableIntegerArrayImpl(); 237 } 238 239 /** 240 * Creates a new observable integer array with {@code values} set to it. 241 * @param values the values that will be in the new observable integer array 242 * @return a newly created ObservableIntegerArray 243 */ 244 public static ObservableIntegerArray observableIntegerArray(int... values) { 245 return new ObservableIntegerArrayImpl(values); 246 } 247 248 /** 249 * Creates a new observable integer array with copy of elements in given 250 * {@code array}. 251 * @param array observable integer array to copy 252 * @return a newly created ObservableIntegerArray 253 */ 254 public static ObservableIntegerArray observableIntegerArray(ObservableIntegerArray array) { 255 return new ObservableIntegerArrayImpl(array); 256 } 257 258 /** 259 * Creates a new empty observable float array. 260 * @return a newly created ObservableFloatArray 261 */ 262 public static ObservableFloatArray observableFloatArray() { 263 return new ObservableFloatArrayImpl(); 264 } 265 266 /** 267 * Creates a new observable float array with {@code values} set to it. 268 * @param values the values that will be in the new observable float array 269 * @return a newly created ObservableFloatArray 270 */ 271 public static ObservableFloatArray observableFloatArray(float... values) { 272 return new ObservableFloatArrayImpl(values); 273 } 274 275 /** 276 * Creates a new observable float array with copy of elements in given 277 * {@code array}. 278 * @param array observable float array to copy 279 * @return a newly created ObservableFloatArray 280 */ 281 public static ObservableFloatArray observableFloatArray(ObservableFloatArray array) { 282 return new ObservableFloatArrayImpl(array); 283 } 284 285 /** 286 * Creates a new empty observable list that is backed by an arraylist. 287 * @see #observableList(java.util.List) 288 * @return a newly created ObservableList 289 */ 290 @SuppressWarnings("unchecked") 291 public static <E> ObservableList<E> observableArrayList() { 292 return observableList(new ArrayList()); 293 } 294 295 /** 296 * Creates a new empty observable list backed by an arraylist. 297 * 298 * This list reports element updates. 299 * @param extractor element to Observable[] convertor. Observable objects are listened for changes on the element. 300 * @see #observableList(java.util.List, javafx.util.Callback) 301 * @since 2.1 302 * @return a newly created ObservableList 303 */ 304 public static <E> ObservableList<E> observableArrayList(Callback<E, Observable[]> extractor) { 305 return observableList(new ArrayList(), extractor); 306 } 307 308 /** 309 * Creates a new observable array list with {@code items} added to it. 310 * @return a newly created observableArrayList 311 * @param items the items that will be in the new observable ArrayList 312 * @see #observableArrayList() 313 */ 314 public static <E> ObservableList<E> observableArrayList(E... items) { 315 ObservableList<E> list = observableArrayList(); 316 list.addAll(items); 317 return list; 318 } 319 320 /** 321 * Creates a new observable array list and adds a content of collection {@code col} 322 * to it. 323 * @param col a collection which content should be added to the observableArrayList 324 * @return a newly created observableArrayList 325 */ 326 public static <E> ObservableList<E> observableArrayList(Collection<? extends E> col) { 327 ObservableList<E> list = observableArrayList(); 328 list.addAll(col); 329 return list; 330 } 331 332 /** 333 * Creates a new empty observable map that is backed by a HashMap. 334 * @param <K> the type of keys 335 * @param <V> the type of values 336 * @return a newly created observable HashMap 337 */ 338 public static <K,V> ObservableMap<K,V> observableHashMap() { 339 return observableMap(new HashMap<K, V>()); 340 } 341 342 /** 343 * Concatenates more observable lists into one. The resulting list 344 * would be backed by an arraylist. 345 * @param lists lists to concatenate 346 * @return new observable array list concatenated from the arguments 347 */ 348 public static <E> ObservableList<E> concat(ObservableList<E>... lists) { 349 if (lists.length == 0 ) { 350 return observableArrayList(); 351 } 352 if (lists.length == 1) { 353 return observableArrayList(lists[0]); 354 } 355 ArrayList<E> backingList = new ArrayList<E>(); 356 for (ObservableList<E> s : lists) { 357 backingList.addAll(s); 358 } 359 360 return observableList(backingList); 361 } 362 363 /** 364 * Creates and returns unmodifiable wrapper list on top of provided observable list. 365 * @param list an ObservableList that is to be wrapped 366 * @return an ObserableList wrapper that is unmodifiable 367 * @see Collections#unmodifiableList(java.util.List) 368 */ 369 @ReturnsUnmodifiableCollection 370 public static<E> ObservableList<E> unmodifiableObservableList(ObservableList<E> list) { 371 if (list == null) { 372 throw new NullPointerException(); 373 } 374 return new UnmodifiableObservableListImpl<E>(list); 375 } 376 377 /** 378 * Creates and returns a typesafe wrapper on top of provided observable list. 379 * @param list an Observable list to be wrapped 380 * @param type the type of element that <tt>list</tt> is permitted to hold 381 * @return a dynamically typesafe view of the specified list 382 * @see Collections#checkedList(java.util.List, java.lang.Class) 383 */ 384 public static<E> ObservableList<E> checkedObservableList(ObservableList<E> list, Class<E> type) { 385 if (list == null) { 386 throw new NullPointerException(); 387 } 388 return new CheckedObservableList<E>(list, type); 389 } 390 391 /** 392 * Creates and returns a synchronized wrapper on top of provided observable list. 393 * @param list the list to be "wrapped" in a synchronized list. 394 * @return A synchronized version of the observable list 395 * @see Collections#synchronizedList(java.util.List) 396 */ 397 public static<E> ObservableList<E> synchronizedObservableList(ObservableList<E> list) { 398 if (list == null) { 399 throw new NullPointerException(); 400 } 401 return new SynchronizedObservableList<E>(list); 402 } 403 404 private static ObservableList EMPTY_OBSERVABLE_LIST = new EmptyObservableList(); 405 406 407 /** 408 * Creates and empty unmodifiable observable list. 409 * @return An empty unmodifiable observable list 410 * @see Collections#emptyList() 411 */ 412 @SuppressWarnings("unchecked") 413 @ReturnsUnmodifiableCollection 414 public static<E> ObservableList<E> emptyObservableList() { 415 return EMPTY_OBSERVABLE_LIST; 416 } 417 418 /** 419 * Creates an unmodifiable observable list with single element. 420 * @param e the only elements that will be contained in this singleton observable list 421 * @return a singleton observable list 422 * @see Collections#singletonList(java.lang.Object) 423 */ 424 @ReturnsUnmodifiableCollection 425 public static<E> ObservableList<E> singletonObservableList(E e) { 426 return new SingletonObservableList<E>(e); 427 } 428 429 /** 430 * Creates and returns unmodifiable wrapper on top of provided observable set. 431 * @param set an ObservableSet that is to be wrapped 432 * @return an ObserableSet wrapper that is unmodifiable 433 * @see Collections#unmodifiableSet(java.util.Set) 434 */ 435 @ReturnsUnmodifiableCollection 436 public static<E> ObservableSet<E> unmodifiableObservableSet(ObservableSet<E> set) { 437 if (set == null) { 438 throw new NullPointerException(); 439 } 440 return new UnmodifiableObservableSet<E>(set); 441 } 442 443 /** 444 * Creates and returns a typesafe wrapper on top of provided observable set. 445 * @param set an Observable set to be wrapped 446 * @param type the type of element that <tt>set</tt> is permitted to hold 447 * @return a dynamically typesafe view of the specified set 448 * @see Collections#checkedSet(java.util.Set, java.lang.Class) 449 */ 450 public static<E> ObservableSet<E> checkedObservableSet(ObservableSet<E> set, Class<E> type) { 451 if (set == null) { 452 throw new NullPointerException(); 453 } 454 return new CheckedObservableSet<E>(set, type); 455 } 456 457 /** 458 * Creates and returns a synchronized wrapper on top of provided observable set. 459 * @param set the set to be "wrapped" in a synchronized set. 460 * @return A synchronized version of the observable set 461 * @see Collections#synchronizedSet(java.util.Set) 462 */ 463 public static<E> ObservableSet<E> synchronizedObservableSet(ObservableSet<E> set) { 464 if (set == null) { 465 throw new NullPointerException(); 466 } 467 return new SynchronizedObservableSet<E>(set); 468 } 469 470 private static ObservableSet EMPTY_OBSERVABLE_SET = new EmptyObservableSet(); 471 472 /** 473 * Creates and empty unmodifiable observable set. 474 * @return An empty unmodifiable observable set 475 * @see Collections#emptySet() 476 */ 477 @SuppressWarnings("unchecked") 478 @ReturnsUnmodifiableCollection 479 public static<E> ObservableSet<E> emptyObservableSet() { 480 return EMPTY_OBSERVABLE_SET; 481 } 482 483 /** 484 * Copies elements from src to dest. Fires only <b>one</b> change notification on dest. 485 * @param dest the destination observable list 486 * @param src the source list 487 * @see Collections#copy(java.util.List, java.util.List) 488 */ 489 @SuppressWarnings("unchecked") 490 public static <T> void copy(ObservableList<? super T> dest, List<? extends T> src) { 491 final int srcSize = src.size(); 492 if (srcSize > dest.size()) { 493 throw new IndexOutOfBoundsException("Source does not fit in dest"); 494 } 495 T[] destArray = (T[]) dest.toArray(); 496 System.arraycopy(src.toArray(), 0, destArray, 0, srcSize); 497 dest.setAll(destArray); 498 } 499 500 /** 501 * Fills the provided list with obj. Fires only <b>one</b> change notification on the list. 502 * @param list the list to fill 503 * @param obj the object to fill the list with 504 * @see Collections#fill(java.util.List, java.lang.Object) 505 */ 506 @SuppressWarnings("unchecked") 507 public static <T> void fill(ObservableList<? super T> list, T obj) { 508 T[] newContent = (T[]) new Object[list.size()]; 509 Arrays.fill(newContent, obj); 510 list.setAll(newContent); 511 } 512 513 /** 514 * Replace all oldVal elements in the list with newVal element. 515 * Fires only <b>one</b> change notification on the list. 516 * @param list the list which will have it's elements replaced 517 * @param oldVal the element that is going to be replace 518 * @param newVal the replacement 519 * @return true if the list was modified 520 * @see Collections#replaceAll(java.util.List, java.lang.Object, java.lang.Object) 521 */ 522 @SuppressWarnings("unchecked") 523 public static <T> boolean replaceAll(ObservableList<T> list, T oldVal, T newVal) { 524 T[] newContent = (T[]) list.toArray(); 525 boolean modified = false; 526 for (int i = 0 ; i < newContent.length; ++i) { 527 if (newContent[i].equals(oldVal)) { 528 newContent[i] = newVal; 529 modified = true; 530 } 531 } 532 if (modified) { 533 list.setAll(newContent); 534 } 535 return modified; 536 } 537 538 /** 539 * Reverse the order in the list 540 * Fires only <b>one</b> change notification on the list. 541 * @param list the list to be reversed 542 * @see Collections#reverse(java.util.List) 543 */ 544 @SuppressWarnings("unchecked") 545 public static void reverse(ObservableList list) { 546 Object[] newContent = list.toArray(); 547 for (int i = 0; i < newContent.length / 2; ++i) { 548 Object tmp = newContent[i]; 549 newContent[i] = newContent[newContent.length - i - 1]; 550 newContent[newContent.length -i - 1] = tmp; 551 } 552 list.setAll(newContent); 553 } 554 555 /** 556 * Rotates the list by distance. 557 * Fires only <b>one</b> change notification on the list. 558 * @param list the list to be rotated 559 * @param distance the distance of rotation 560 * @see Collections#rotate(java.util.List, int) 561 */ 562 @SuppressWarnings("unchecked") 563 public static void rotate(ObservableList list, int distance) { 564 Object[] newContent = list.toArray(); 565 566 int size = list.size(); 567 distance = distance % size; 568 if (distance < 0) 569 distance += size; 570 if (distance == 0) 571 return; 572 573 for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) { 574 Object displaced = newContent[cycleStart]; 575 Object tmp; 576 int i = cycleStart; 577 do { 578 i += distance; 579 if (i >= size) 580 i -= size; 581 tmp = newContent[i]; 582 newContent[i] = displaced; 583 displaced = tmp; 584 nMoved ++; 585 } while(i != cycleStart); 586 } 587 list.setAll(newContent); 588 } 589 590 /** 591 * Shuffles all elements in the observable list. 592 * Fires only <b>one</b> change notification on the list. 593 * @param list the list to shuffle 594 * @see Collections#shuffle(java.util.List) 595 */ 596 public static void shuffle(ObservableList<?> list) { 597 if (r == null) { 598 r = new Random(); 599 } 600 shuffle(list, r); 601 } 602 private static Random r; 603 604 /** 605 * Shuffles all elements in the observable list. 606 * Fires only <b>one</b> change notification on the list. 607 * @param list the list to be shuffled 608 * @param rnd the random generator used for shuffling 609 * @see Collections#shuffle(java.util.List, java.util.Random) 610 */ 611 @SuppressWarnings("unchecked") 612 public static void shuffle(ObservableList list, Random rnd) { 613 Object newContent[] = list.toArray(); 614 615 for (int i = list.size(); i > 1; i--) { 616 swap(newContent, i - 1, rnd.nextInt(i)); 617 } 618 619 list.setAll(newContent); 620 } 621 622 private static void swap(Object[] arr, int i, int j) { 623 Object tmp = arr[i]; 624 arr[i] = arr[j]; 625 arr[j] = tmp; 626 } 627 628 /** 629 * Sorts the provided observable list. 630 * Fires only <b>one</b> change notification on the list. 631 * @see Collections#sort(java.util.List) 632 */ 633 @SuppressWarnings("unchecked") 634 public static <T extends Comparable<? super T>> void sort(ObservableList<T> list) { 635 if (list instanceof SortableList) { 636 ((SortableList<? extends T>)list).sort(); 637 } else { 638 List<T> newContent = new ArrayList<T>(list); 639 Collections.sort(newContent); 640 list.setAll((Collection<T>)newContent); 641 } 642 } 643 644 /** 645 * Sorts the provided observable list using the c comparator. 646 * Fires only <b>one</b> change notification on the list. 647 * @param list the list to sort 648 * @param c comparator used for sorting. Null if natural ordering is required. 649 * @see Collections#sort(java.util.List, java.util.Comparator) 650 */ 651 @SuppressWarnings("unchecked") 652 public static <T> void sort(ObservableList<T> list, Comparator<? super T> c) { 653 if (list instanceof SortableList) { 654 ((SortableList<? extends T>)list).sort(c); 655 } else { 656 List<T> newContent = new ArrayList<T>(list); 657 Collections.sort(newContent, c); 658 list.setAll((Collection<T>)newContent); 659 } 660 } 661 662 private static class EmptyObservableList<E> extends AbstractList<E> implements ObservableList<E> { 663 664 private static final ListIterator iterator = new ListIterator() { 665 666 @Override 667 public boolean hasNext() { 668 return false; 669 } 670 671 @Override 672 public Object next() { 673 throw new NoSuchElementException(); 674 } 675 676 @Override 677 public void remove() { 678 throw new UnsupportedOperationException(); 679 } 680 681 @Override 682 public boolean hasPrevious() { 683 return false; 684 } 685 686 @Override 687 public Object previous() { 688 throw new NoSuchElementException(); 689 } 690 691 @Override 692 public int nextIndex() { 693 return 0; 694 } 695 696 @Override 697 public int previousIndex() { 698 return -1; 699 } 700 701 @Override 702 public void set(Object e) { 703 throw new UnsupportedOperationException(); 704 } 705 706 @Override 707 public void add(Object e) { 708 throw new UnsupportedOperationException(); 709 } 710 }; 711 712 public EmptyObservableList() { 713 } 714 715 @Override 716 public final void addListener(InvalidationListener listener) { 717 } 718 719 @Override 720 public final void removeListener(InvalidationListener listener) { 721 } 722 723 724 @Override 725 public void addListener(ListChangeListener<? super E> o) { 726 } 727 728 @Override 729 public void removeListener(ListChangeListener<? super E> o) { 730 } 731 732 @Override 733 public int size() { 734 return 0; 735 } 736 737 @Override 738 public boolean contains(Object o) { 739 return false; 740 } 741 742 @Override 743 @SuppressWarnings("unchecked") 744 public Iterator<E> iterator() { 745 return iterator; 746 } 747 748 @Override 749 public boolean containsAll(Collection<?> c) { 750 return c.isEmpty(); 751 } 752 753 @Override 754 public E get(int index) { 755 throw new IndexOutOfBoundsException(); 756 } 757 758 @Override 759 public int indexOf(Object o) { 760 return -1; 761 } 762 763 @Override 764 public int lastIndexOf(Object o) { 765 return -1; 766 } 767 768 @Override 769 @SuppressWarnings("unchecked") 770 public ListIterator<E> listIterator() { 771 return iterator; 772 } 773 774 @Override 775 @SuppressWarnings("unchecked") 776 public ListIterator<E> listIterator(int index) { 777 if (index != 0) { 778 throw new IndexOutOfBoundsException(); 779 } 780 return iterator; 781 } 782 783 @Override 784 public List<E> subList(int fromIndex, int toIndex) { 785 if (fromIndex != 0 || toIndex != 0) { 786 throw new IndexOutOfBoundsException(); 787 } 788 return this; 789 } 790 791 @Override 792 public boolean addAll(E... elements) { 793 throw new UnsupportedOperationException(); 794 } 795 796 @Override 797 public boolean setAll(E... elements) { 798 throw new UnsupportedOperationException(); 799 } 800 801 @Override 802 public boolean setAll(Collection<? extends E> col) { 803 throw new UnsupportedOperationException(); 804 } 805 806 @Override 807 public boolean removeAll(E... elements) { 808 throw new UnsupportedOperationException(); 809 } 810 811 @Override 812 public boolean retainAll(E... elements) { 813 throw new UnsupportedOperationException(); 814 } 815 816 @Override 817 public void remove(int from, int to) { 818 throw new UnsupportedOperationException(); 819 } 820 } 821 822 private static class SingletonObservableList<E> extends AbstractList<E> implements ObservableList<E> { 823 824 private final E element; 825 826 public SingletonObservableList(E element) { 827 if (element == null) { 828 throw new NullPointerException(); 829 } 830 this.element = element; 831 } 832 833 @Override 834 public boolean addAll(E... elements) { 835 throw new UnsupportedOperationException(); 836 } 837 838 @Override 839 public boolean setAll(E... elements) { 840 throw new UnsupportedOperationException(); 841 } 842 843 @Override 844 public boolean setAll(Collection<? extends E> col) { 845 throw new UnsupportedOperationException(); 846 } 847 848 @Override 849 public boolean removeAll(E... elements) { 850 throw new UnsupportedOperationException(); 851 } 852 853 @Override 854 public boolean retainAll(E... elements) { 855 throw new UnsupportedOperationException(); 856 } 857 858 @Override 859 public void remove(int from, int to) { 860 throw new UnsupportedOperationException(); 861 } 862 863 @Override 864 public void addListener(InvalidationListener listener) { 865 } 866 867 @Override 868 public void removeListener(InvalidationListener listener) { 869 } 870 871 @Override 872 public void addListener(ListChangeListener<? super E> o) { 873 } 874 875 @Override 876 public void removeListener(ListChangeListener<? super E> o) { 877 } 878 879 @Override 880 public int size() { 881 return 1; 882 } 883 884 @Override 885 public boolean isEmpty() { 886 return false; 887 } 888 889 @Override 890 public boolean contains(Object o) { 891 return element.equals(o); 892 } 893 894 @Override 895 public E get(int index) { 896 if (index != 0) { 897 throw new IndexOutOfBoundsException(); 898 } 899 return element; 900 } 901 902 } 903 904 private static class UnmodifiableObservableListImpl<T> extends ObservableListBase<T> implements ObservableList<T> { 905 906 private final ObservableList<T> backingList; 907 private final ListChangeListener<T> listener; 908 909 public UnmodifiableObservableListImpl(ObservableList<T> backingList) { 910 this.backingList = backingList; 911 listener = new ListChangeListener<T>() { 912 913 @Override 914 public void onChanged(Change<? extends T> c) { 915 fireChange(new SourceAdapterChange<T>(UnmodifiableObservableListImpl.this, c)); 916 } 917 }; 918 this.backingList.addListener(new WeakListChangeListener<T>(listener)); 919 } 920 921 @Override 922 public T get(int index) { 923 return backingList.get(index); 924 } 925 926 @Override 927 public int size() { 928 return backingList.size(); 929 } 930 931 @Override 932 public boolean addAll(T... elements) { 933 throw new UnsupportedOperationException(); 934 } 935 936 @Override 937 public boolean setAll(T... elements) { 938 throw new UnsupportedOperationException(); 939 } 940 941 @Override 942 public boolean setAll(Collection<? extends T> col) { 943 throw new UnsupportedOperationException(); 944 } 945 946 @Override 947 public boolean removeAll(T... elements) { 948 throw new UnsupportedOperationException(); 949 } 950 951 @Override 952 public boolean retainAll(T... elements) { 953 throw new UnsupportedOperationException(); 954 } 955 956 @Override 957 public void remove(int from, int to) { 958 throw new UnsupportedOperationException(); 959 } 960 961 } 962 963 private static class SynchronizedList<T> implements List<T> { 964 final Object mutex; 965 private final List<T> backingList; 966 967 SynchronizedList(List<T> list, Object mutex) { 968 this.backingList = list; 969 this.mutex = mutex; 970 } 971 972 SynchronizedList(List<T> seq) { 973 this (seq, new Object()); 974 } 975 976 977 @Override 978 public int size() { 979 synchronized(mutex) { 980 return backingList.size(); 981 } 982 } 983 984 @Override 985 public boolean isEmpty() { 986 synchronized(mutex) { 987 return backingList.isEmpty(); 988 } 989 } 990 991 @Override 992 public boolean contains(Object o) { 993 synchronized(mutex) { 994 return backingList.contains(o); 995 } 996 } 997 998 @Override 999 public Iterator<T> iterator() { 1000 return backingList.iterator(); 1001 } 1002 1003 @Override 1004 public Object[] toArray() { 1005 synchronized(mutex) { 1006 return backingList.toArray(); 1007 } 1008 } 1009 1010 @Override 1011 public <T> T[] toArray(T[] a) { 1012 synchronized(mutex) { 1013 return backingList.toArray(a); 1014 } 1015 } 1016 1017 @Override 1018 public boolean add(T e) { 1019 synchronized(mutex) { 1020 return backingList.add(e); 1021 } 1022 } 1023 1024 @Override 1025 public boolean remove(Object o) { 1026 synchronized(mutex) { 1027 return backingList.remove(o); 1028 } 1029 } 1030 1031 @Override 1032 public boolean containsAll(Collection<?> c) { 1033 synchronized(mutex) { 1034 return backingList.containsAll(c); 1035 } 1036 } 1037 1038 @Override 1039 public boolean addAll(Collection<? extends T> c) { 1040 synchronized(mutex) { 1041 return backingList.addAll(c); 1042 } 1043 } 1044 1045 @Override 1046 public boolean addAll(int index, Collection<? extends T> c) { 1047 synchronized(mutex) { 1048 return backingList.addAll(index, c); 1049 1050 } 1051 } 1052 1053 @Override 1054 public boolean removeAll(Collection<?> c) { 1055 synchronized(mutex) { 1056 return backingList.removeAll(c); 1057 } 1058 } 1059 1060 @Override 1061 public boolean retainAll(Collection<?> c) { 1062 synchronized(mutex) { 1063 return backingList.retainAll(c); 1064 } 1065 } 1066 1067 @Override 1068 public void clear() { 1069 synchronized(mutex) { 1070 backingList.clear(); 1071 } 1072 } 1073 1074 @Override 1075 public T get(int index) { 1076 synchronized(mutex) { 1077 return backingList.get(index); 1078 } 1079 } 1080 1081 @Override 1082 public T set(int index, T element) { 1083 synchronized(mutex) { 1084 return backingList.set(index, element); 1085 } 1086 } 1087 1088 @Override 1089 public void add(int index, T element) { 1090 synchronized(mutex) { 1091 backingList.add(index, element); 1092 } 1093 } 1094 1095 @Override 1096 public T remove(int index) { 1097 synchronized(mutex) { 1098 return backingList.remove(index); 1099 } 1100 } 1101 1102 @Override 1103 public int indexOf(Object o) { 1104 synchronized(mutex) { 1105 return backingList.indexOf(o); 1106 } 1107 } 1108 1109 @Override 1110 public int lastIndexOf(Object o) { 1111 synchronized(mutex) { 1112 return backingList.lastIndexOf(o); 1113 } 1114 } 1115 1116 @Override 1117 public ListIterator<T> listIterator() { 1118 return backingList.listIterator(); 1119 } 1120 1121 @Override 1122 public ListIterator<T> listIterator(int index) { 1123 synchronized(mutex) { 1124 return backingList.listIterator(index); 1125 } 1126 } 1127 1128 @Override 1129 public List<T> subList(int fromIndex, int toIndex) { 1130 synchronized(mutex) { 1131 return new SynchronizedList<T>(backingList.subList(fromIndex, toIndex), 1132 mutex); 1133 } 1134 } 1135 1136 @Override 1137 public String toString() { 1138 synchronized(mutex) { 1139 return backingList.toString(); 1140 } 1141 } 1142 1143 @Override 1144 public int hashCode() { 1145 synchronized(mutex) { 1146 return backingList.hashCode(); 1147 } 1148 } 1149 1150 @Override 1151 public boolean equals(Object o) { 1152 synchronized(mutex) { 1153 return backingList.equals(o); 1154 } 1155 } 1156 1157 } 1158 1159 private static class SynchronizedObservableList<T> extends SynchronizedList<T> implements ObservableList<T> { 1160 1161 private ListListenerHelper helper; 1162 1163 private final ObservableList<T> backingList; 1164 private final ListChangeListener<T> listener; 1165 1166 SynchronizedObservableList(ObservableList<T> seq, Object mutex) { 1167 super(seq, mutex); 1168 this.backingList = seq; 1169 listener = new ListChangeListener<T>() { 1170 1171 @Override 1172 public void onChanged(Change<? extends T> c) { 1173 ListListenerHelper.fireValueChangedEvent(helper, new SourceAdapterChange<T>(SynchronizedObservableList.this, c)); 1174 } 1175 }; 1176 backingList.addListener(new WeakListChangeListener<T>(listener)); 1177 } 1178 1179 SynchronizedObservableList(ObservableList<T> seq) { 1180 this(seq, new Object()); 1181 } 1182 1183 @Override 1184 public boolean addAll(T... elements) { 1185 synchronized(mutex) { 1186 return backingList.addAll(elements); 1187 } 1188 } 1189 1190 @Override 1191 public boolean setAll(T... elements) { 1192 synchronized(mutex) { 1193 return backingList.setAll(elements); 1194 } 1195 } 1196 1197 @Override 1198 public boolean removeAll(T... elements) { 1199 synchronized(mutex) { 1200 return backingList.removeAll(elements); 1201 } 1202 } 1203 1204 @Override 1205 public boolean retainAll(T... elements) { 1206 synchronized(mutex) { 1207 return backingList.retainAll(elements); 1208 } 1209 } 1210 1211 @Override 1212 public void remove(int from, int to) { 1213 synchronized(mutex) { 1214 backingList.remove(from, to); 1215 } 1216 } 1217 1218 @Override 1219 public boolean setAll(Collection<? extends T> col) { 1220 synchronized(mutex) { 1221 return backingList.setAll(col); 1222 } 1223 } 1224 1225 @Override 1226 public final void addListener(InvalidationListener listener) { 1227 helper = ListListenerHelper.addListener(helper, listener); 1228 } 1229 1230 @Override 1231 public final void removeListener(InvalidationListener listener) { 1232 helper = ListListenerHelper.removeListener(helper, listener); 1233 } 1234 1235 @Override 1236 public void addListener(ListChangeListener<? super T> listener) { 1237 helper = ListListenerHelper.addListener(helper, listener); 1238 } 1239 1240 @Override 1241 public void removeListener(ListChangeListener<? super T> listener) { 1242 helper = ListListenerHelper.removeListener(helper, listener); 1243 } 1244 1245 1246 } 1247 1248 private static class CheckedObservableList<T> extends ObservableListBase<T> implements ObservableList<T> { 1249 1250 private final ObservableList<T> list; 1251 private final Class<T> type; 1252 private final ListChangeListener<T> listener; 1253 1254 CheckedObservableList(ObservableList<T> list, Class<T> type) { 1255 if (list == null || type == null) { 1256 throw new NullPointerException(); 1257 } 1258 this.list = list; 1259 this.type = type; 1260 listener = new ListChangeListener<T>() { 1261 1262 @Override 1263 public void onChanged(Change<? extends T> c) { 1264 fireChange(new SourceAdapterChange<T>(CheckedObservableList.this, c)); 1265 } 1266 }; 1267 list.addListener(new WeakListChangeListener<T>(listener)); 1268 } 1269 1270 void typeCheck(Object o) { 1271 if (o != null && !type.isInstance(o)) { 1272 throw new ClassCastException("Attempt to insert " 1273 + o.getClass() + " element into collection with element type " 1274 + type); 1275 } 1276 } 1277 1278 @Override 1279 public int size() { 1280 return list.size(); 1281 } 1282 1283 @Override 1284 public boolean isEmpty() { 1285 return list.isEmpty(); 1286 } 1287 1288 @Override 1289 public boolean contains(Object o) { 1290 return list.contains(o); 1291 } 1292 1293 @Override 1294 public Object[] toArray() { 1295 return list.toArray(); 1296 } 1297 1298 @Override 1299 public <T> T[] toArray(T[] a) { 1300 return list.toArray(a); 1301 } 1302 1303 @Override 1304 public String toString() { 1305 return list.toString(); 1306 } 1307 1308 @Override 1309 public boolean remove(Object o) { 1310 return list.remove(o); 1311 } 1312 1313 @Override 1314 public boolean containsAll(Collection<?> coll) { 1315 return list.containsAll(coll); 1316 } 1317 1318 @Override 1319 public boolean removeAll(Collection<?> coll) { 1320 return list.removeAll(coll); 1321 } 1322 1323 @Override 1324 public boolean retainAll(Collection<?> coll) { 1325 return list.retainAll(coll); 1326 } 1327 1328 @Override 1329 public boolean removeAll(T... elements) { 1330 return list.removeAll(elements); 1331 } 1332 1333 @Override 1334 public boolean retainAll(T... elements) { 1335 return list.retainAll(elements); 1336 } 1337 1338 @Override 1339 public void remove(int from, int to) { 1340 list.remove(from, to); 1341 } 1342 1343 @Override 1344 public void clear() { 1345 list.clear(); 1346 } 1347 1348 @Override 1349 public boolean equals(Object o) { 1350 return o == this || list.equals(o); 1351 } 1352 1353 @Override 1354 public int hashCode() { 1355 return list.hashCode(); 1356 } 1357 1358 @Override 1359 public T get(int index) { 1360 return list.get(index); 1361 } 1362 1363 @Override 1364 public T remove(int index) { 1365 return list.remove(index); 1366 } 1367 1368 @Override 1369 public int indexOf(Object o) { 1370 return list.indexOf(o); 1371 } 1372 1373 @Override 1374 public int lastIndexOf(Object o) { 1375 return list.lastIndexOf(o); 1376 } 1377 1378 @Override 1379 public T set(int index, T element) { 1380 typeCheck(element); 1381 return list.set(index, element); 1382 } 1383 1384 @Override 1385 public void add(int index, T element) { 1386 typeCheck(element); 1387 list.add(index, element); 1388 } 1389 1390 @Override 1391 @SuppressWarnings("unchecked") 1392 public boolean addAll(int index, Collection<? extends T> c) { 1393 T[] a = null; 1394 try { 1395 a = c.toArray((T[]) Array.newInstance(type, 0)); 1396 } catch (ArrayStoreException e) { 1397 throw new ClassCastException(); 1398 } 1399 1400 return this.list.addAll(index, Arrays.asList(a)); 1401 } 1402 1403 @Override 1404 @SuppressWarnings("unchecked") 1405 public boolean addAll(Collection<? extends T> coll) { 1406 T[] a = null; 1407 try { 1408 a = coll.toArray((T[]) Array.newInstance(type, 0)); 1409 } catch (ArrayStoreException e) { 1410 throw new ClassCastException(); 1411 } 1412 1413 return this.list.addAll(Arrays.asList(a)); 1414 } 1415 1416 @Override 1417 public ListIterator<T> listIterator() { 1418 return listIterator(0); 1419 } 1420 1421 @Override 1422 public ListIterator<T> listIterator(final int index) { 1423 return new ListIterator<T>() { 1424 1425 ListIterator<T> i = list.listIterator(index); 1426 1427 @Override 1428 public boolean hasNext() { 1429 return i.hasNext(); 1430 } 1431 1432 @Override 1433 public T next() { 1434 return i.next(); 1435 } 1436 1437 @Override 1438 public boolean hasPrevious() { 1439 return i.hasPrevious(); 1440 } 1441 1442 @Override 1443 public T previous() { 1444 return i.previous(); 1445 } 1446 1447 @Override 1448 public int nextIndex() { 1449 return i.nextIndex(); 1450 } 1451 1452 @Override 1453 public int previousIndex() { 1454 return i.previousIndex(); 1455 } 1456 1457 @Override 1458 public void remove() { 1459 i.remove(); 1460 } 1461 1462 @Override 1463 public void set(T e) { 1464 typeCheck(e); 1465 i.set(e); 1466 } 1467 1468 @Override 1469 public void add(T e) { 1470 typeCheck(e); 1471 i.add(e); 1472 } 1473 }; 1474 } 1475 1476 @Override 1477 public Iterator<T> iterator() { 1478 return new Iterator<T>() { 1479 1480 private final Iterator<T> it = list.iterator(); 1481 1482 @Override 1483 public boolean hasNext() { 1484 return it.hasNext(); 1485 } 1486 1487 @Override 1488 public T next() { 1489 return it.next(); 1490 } 1491 1492 @Override 1493 public void remove() { 1494 it.remove(); 1495 } 1496 }; 1497 } 1498 1499 @Override 1500 public boolean add(T e) { 1501 typeCheck(e); 1502 return list.add(e); 1503 } 1504 1505 @Override 1506 public List<T> subList(int fromIndex, int toIndex) { 1507 return Collections.checkedList(list.subList(fromIndex, toIndex), type); 1508 } 1509 1510 @Override 1511 @SuppressWarnings("unchecked") 1512 public boolean addAll(T... elements) { 1513 try { 1514 T[] array = (T[]) Array.newInstance(type, elements.length); 1515 System.arraycopy(elements, 0, array, 0, elements.length); 1516 return list.addAll(array); 1517 } catch (ArrayStoreException e) { 1518 throw new ClassCastException(); 1519 } 1520 } 1521 1522 @Override 1523 @SuppressWarnings("unchecked") 1524 public boolean setAll(T... elements) { 1525 try { 1526 T[] array = (T[]) Array.newInstance(type, elements.length); 1527 System.arraycopy(elements, 0, array, 0, elements.length); 1528 return list.setAll(array); 1529 } catch (ArrayStoreException e) { 1530 throw new ClassCastException(); 1531 } 1532 } 1533 1534 @Override 1535 @SuppressWarnings("unchecked") 1536 public boolean setAll(Collection<? extends T> col) { 1537 T[] a = null; 1538 try { 1539 a = col.toArray((T[]) Array.newInstance(type, 0)); 1540 } catch (ArrayStoreException e) { 1541 throw new ClassCastException(); 1542 } 1543 1544 return list.setAll(Arrays.asList(a)); 1545 } 1546 } 1547 1548 private static class EmptyObservableSet<E> extends AbstractSet<E> implements ObservableSet<E> { 1549 1550 public EmptyObservableSet() { 1551 } 1552 1553 @Override 1554 public void addListener(InvalidationListener listener) { 1555 } 1556 1557 @Override 1558 public void removeListener(InvalidationListener listener) { 1559 } 1560 1561 @Override 1562 public void addListener(SetChangeListener<? super E> listener) { 1563 } 1564 1565 @Override 1566 public void removeListener(SetChangeListener<? super E> listener) { 1567 } 1568 1569 @Override 1570 public int size() { 1571 return 0; 1572 } 1573 1574 @Override 1575 public boolean isEmpty() { 1576 return true; 1577 } 1578 1579 @Override 1580 public boolean contains(Object obj) { 1581 return false; 1582 } 1583 1584 @Override 1585 public boolean containsAll(Collection<?> c) { 1586 return c.isEmpty(); 1587 } 1588 1589 @Override 1590 public Object[] toArray() { 1591 return new Object[0]; 1592 } 1593 1594 @Override 1595 public <E> E[] toArray(E[] a) { 1596 if (a.length > 0) 1597 a[0] = null; 1598 return a; 1599 } 1600 1601 @Override 1602 public Iterator<E> iterator() { 1603 return new Iterator() { 1604 1605 @Override 1606 public boolean hasNext() { 1607 return false; 1608 } 1609 1610 @Override 1611 public Object next() { 1612 throw new NoSuchElementException(); 1613 } 1614 1615 @Override 1616 public void remove() { 1617 throw new UnsupportedOperationException(); 1618 } 1619 }; 1620 } 1621 1622 } 1623 1624 private static class UnmodifiableObservableSet<E> extends AbstractSet<E> implements ObservableSet<E> { 1625 1626 private final ObservableSet<E> backingSet; 1627 private SetListenerHelper<E> listenerHelper; 1628 private final SetChangeListener<E> listener; 1629 1630 public UnmodifiableObservableSet(ObservableSet<E> backingSet) { 1631 this.backingSet = backingSet; 1632 listener = new SetChangeListener<E>() { 1633 @Override 1634 public void onChanged(Change<? extends E> c) { 1635 callObservers(new SetAdapterChange<E>(UnmodifiableObservableSet.this, c)); 1636 } 1637 }; 1638 this.backingSet.addListener(new WeakSetChangeListener<E>(listener)); 1639 } 1640 1641 private void callObservers(SetChangeListener.Change<? extends E> change) { 1642 SetListenerHelper.fireValueChangedEvent(listenerHelper, change); 1643 } 1644 1645 @Override 1646 public Iterator<E> iterator() { 1647 return new Iterator<E>() { 1648 private final Iterator<? extends E> i = backingSet.iterator(); 1649 1650 @Override 1651 public boolean hasNext() { 1652 return i.hasNext(); 1653 } 1654 1655 @Override 1656 public E next() { 1657 return i.next(); 1658 } 1659 1660 @Override 1661 public void remove() { 1662 throw new UnsupportedOperationException(); 1663 } 1664 }; 1665 } 1666 1667 @Override 1668 public int size() { 1669 return backingSet.size(); 1670 } 1671 1672 @Override 1673 public void addListener(InvalidationListener listener) { 1674 listenerHelper = SetListenerHelper.addListener(listenerHelper, listener); 1675 } 1676 1677 @Override 1678 public void removeListener(InvalidationListener listener) { 1679 listenerHelper = SetListenerHelper.removeListener(listenerHelper, listener); 1680 } 1681 1682 @Override 1683 public void addListener(SetChangeListener<? super E> listener) { 1684 listenerHelper = SetListenerHelper.addListener(listenerHelper, listener); 1685 } 1686 1687 @Override 1688 public void removeListener(SetChangeListener<? super E> listener) { 1689 listenerHelper = SetListenerHelper.removeListener(listenerHelper, listener); 1690 } 1691 1692 @Override 1693 public boolean add(E e) { 1694 throw new UnsupportedOperationException(); 1695 } 1696 1697 @Override 1698 public boolean remove(Object o) { 1699 throw new UnsupportedOperationException(); 1700 } 1701 1702 @Override 1703 public boolean addAll(Collection<? extends E> c) { 1704 throw new UnsupportedOperationException(); 1705 } 1706 1707 @Override 1708 public boolean retainAll(Collection<?> c) { 1709 throw new UnsupportedOperationException(); 1710 } 1711 1712 @Override 1713 public boolean removeAll(Collection<?> c) { 1714 throw new UnsupportedOperationException(); 1715 } 1716 1717 @Override 1718 public void clear() { 1719 throw new UnsupportedOperationException(); 1720 } 1721 } 1722 1723 private static class SynchronizedSet<E> implements Set<E> { 1724 final Object mutex; 1725 private final Set<E> backingSet; 1726 1727 SynchronizedSet(Set<E> set, Object mutex) { 1728 this.backingSet = set; 1729 this.mutex = mutex; 1730 } 1731 1732 SynchronizedSet(Set<E> set) { 1733 this(set, new Object()); 1734 } 1735 1736 @Override 1737 public int size() { 1738 synchronized(mutex) { 1739 return backingSet.size(); 1740 } 1741 } 1742 1743 @Override 1744 public boolean isEmpty() { 1745 synchronized(mutex) { 1746 return backingSet.isEmpty(); 1747 } 1748 } 1749 1750 @Override 1751 public boolean contains(Object o) { 1752 synchronized(mutex) { 1753 return backingSet.contains(o); 1754 } 1755 } 1756 1757 @Override 1758 public Iterator<E> iterator() { 1759 return backingSet.iterator(); 1760 } 1761 1762 @Override 1763 public Object[] toArray() { 1764 synchronized(mutex) { 1765 return backingSet.toArray(); 1766 } 1767 } 1768 1769 @Override 1770 public <E> E[] toArray(E[] a) { 1771 synchronized(mutex) { 1772 return backingSet.toArray(a); 1773 } 1774 } 1775 1776 @Override 1777 public boolean add(E e) { 1778 synchronized(mutex) { 1779 return backingSet.add(e); 1780 } 1781 } 1782 1783 @Override 1784 public boolean remove(Object o) { 1785 synchronized(mutex) { 1786 return backingSet.remove(o); 1787 } 1788 } 1789 1790 @Override 1791 public boolean containsAll(Collection<?> c) { 1792 synchronized(mutex) { 1793 return backingSet.containsAll(c); 1794 } 1795 } 1796 1797 @Override 1798 public boolean addAll(Collection<? extends E> c) { 1799 synchronized(mutex) { 1800 return backingSet.addAll(c); 1801 } 1802 } 1803 1804 @Override 1805 public boolean retainAll(Collection<?> c) { 1806 synchronized(mutex) { 1807 return backingSet.retainAll(c); 1808 } 1809 } 1810 1811 @Override 1812 public boolean removeAll(Collection<?> c) { 1813 synchronized(mutex) { 1814 return backingSet.removeAll(c); 1815 } 1816 } 1817 1818 @Override 1819 public void clear() { 1820 synchronized(mutex) { 1821 backingSet.clear(); 1822 } 1823 } 1824 1825 @Override 1826 public boolean equals(Object o) { 1827 if (o == this) { 1828 return true; 1829 } 1830 synchronized(mutex) { 1831 return backingSet.equals(o); 1832 } 1833 } 1834 1835 @Override 1836 public int hashCode() { 1837 synchronized (mutex) { 1838 return backingSet.hashCode(); 1839 } 1840 } 1841 } 1842 1843 private static class SynchronizedObservableSet<E> extends SynchronizedSet<E> implements ObservableSet<E> { 1844 1845 private final ObservableSet<E> backingSet; 1846 private SetListenerHelper listenerHelper; 1847 private final SetChangeListener<E> listener; 1848 1849 SynchronizedObservableSet(ObservableSet<E> set, Object mutex) { 1850 super(set, mutex); 1851 backingSet = set; 1852 listener = new SetChangeListener<E>() { 1853 @Override 1854 public void onChanged(Change<? extends E> c) { 1855 SetListenerHelper.fireValueChangedEvent(listenerHelper, new SetAdapterChange<E>(SynchronizedObservableSet.this, c)); 1856 } 1857 }; 1858 backingSet.addListener(new WeakSetChangeListener<E>(listener)); 1859 } 1860 1861 SynchronizedObservableSet(ObservableSet<E> set) { 1862 this(set, new Object()); 1863 } 1864 1865 @Override 1866 public void addListener(InvalidationListener listener) { 1867 listenerHelper = SetListenerHelper.addListener(listenerHelper, listener); 1868 } 1869 1870 @Override 1871 public void removeListener(InvalidationListener listener) { 1872 listenerHelper = SetListenerHelper.removeListener(listenerHelper, listener); 1873 } 1874 @Override 1875 public void addListener(SetChangeListener<? super E> listener) { 1876 listenerHelper = SetListenerHelper.addListener(listenerHelper, listener); 1877 } 1878 1879 @Override 1880 public void removeListener(SetChangeListener<? super E> listener) { 1881 listenerHelper = SetListenerHelper.removeListener(listenerHelper, listener); 1882 } 1883 } 1884 1885 private static class CheckedObservableSet<E> extends AbstractSet<E> implements ObservableSet<E> { 1886 1887 private final ObservableSet<E> backingSet; 1888 private final Class<E> type; 1889 private SetListenerHelper listenerHelper; 1890 private final SetChangeListener<E> listener; 1891 1892 CheckedObservableSet(ObservableSet<E> set, Class<E> type) { 1893 if (set == null || type == null) { 1894 throw new NullPointerException(); 1895 } 1896 backingSet = set; 1897 this.type = type; 1898 listener = new SetChangeListener<E>() { 1899 @Override 1900 public void onChanged(SetChangeListener.Change<? extends E> c) { 1901 callObservers(new SetAdapterChange<E>(CheckedObservableSet.this, c)); 1902 } 1903 }; 1904 backingSet.addListener(new WeakSetChangeListener<E>(listener)); 1905 } 1906 1907 private void callObservers(SetChangeListener.Change<? extends E> c) { 1908 SetListenerHelper.fireValueChangedEvent(listenerHelper, c); 1909 } 1910 1911 void typeCheck(Object o) { 1912 if (o != null && !type.isInstance(o)) { 1913 throw new ClassCastException("Attempt to insert " 1914 + o.getClass() + " element into collection with element type " 1915 + type); 1916 } 1917 } 1918 1919 @Override 1920 public void addListener(InvalidationListener listener) { 1921 listenerHelper = SetListenerHelper.addListener(listenerHelper, listener); 1922 } 1923 1924 @Override 1925 public void removeListener(InvalidationListener listener) { 1926 listenerHelper = SetListenerHelper.removeListener(listenerHelper, listener); 1927 } 1928 1929 @Override 1930 public void addListener(SetChangeListener<? super E> listener) { 1931 listenerHelper = SetListenerHelper.addListener(listenerHelper, listener); 1932 } 1933 1934 @Override 1935 public void removeListener(SetChangeListener<? super E> listener) { 1936 listenerHelper = SetListenerHelper.removeListener(listenerHelper, listener); 1937 } 1938 1939 @Override 1940 public int size() { 1941 return backingSet.size(); 1942 } 1943 1944 @Override 1945 public boolean isEmpty() { 1946 return backingSet.isEmpty(); 1947 } 1948 1949 @Override 1950 public boolean contains(Object o) { 1951 return backingSet.contains(o); 1952 } 1953 1954 @Override 1955 public Object[] toArray() { 1956 return backingSet.toArray(); 1957 } 1958 1959 @Override 1960 public <T> T[] toArray(T[] a) { 1961 return backingSet.toArray(a); 1962 } 1963 1964 @Override 1965 public boolean add(E e) { 1966 typeCheck(e); 1967 return backingSet.add(e); 1968 } 1969 1970 @Override 1971 public boolean remove(Object o) { 1972 return backingSet.remove(o); 1973 } 1974 1975 @Override 1976 public boolean containsAll(Collection<?> c) { 1977 return backingSet.containsAll(c); 1978 } 1979 1980 @Override 1981 @SuppressWarnings("unchecked") 1982 public boolean addAll(Collection<? extends E> c) { 1983 E[] a = null; 1984 try { 1985 a = c.toArray((E[]) Array.newInstance(type, 0)); 1986 } catch (ArrayStoreException e) { 1987 throw new ClassCastException(); 1988 } 1989 1990 return backingSet.addAll(Arrays.asList(a)); 1991 } 1992 1993 @Override 1994 public boolean retainAll(Collection<?> c) { 1995 return backingSet.retainAll(c); 1996 } 1997 1998 @Override 1999 public boolean removeAll(Collection<?> c) { 2000 return backingSet.removeAll(c); 2001 } 2002 2003 @Override 2004 public void clear() { 2005 backingSet.clear(); 2006 } 2007 2008 @Override 2009 public boolean equals(Object o) { 2010 return o == this || backingSet.equals(o); 2011 } 2012 2013 @Override 2014 public int hashCode() { 2015 return backingSet.hashCode(); 2016 } 2017 2018 @Override 2019 public Iterator<E> iterator() { 2020 final Iterator<E> it = backingSet.iterator(); 2021 2022 return new Iterator<E>() { 2023 @Override 2024 public boolean hasNext() { 2025 return it.hasNext(); 2026 } 2027 2028 @Override 2029 public E next() { 2030 return it.next(); 2031 } 2032 2033 @Override 2034 public void remove() { 2035 it.remove(); 2036 } 2037 }; 2038 } 2039 2040 } 2041 2042 private static class EmptyObservableMap<K, V> extends AbstractMap<K, V> implements ObservableMap<K, V> { 2043 2044 public EmptyObservableMap() { 2045 } 2046 2047 @Override 2048 public void addListener(InvalidationListener listener) { 2049 } 2050 2051 @Override 2052 public void removeListener(InvalidationListener listener) { 2053 } 2054 2055 @Override 2056 public void addListener(MapChangeListener<? super K, ? super V> listener) { 2057 } 2058 2059 @Override 2060 public void removeListener(MapChangeListener<? super K, ? super V> listener) { 2061 } 2062 2063 @Override 2064 public int size() { 2065 return 0; 2066 } 2067 2068 @Override 2069 public boolean isEmpty() { 2070 return true; 2071 } 2072 2073 @Override 2074 public boolean containsKey(Object key) { 2075 return false; 2076 } 2077 2078 @Override 2079 public boolean containsValue(Object value) { 2080 return false; 2081 } 2082 2083 @Override 2084 public V get(Object key) { 2085 return null; 2086 } 2087 2088 @Override 2089 public Set<K> keySet() { 2090 return emptyObservableSet(); 2091 } 2092 2093 @Override 2094 public Collection<V> values() { 2095 return emptyObservableSet(); 2096 } 2097 2098 @Override 2099 public Set<Map.Entry<K,V>> entrySet() { 2100 return emptyObservableSet(); 2101 } 2102 2103 @Override 2104 public boolean equals(Object o) { 2105 return (o instanceof Map) && ((Map<?,?>)o).isEmpty(); 2106 } 2107 2108 @Override 2109 public int hashCode() { 2110 return 0; 2111 } 2112 } 2113 2114 private static class CheckedObservableMap<K, V> extends AbstractMap<K, V> implements ObservableMap<K, V> { 2115 2116 private final ObservableMap<K, V> backingMap; 2117 private final Class<K> keyType; 2118 private final Class<V> valueType; 2119 private MapListenerHelper listenerHelper; 2120 private final MapChangeListener<K, V> listener; 2121 2122 CheckedObservableMap(ObservableMap<K, V> map, Class<K> keyType, Class<V> valueType) { 2123 backingMap = map; 2124 this.keyType = keyType; 2125 this.valueType = valueType; 2126 listener = new MapChangeListener<K, V>() { 2127 @Override 2128 public void onChanged(MapChangeListener.Change<? extends K, ? extends V> c) { 2129 callObservers(new MapAdapterChange<K, V>(CheckedObservableMap.this, c)); 2130 } 2131 }; 2132 backingMap.addListener(new WeakMapChangeListener<K, V>(listener)); 2133 } 2134 2135 private void callObservers(MapChangeListener.Change<? extends K, ? extends V> c) { 2136 MapListenerHelper.fireValueChangedEvent(listenerHelper, c); 2137 } 2138 2139 void typeCheck(Object key, Object value) { 2140 if (key != null && !keyType.isInstance(key)) { 2141 throw new ClassCastException("Attempt to insert " 2142 + key.getClass() + " key into map with key type " 2143 + keyType); 2144 } 2145 2146 if (value != null && !valueType.isInstance(value)) { 2147 throw new ClassCastException("Attempt to insert " 2148 + value.getClass() + " value into map with value type " 2149 + valueType); 2150 } 2151 } 2152 2153 @Override 2154 public void addListener(InvalidationListener listener) { 2155 listenerHelper = MapListenerHelper.addListener(listenerHelper, listener); 2156 } 2157 2158 @Override 2159 public void removeListener(InvalidationListener listener) { 2160 listenerHelper = MapListenerHelper.removeListener(listenerHelper, listener); 2161 } 2162 2163 @Override 2164 public void addListener(MapChangeListener<? super K, ? super V> listener) { 2165 listenerHelper = MapListenerHelper.addListener(listenerHelper, listener); 2166 } 2167 2168 @Override 2169 public void removeListener(MapChangeListener<? super K, ? super V> listener) { 2170 listenerHelper = MapListenerHelper.removeListener(listenerHelper, listener); 2171 } 2172 2173 @Override 2174 public int size() { 2175 return backingMap.size(); 2176 } 2177 2178 @Override 2179 public boolean isEmpty() { 2180 return backingMap.isEmpty(); 2181 } 2182 2183 @Override 2184 public boolean containsKey(Object key) { 2185 return backingMap.containsKey(key); 2186 } 2187 2188 @Override 2189 public boolean containsValue(Object value) { 2190 return backingMap.containsValue(value); 2191 } 2192 2193 @Override 2194 public V get(Object key) { 2195 return backingMap.get(key); 2196 } 2197 2198 @Override 2199 public V put(K key, V value) { 2200 typeCheck(key, value); 2201 return backingMap.put(key, value); 2202 } 2203 2204 @Override 2205 public V remove(Object key) { 2206 return backingMap.remove(key); 2207 } 2208 2209 @Override 2210 @SuppressWarnings("unchecked") 2211 public void putAll(Map t) { 2212 // Satisfy the following goals: 2213 // - good diagnostics in case of type mismatch 2214 // - all-or-nothing semantics 2215 // - protection from malicious t 2216 // - correct behavior if t is a concurrent map 2217 Object[] entries = t.entrySet().toArray(); 2218 List<Map.Entry<K,V>> checked = 2219 new ArrayList<Map.Entry<K,V>>(entries.length); 2220 for (Object o : entries) { 2221 Map.Entry<?,?> e = (Map.Entry<?,?>) o; 2222 Object k = e.getKey(); 2223 Object v = e.getValue(); 2224 typeCheck(k, v); 2225 checked.add( 2226 new AbstractMap.SimpleImmutableEntry<K,V>((K) k, (V) v)); 2227 } 2228 for (Map.Entry<K,V> e : checked) 2229 backingMap.put(e.getKey(), e.getValue()); 2230 } 2231 2232 @Override 2233 public void clear() { 2234 backingMap.clear(); 2235 } 2236 2237 @Override 2238 public Set<K> keySet() { 2239 return backingMap.keySet(); 2240 } 2241 2242 @Override 2243 public Collection<V> values() { 2244 return backingMap.values(); 2245 } 2246 2247 private transient Set<Map.Entry<K,V>> entrySet = null; 2248 2249 @Override 2250 public Set entrySet() { 2251 if (entrySet==null) 2252 entrySet = new CheckedEntrySet<K,V>(backingMap.entrySet(), valueType); 2253 return entrySet; 2254 } 2255 2256 @Override 2257 public boolean equals(Object o) { 2258 return o == this || backingMap.equals(o); 2259 } 2260 2261 @Override 2262 public int hashCode() { 2263 return backingMap.hashCode(); 2264 } 2265 2266 static class CheckedEntrySet<K,V> implements Set<Map.Entry<K,V>> { 2267 private final Set<Map.Entry<K,V>> s; 2268 private final Class<V> valueType; 2269 2270 CheckedEntrySet(Set<Map.Entry<K, V>> s, Class<V> valueType) { 2271 this.s = s; 2272 this.valueType = valueType; 2273 } 2274 2275 @Override 2276 public int size() { 2277 return s.size(); 2278 } 2279 2280 @Override 2281 public boolean isEmpty() { 2282 return s.isEmpty(); 2283 } 2284 2285 @Override 2286 public String toString() { 2287 return s.toString(); 2288 } 2289 2290 @Override 2291 public int hashCode() { 2292 return s.hashCode(); 2293 } 2294 2295 @Override 2296 public void clear() { 2297 s.clear(); 2298 } 2299 2300 @Override 2301 public boolean add(Map.Entry<K, V> e) { 2302 throw new UnsupportedOperationException(); 2303 } 2304 2305 @Override 2306 public boolean addAll(Collection<? extends Map.Entry<K, V>> coll) { 2307 throw new UnsupportedOperationException(); 2308 } 2309 2310 @Override 2311 public Iterator<Map.Entry<K,V>> iterator() { 2312 final Iterator<Map.Entry<K, V>> i = s.iterator(); 2313 final Class<V> valueType = this.valueType; 2314 2315 return new Iterator<Map.Entry<K,V>>() { 2316 @Override 2317 public boolean hasNext() { 2318 return i.hasNext(); 2319 } 2320 2321 @Override 2322 public void remove() { 2323 i.remove(); 2324 } 2325 2326 @Override 2327 public Map.Entry<K,V> next() { 2328 return checkedEntry(i.next(), valueType); 2329 } 2330 }; 2331 } 2332 2333 @Override 2334 @SuppressWarnings("unchecked") 2335 public Object[] toArray() { 2336 Object[] source = s.toArray(); 2337 2338 /* 2339 * Ensure that we don't get an ArrayStoreException even if 2340 * s.toArray returns an array of something other than Object 2341 */ 2342 Object[] dest = (CheckedEntry.class.isInstance( 2343 source.getClass().getComponentType()) ? source : 2344 new Object[source.length]); 2345 2346 for (int i = 0; i < source.length; i++) 2347 dest[i] = checkedEntry((Map.Entry<K,V>)source[i], 2348 valueType); 2349 return dest; 2350 } 2351 2352 @Override 2353 @SuppressWarnings("unchecked") 2354 public <T> T[] toArray(T[] a) { 2355 // We don't pass a to s.toArray, to avoid window of 2356 // vulnerability wherein an unscrupulous multithreaded client 2357 // could get his hands on raw (unwrapped) Entries from s. 2358 T[] arr = s.toArray(a.length==0 ? a : Arrays.copyOf(a, 0)); 2359 2360 for (int i=0; i<arr.length; i++) 2361 arr[i] = (T) checkedEntry((Map.Entry<K,V>)arr[i], 2362 valueType); 2363 if (arr.length > a.length) 2364 return arr; 2365 2366 System.arraycopy(arr, 0, a, 0, arr.length); 2367 if (a.length > arr.length) 2368 a[arr.length] = null; 2369 return a; 2370 } 2371 2372 /** 2373 * This method is overridden to protect the backing set against 2374 * an object with a nefarious equals function that senses 2375 * that the equality-candidate is Map.Entry and calls its 2376 * setValue method. 2377 */ 2378 @Override 2379 public boolean contains(Object o) { 2380 if (!(o instanceof Map.Entry)) 2381 return false; 2382 Map.Entry<?,?> e = (Map.Entry<?,?>) o; 2383 return s.contains( 2384 (e instanceof CheckedEntry) ? e : checkedEntry(e, valueType)); 2385 } 2386 2387 /** 2388 * The bulk collection methods are overridden to protect 2389 * against an unscrupulous collection whose contains(Object o) 2390 * method senses when o is a Map.Entry, and calls o.setValue. 2391 */ 2392 @Override 2393 public boolean containsAll(Collection<?> c) { 2394 for (Object o : c) 2395 if (!contains(o)) // Invokes safe contains() above 2396 return false; 2397 return true; 2398 } 2399 2400 @Override 2401 public boolean remove(Object o) { 2402 if (!(o instanceof Map.Entry)) 2403 return false; 2404 return s.remove(new AbstractMap.SimpleImmutableEntry 2405 <Object, Object>((Map.Entry<?,?>)o)); 2406 } 2407 2408 @Override 2409 public boolean removeAll(Collection<?> c) { 2410 return batchRemove(c, false); 2411 } 2412 2413 @Override 2414 public boolean retainAll(Collection<?> c) { 2415 return batchRemove(c, true); 2416 } 2417 2418 private boolean batchRemove(Collection<?> c, boolean complement) { 2419 boolean modified = false; 2420 Iterator<Map.Entry<K,V>> it = iterator(); 2421 while (it.hasNext()) { 2422 if (c.contains(it.next()) != complement) { 2423 it.remove(); 2424 modified = true; 2425 } 2426 } 2427 return modified; 2428 } 2429 2430 @Override 2431 public boolean equals(Object o) { 2432 if (o == this) 2433 return true; 2434 if (!(o instanceof Set)) 2435 return false; 2436 Set<?> that = (Set<?>) o; 2437 return that.size() == s.size() 2438 && containsAll(that); // Invokes safe containsAll() above 2439 } 2440 2441 static <K,V,T> CheckedEntry<K,V,T> checkedEntry(Map.Entry<K,V> e, 2442 Class<T> valueType) { 2443 return new CheckedEntry<K,V,T>(e, valueType); 2444 } 2445 2446 /** 2447 * This "wrapper class" serves two purposes: it prevents 2448 * the client from modifying the backing Map, by short-circuiting 2449 * the setValue method, and it protects the backing Map against 2450 * an ill-behaved Map.Entry that attempts to modify another 2451 * Map.Entry when asked to perform an equality check. 2452 */ 2453 private static class CheckedEntry<K,V,T> implements Map.Entry<K,V> { 2454 private final Map.Entry<K, V> e; 2455 private final Class<T> valueType; 2456 2457 CheckedEntry(Map.Entry<K, V> e, Class<T> valueType) { 2458 this.e = e; 2459 this.valueType = valueType; 2460 } 2461 2462 @Override 2463 public K getKey() { 2464 return e.getKey(); 2465 } 2466 2467 @Override 2468 public V getValue() { 2469 return e.getValue(); 2470 } 2471 2472 @Override 2473 public int hashCode() { 2474 return e.hashCode(); 2475 } 2476 2477 @Override 2478 public String toString() { 2479 return e.toString(); 2480 } 2481 2482 @Override 2483 public V setValue(V value) { 2484 if (value != null && !valueType.isInstance(value)) 2485 throw new ClassCastException(badValueMsg(value)); 2486 return e.setValue(value); 2487 } 2488 2489 private String badValueMsg(Object value) { 2490 return "Attempt to insert " + value.getClass() + 2491 " value into map with value type " + valueType; 2492 } 2493 2494 @Override 2495 public boolean equals(Object o) { 2496 if (o == this) 2497 return true; 2498 if (!(o instanceof Map.Entry)) 2499 return false; 2500 return e.equals(new AbstractMap.SimpleImmutableEntry 2501 <Object, Object>((Map.Entry<?,?>)o)); 2502 } 2503 } 2504 } 2505 2506 } 2507 2508 private static class SynchronizedMap<K, V> implements Map<K, V> { 2509 final Object mutex; 2510 private final Map<K, V> backingMap; 2511 2512 SynchronizedMap(Map<K, V> map, Object mutex) { 2513 backingMap = map; 2514 this.mutex = mutex; 2515 } 2516 2517 SynchronizedMap(Map<K, V> map) { 2518 this(map, new Object()); 2519 } 2520 2521 @Override 2522 public int size() { 2523 synchronized (mutex) { 2524 return backingMap.size(); 2525 } 2526 } 2527 2528 @Override 2529 public boolean isEmpty() { 2530 synchronized (mutex) { 2531 return backingMap.isEmpty(); 2532 } 2533 } 2534 2535 @Override 2536 public boolean containsKey(Object key) { 2537 synchronized (mutex) { 2538 return backingMap.containsKey(key); 2539 } 2540 } 2541 2542 @Override 2543 public boolean containsValue(Object value) { 2544 synchronized (mutex) { 2545 return backingMap.containsValue(value); 2546 } 2547 } 2548 2549 @Override 2550 public V get(Object key) { 2551 synchronized (mutex) { 2552 return backingMap.get(key); 2553 } 2554 } 2555 2556 @Override 2557 public V put(K key, V value) { 2558 synchronized (mutex) { 2559 return backingMap.put(key, value); 2560 } 2561 } 2562 2563 @Override 2564 public V remove(Object key) { 2565 synchronized (mutex) { 2566 return backingMap.remove(key); 2567 } 2568 } 2569 2570 @Override 2571 public void putAll(Map<? extends K, ? extends V> m) { 2572 synchronized (mutex) { 2573 backingMap.putAll(m); 2574 } 2575 } 2576 2577 @Override 2578 public void clear() { 2579 synchronized (mutex) { 2580 backingMap.clear(); 2581 } 2582 } 2583 2584 private transient Set<K> keySet = null; 2585 private transient Set<Map.Entry<K,V>> entrySet = null; 2586 private transient Collection<V> values = null; 2587 2588 @Override 2589 public Set<K> keySet() { 2590 synchronized(mutex) { 2591 if (keySet==null) 2592 keySet = new SynchronizedSet<K>(backingMap.keySet(), mutex); 2593 return keySet; 2594 } 2595 } 2596 2597 @Override 2598 public Collection<V> values() { 2599 synchronized(mutex) { 2600 if (values==null) 2601 values = new SynchronizedCollection<V>(backingMap.values(), mutex); 2602 return values; 2603 } 2604 } 2605 2606 @Override 2607 public Set<Entry<K, V>> entrySet() { 2608 synchronized(mutex) { 2609 if (entrySet==null) 2610 entrySet = new SynchronizedSet<Map.Entry<K,V>>(backingMap.entrySet(), mutex); 2611 return entrySet; 2612 } 2613 } 2614 2615 @Override 2616 public boolean equals(Object o) { 2617 if (o == this) { 2618 return true; 2619 } 2620 synchronized(mutex) { 2621 return backingMap.equals(o); 2622 } 2623 } 2624 2625 @Override 2626 public int hashCode() { 2627 synchronized(mutex) { 2628 return backingMap.hashCode(); 2629 } 2630 } 2631 2632 } 2633 2634 private static class SynchronizedCollection<E> implements Collection<E> { 2635 2636 private final Collection<E> backingCollection; 2637 final Object mutex; 2638 2639 SynchronizedCollection(Collection<E> c, Object mutex) { 2640 backingCollection = c; 2641 this.mutex = mutex; 2642 } 2643 2644 SynchronizedCollection(Collection<E> c) { 2645 this(c, new Object()); 2646 } 2647 2648 @Override 2649 public int size() { 2650 synchronized (mutex) { 2651 return backingCollection.size(); 2652 } 2653 } 2654 2655 @Override 2656 public boolean isEmpty() { 2657 synchronized (mutex) { 2658 return backingCollection.isEmpty(); 2659 } 2660 } 2661 2662 @Override 2663 public boolean contains(Object o) { 2664 synchronized (mutex) { 2665 return backingCollection.contains(o); 2666 } 2667 } 2668 2669 @Override 2670 public Iterator<E> iterator() { 2671 return backingCollection.iterator(); 2672 } 2673 2674 @Override 2675 public Object[] toArray() { 2676 synchronized (mutex) { 2677 return backingCollection.toArray(); 2678 } 2679 } 2680 2681 @Override 2682 public <T> T[] toArray(T[] a) { 2683 synchronized (mutex) { 2684 return backingCollection.toArray(a); 2685 } 2686 } 2687 2688 @Override 2689 public boolean add(E e) { 2690 synchronized (mutex) { 2691 return backingCollection.add(e); 2692 } 2693 } 2694 2695 @Override 2696 public boolean remove(Object o) { 2697 synchronized (mutex) { 2698 return backingCollection.remove(o); 2699 } 2700 } 2701 2702 @Override 2703 public boolean containsAll(Collection<?> c) { 2704 synchronized (mutex) { 2705 return backingCollection.containsAll(c); 2706 } 2707 } 2708 2709 @Override 2710 public boolean addAll(Collection<? extends E> c) { 2711 synchronized (mutex) { 2712 return backingCollection.addAll(c); 2713 } 2714 } 2715 2716 @Override 2717 public boolean removeAll(Collection<?> c) { 2718 synchronized (mutex) { 2719 return backingCollection.removeAll(c); 2720 } 2721 } 2722 2723 @Override 2724 public boolean retainAll(Collection<?> c) { 2725 synchronized (mutex) { 2726 return backingCollection.retainAll(c); 2727 } 2728 } 2729 2730 @Override 2731 public void clear() { 2732 synchronized (mutex) { 2733 backingCollection.clear(); 2734 } 2735 } 2736 } 2737 2738 private static class SynchronizedObservableMap<K, V> extends SynchronizedMap<K, V> implements ObservableMap<K, V> { 2739 2740 private final ObservableMap<K, V> backingMap; 2741 private MapListenerHelper listenerHelper; 2742 private final MapChangeListener<K, V> listener; 2743 2744 SynchronizedObservableMap(ObservableMap<K, V> map, Object mutex) { 2745 super(map, mutex); 2746 backingMap = map; 2747 listener = new MapChangeListener<K, V>() { 2748 @Override 2749 public void onChanged(Change<? extends K, ? extends V> c) { 2750 MapListenerHelper.fireValueChangedEvent(listenerHelper, new MapAdapterChange<K, V>(SynchronizedObservableMap.this, c)); 2751 } 2752 }; 2753 backingMap.addListener(new WeakMapChangeListener<K, V>(listener)); 2754 } 2755 2756 SynchronizedObservableMap(ObservableMap<K, V> map) { 2757 this(map, new Object()); 2758 } 2759 2760 @Override 2761 public void addListener(InvalidationListener listener) { 2762 listenerHelper = MapListenerHelper.addListener(listenerHelper, listener); 2763 2764 } 2765 2766 @Override 2767 public void removeListener(InvalidationListener listener) { 2768 listenerHelper = MapListenerHelper.removeListener(listenerHelper, listener); 2769 } 2770 2771 @Override 2772 public void addListener(MapChangeListener<? super K, ? super V> listener) { 2773 listenerHelper = MapListenerHelper.addListener(listenerHelper, listener); 2774 } 2775 2776 @Override 2777 public void removeListener(MapChangeListener<? super K, ? super V> listener) { 2778 listenerHelper = MapListenerHelper.removeListener(listenerHelper, listener); 2779 } 2780 2781 } 2782 2783}