1 /*
   2  * Copyright (c) 2009, 2014, 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 com.sun.javafx.collections.ObservableListWrapper;
  29 import java.util.ArrayList;
  30 import java.util.Arrays;
  31 import java.util.Collections;
  32 import java.util.List;
  33 import org.junit.Before;
  34 import org.junit.Test;
  35 import static org.junit.Assert.*;
  36 
  37 public class ListChangeBuilderTest {
  38 
  39     private ListChangeBuilder<String> builder;
  40     private ObservableListWrapper<String> observableList;
  41     private ArrayList<String> list;
  42     private MockListObserver<String> observer;
  43     
  44     @Before
  45     public void setUp() {
  46         observer = new MockListObserver<String>();
  47         list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
  48         observableList = new ObservableListWrapper<String>(list);
  49         observableList.addListener(observer);
  50         builder = new ListChangeBuilder<String>(observableList);
  51     }
  52 
  53     @Test
  54     public void testAddRemove() {
  55         builder.beginChange();
  56         list.remove(2);
  57         builder.nextRemove(2, "c");
  58         list.add(2, "cc");
  59         list.add(3, "ccc");
  60         builder.nextAdd(2, 4);
  61         list.remove(2);
  62         builder.nextRemove(2, "cc");
  63         list.remove(3);
  64         builder.nextRemove(3, "d");
  65         list.add(0, "aa");
  66         builder.nextAdd(0, 1);
  67         builder.endChange();
  68 
  69         assertEquals(list, Arrays.asList("aa", "a", "b", "ccc"));
  70 
  71         observer.checkAddRemove(0, observableList, Collections.EMPTY_LIST, 0, 1);
  72         observer.checkAddRemove(1, observableList, Arrays.asList("c", "d"), 3, 4);
  73     }
  74 
  75     @Test
  76     public void testAddRemove_2() {
  77         builder.beginChange();
  78         list.add("e");
  79         builder.nextAdd(4, 5);
  80         list.add(3, "dd");
  81         builder.nextAdd(3, 4);
  82         list.remove(4);
  83         builder.nextRemove(4, "d");
  84 
  85         list.remove(0);
  86         builder.nextRemove(0, "a");
  87         builder.endChange();
  88 
  89         assertEquals(list, Arrays.asList("b", "c", "dd", "e"));
  90 
  91         observer.checkAddRemove(0, observableList, Arrays.asList("a"), 0, 0);
  92         observer.checkAddRemove(1, observableList, Arrays.asList("d"), 2, 4);
  93     }
  94 
  95     @Test
  96     public void testAddRemove_3() {
  97         builder.beginChange();
  98         list.add("e");
  99         builder.nextAdd(4, 5);
 100 
 101         list.set(0, "aa");
 102         builder.nextReplace(0, 1, Arrays.asList("a"));
 103 
 104         list.remove(4);
 105         builder.nextRemove(4, "e");
 106 
 107         list.remove(0);
 108         builder.nextRemove(0, "aa");
 109         builder.endChange();
 110 
 111         assertEquals(list, Arrays.asList("b", "c", "d"));
 112 
 113         observer.check1AddRemove(observableList, Arrays.asList("a"), 0, 0);
 114 
 115     }
 116     
 117     @Test
 118     public void testAddRemove_4() {
 119         builder.beginChange();
 120 
 121         list.add("e");
 122         builder.nextAdd(4, 5);
 123 
 124         list.remove(1);
 125         builder.nextRemove(1, "b");
 126 
 127         list.add(1, "bb");
 128         builder.nextAdd(1, 2);
 129 
 130         builder.endChange();
 131 
 132         assertEquals(list, Arrays.asList("a", "bb", "c", "d", "e"));
 133 
 134         observer.checkAddRemove(0, observableList, Arrays.asList("b"), 1, 2);
 135         observer.checkAddRemove(1, observableList, Collections.EMPTY_LIST, 4, 5);
 136     }
 137 
 138     //RT-37089
 139     @Test
 140     public void testAddRemove_5() {
 141         builder.beginChange();
 142 
 143         list.addAll(1, Arrays.asList("x", "y"));
 144         builder.nextAdd(1, 3);
 145 
 146         list.remove(2);
 147         builder.nextRemove(2, "y");
 148 
 149         builder.endChange();
 150 
 151         observer.check1AddRemove(observableList, Collections.EMPTY_LIST, 1, 2);
 152 
 153     }
 154 
 155     @Test
 156     public void testAdd() {
 157         builder.beginChange();
 158 
 159         list.add(1, "aa");
 160         builder.nextAdd(1, 2);
 161         list.add(5, "e");
 162         builder.nextAdd(5, 6);
 163         list.add(1, "aa");
 164         builder.nextAdd(1, 2);
 165         list.add(2, "aa");
 166         builder.nextAdd(2, 3);
 167         list.add(4, "aa");
 168         builder.nextAdd(4, 5);
 169 
 170         builder.endChange();
 171         
 172         assertEquals(list, Arrays.asList("a", "aa","aa","aa","aa", "b", "c", "d", "e"));
 173 
 174         observer.checkAddRemove(0, observableList, Collections.EMPTY_LIST, 1, 5);
 175         observer.checkAddRemove(1, observableList, Collections.EMPTY_LIST, 8, 9);
 176 
 177     }
 178 
 179     @Test
 180     public void testRemove() {
 181         builder.beginChange();
 182         list.remove(0);
 183         builder.nextRemove(0, "a");
 184         list.remove(2);
 185         builder.nextRemove(2, "d");
 186         list.remove(0);
 187         builder.nextRemove(0, "b");
 188         builder.endChange();
 189 
 190         assertEquals(list, Arrays.asList("c"));
 191 
 192         observer.checkAddRemove(0, observableList, Arrays.asList("a", "b"), 0, 0);
 193         observer.checkAddRemove(1, observableList, Arrays.asList("d"), 1, 1);
 194 
 195     }
 196 
 197     @Test
 198     public void testRemove_2() {
 199         builder.beginChange();
 200         list.remove(1);
 201         builder.nextRemove(1, "b");
 202         list.remove(2);
 203         builder.nextRemove(2, "d");
 204         list.remove(0);
 205         builder.nextRemove(0, "a");
 206         builder.endChange();
 207 
 208         assertEquals(list, Arrays.asList("c"));
 209 
 210         observer.checkAddRemove(0, observableList, Arrays.asList("a", "b"), 0, 0);
 211         observer.checkAddRemove(1, observableList, Arrays.asList("d"), 1, 1);
 212 
 213     }
 214 
 215     @Test
 216     public void testUpdate() {
 217         builder.beginChange();
 218         builder.nextUpdate(1);
 219         builder.nextUpdate(0);
 220         builder.nextUpdate(3);
 221         builder.endChange();
 222 
 223         observer.checkUpdate(0, observableList, 0, 2);
 224         observer.checkUpdate(1, observableList, 3, 4);
 225     }
 226 
 227     @Test
 228     public void testUpdate_2() {
 229         builder.beginChange();
 230         builder.nextUpdate(3);
 231         builder.nextUpdate(1);
 232         builder.nextUpdate(0);
 233         builder.nextUpdate(0);
 234         builder.nextUpdate(2);
 235         builder.endChange();
 236 
 237         observer.checkUpdate(0, observableList, 0, 4);
 238     }
 239 
 240     @Test
 241     public void testPermutation() {
 242         builder.beginChange();
 243 
 244         builder.nextPermutation(0, 4, new int[] {3, 2, 1, 0});
 245         builder.nextPermutation(1, 4, new int[] {3, 2, 1});
 246         builder.endChange();
 247 
 248         observer.check1Permutation(observableList, new int[] {1, 2, 3, 0});
 249     }
 250 
 251     @Test
 252     public void testUpdateAndAddRemove() {
 253         builder.beginChange();
 254         builder.nextUpdate(1);
 255         builder.nextUpdate(2);
 256         list.remove(2);
 257         builder.nextRemove(2, "c");
 258         list.add(2, "cc");
 259         list.add(3, "ccc");
 260         builder.nextAdd(2, 4);
 261         builder.nextUpdate(2);
 262         list.remove(2);
 263         builder.nextRemove(2, "cc");
 264         list.remove(3);
 265         builder.nextRemove(3, "d");
 266         list.add(0, "aa");
 267         builder.nextAdd(0, 1);
 268         builder.endChange();
 269 
 270         assertEquals(list, Arrays.asList("aa", "a", "b", "ccc"));
 271 
 272         observer.checkAddRemove(0, observableList, Collections.EMPTY_LIST, 0, 1);
 273         observer.checkAddRemove(1, observableList, Arrays.asList("c", "d"), 3, 4);
 274         observer.checkUpdate(2, observableList, 2, 3);
 275     }
 276 
 277     @Test
 278     public void testUpdateAndAddRemove_2() {
 279         builder.beginChange();
 280         builder.nextUpdate(0);
 281         builder.nextUpdate(1);
 282         list.add(1,"aaa");
 283         list.add(1,"aa");
 284         builder.nextAdd(1, 3);
 285         builder.endChange();
 286 
 287         assertEquals(list, Arrays.asList("a", "aa", "aaa", "b", "c", "d"));
 288 
 289         observer.checkAddRemove(0, observableList, Collections.EMPTY_LIST, 1, 3);
 290         observer.checkUpdate(1, observableList, 0, 1);
 291         observer.checkUpdate(2, observableList, 3, 4);
 292     }
 293 
 294     @Test
 295     public void testUpdateAndAddRemove_3() {
 296         builder.beginChange();
 297         builder.nextUpdate(2);
 298         builder.nextUpdate(3);
 299         list.add(1,"aa");
 300         builder.nextAdd(1, 2);
 301         list.remove(0);
 302         builder.nextRemove(0, "a");
 303         builder.endChange();
 304 
 305         assertEquals(list, Arrays.asList("aa", "b", "c", "d"));
 306 
 307         observer.checkAddRemove(0, observableList, Arrays.asList("a"), 0, 1);
 308         observer.checkUpdate(1, observableList, 2, 4);
 309     }
 310 
 311     @Test
 312     public void testUpdateAndPermutation() {
 313         builder.beginChange();
 314 
 315         builder.nextUpdate(1);
 316         builder.nextUpdate(2);
 317         builder.nextPermutation(1, 4, new int[] {3, 2, 1});
 318         builder.endChange();
 319 
 320         observer.checkPermutation(0, observableList, 1, 4, new int[] {3, 2, 1});
 321         observer.checkUpdate(1, observableList, 2, 4);
 322     }
 323 
 324     @Test
 325     public void testUpdateAndPermutation_2() {
 326         builder.beginChange();
 327 
 328         builder.nextUpdate(0);
 329         builder.nextUpdate(2);
 330         builder.nextPermutation(0, 4, new int[] {1, 3, 2, 0});
 331         builder.endChange();
 332 
 333         observer.checkPermutation(0, observableList, 0, 4, new int[] {1, 3, 2, 0});
 334         observer.checkUpdate(1, observableList, 1, 3);
 335     }
 336 
 337     @Test
 338     public void testAddAndPermutation() {
 339         builder.beginChange();
 340 
 341         builder.nextAdd(1, 2); // as-if "b" was added
 342         builder.nextPermutation(0, 3, new int[] { 2, 0, 1}); // new order is "b", "c", "a", "d"
 343 
 344         builder.endChange();
 345          // "c", "a", "d" before "b" was added
 346         observer.checkPermutation(0, observableList, 0, 3, new int[] {1, 0, 2});
 347 
 348         observer.checkAddRemove(1, observableList, Collections.EMPTY_LIST, 0, 1);
 349     }
 350 
 351     @Test
 352     public void testRemoveAndPermutation() {
 353         builder.beginChange();
 354 
 355         List<String> removed = Arrays.asList("bb", "bbb");
 356 
 357         builder.nextRemove(2, removed);
 358         builder.nextPermutation(0, 3, new int[] {2, 0, 1});
 359 
 360         builder.endChange();
 361 
 362         observer.checkPermutation(0, observableList, 0, 6, new int[] {4, 0, 2, 3, 1, 5});
 363         observer.checkAddRemove(1, observableList, removed, 1, 1);
 364 
 365     }
 366 
 367     @Test
 368     public void testAddRemoveAndPermutation() {
 369         builder.beginChange();
 370 
 371         // Expect list to be "b", "c1", "c2", "d"
 372         List<String> removed = Arrays.asList("c1", "c2");
 373         // After add: "a", "b", "c1", "c2", "d"
 374         builder.nextAdd(0, 1);
 375         // After replace "a", "b", "c", "d"
 376         builder.nextReplace(2, 3, removed);
 377         builder.nextPermutation(1, 4, new int[] {3, 1, 2});
 378 
 379         builder.endChange();
 380 
 381         observer.checkPermutation(0, observableList, 0, 4, new int[] {3, 1, 2, 0});
 382         observer.checkAddRemove(1, observableList, removed, 0, 2);
 383     }
 384 
 385     @Test
 386     public void testPermutationAndAddRemove() {
 387         builder.beginChange();
 388 
 389         // Expect list to be "b", "c1", "c2", "d"
 390         // After perm "b", "c2", "d", "c1"
 391         builder.nextPermutation(1, 4, new int[] {3, 1, 2});
 392         // After add: "a", "b", "c2", "d", "c1"
 393         builder.nextAdd(0, 1);
 394         builder.nextReplace(2, 3, Arrays.asList("c2"));
 395         builder.nextRemove(4, Arrays.asList("c1"));
 396 
 397         builder.endChange();
 398 
 399         observer.checkPermutation(0, observableList, 1, 4, new int[] {3, 1, 2});
 400         observer.checkAddRemove(1, observableList, Collections.EMPTY_LIST, 0, 1);
 401         observer.checkAddRemove(2, observableList, Arrays.asList("c2"), 2, 3);
 402         observer.checkAddRemove(3, observableList, Arrays.asList("c1"), 4, 4);
 403     }
 404 
 405     @Test
 406     public void testPermutationAddRemoveAndPermutation() {
 407 
 408         builder.beginChange();
 409         // Expect list to be "b", "c1", "d"
 410         List<String> removed = Arrays.asList("c1");
 411         // After perm: "c1", "b", "d"
 412         builder.nextPermutation(0, 2, new int[] { 1, 0 });
 413         // After add: "a", "c1", "b", "d"
 414         builder.nextAdd(0, 1);
 415         // After remove/add "a", "b", "c", "d"
 416         builder.nextRemove(1, removed);
 417         builder.nextAdd(2, 3);
 418         // After permutation "a", "c", "d", "b"
 419         builder.nextPermutation(1, 4, new int[] {3, 1, 2});
 420 
 421         builder.endChange();
 422 
 423         // When combined, it's from the expected list:
 424         // permutation to "c1", "d", "b"
 425         observer.checkPermutation(0, observableList, 0, 3, new int[] {2, 0, 1});
 426         // add remove to "a", "c", "d", "b"
 427         observer.checkAddRemove(1, observableList, removed, 0, 2);
 428     }
 429 
 430     @Test(expected=IllegalStateException.class)
 431     public void testNextAddWithoutBegin() {
 432         builder.nextAdd(0, 1);
 433     }
 434 
 435     @Test(expected=IllegalStateException.class)
 436     public void testNextRemoveWithoutBegin() {
 437         builder.nextRemove(0, (String)null);
 438     }
 439 
 440     @Test(expected=IllegalStateException.class)
 441     public void testNextRemove2WithoutBegin() {
 442         builder.nextRemove(0, Collections.EMPTY_LIST);
 443     }
 444 
 445     @Test(expected=IllegalStateException.class)
 446     public void testNextUpdateWithoutBegin() {
 447         builder.nextUpdate(0);
 448     }
 449 
 450     @Test(expected=IllegalStateException.class)
 451     public void testNextSetWithoutBegin() {
 452         builder.nextSet(0, null);
 453     }
 454 
 455     @Test(expected=IllegalStateException.class)
 456     public void testNextReplaceWithoutBegin() {
 457         builder.nextReplace(0, 1, Collections.EMPTY_LIST);
 458     }
 459     
 460     @Test
 461     public void testEmpty() {
 462         builder.beginChange();
 463         builder.endChange();
 464         
 465         observer.check0();
 466     }
 467     
 468     @Test
 469     public void testToString_Update() {
 470         observableList.removeListener(observer);
 471         observableList.addListener((ListChangeListener.Change<? extends String> change) -> {
 472             assertNotNull(change.toString());
 473         });
 474         builder.beginChange();
 475         
 476         builder.nextUpdate(0);
 477         
 478         builder.endChange();
 479     }
 480     
 481     @Test
 482     public void testToString_Add() {
 483         observableList.removeListener(observer);
 484         observableList.addListener((ListChangeListener.Change<? extends String> change) -> {
 485             assertNotNull(change.toString());
 486         });
 487         builder.beginChange();
 488         
 489         builder.nextAdd(0, 1);
 490         
 491         builder.endChange();
 492     }
 493     
 494     @Test
 495     public void testToString_Remove() {
 496         observableList.removeListener(observer);
 497         observableList.addListener((ListChangeListener.Change<? extends String> change) -> {
 498             assertNotNull(change.toString());
 499         });
 500         builder.beginChange();
 501         
 502         builder.nextRemove(0, "");
 503         
 504         builder.endChange();
 505     }
 506     
 507     @Test
 508     public void testToString_Composed() {
 509         observableList.removeListener(observer);
 510         observableList.addListener((ListChangeListener.Change<? extends String> change) -> {
 511             assertNotNull(change.toString());
 512         });
 513         builder.beginChange();
 514         
 515         builder.nextUpdate(0);
 516         
 517         builder.nextAdd(0, 3);
 518         
 519         builder.endChange();
 520     }
 521     
 522     @Test
 523     public void testToString_Permutation() {
 524         observableList.removeListener(observer);
 525         observableList.addListener((ListChangeListener.Change<? extends String> change) -> {
 526             assertNotNull(change.toString());
 527         });
 528         builder.beginChange();
 529         
 530         builder.nextPermutation(0, 2, new int[] {1, 0});
 531         
 532         builder.endChange();
 533     }
 534 
 535 }