/**
   * Checks and verifies whether the ListDataListener has been reregistered properly. This will fail
   * if the change support fails to fire a change event when the instance changes.
   *
   * <p>Creates a SelectionInList on list1, then changes it to list2, modifies boths lists, and
   * finally checks whether the SelectionInList has fired the correct events.
   */
  private static void testReregistersListDataListener(
      ObservableList<Object> list1, ObservableList<Object> list2) {
    ListDataReport listDataReport1 = new ListDataReport();
    ListDataReport listDataReport2 = new ListDataReport();
    ListDataReport listDataReportSel = new ListDataReport();

    SelectionInList<Object> sil = new SelectionInList<Object>((ListModel) list1);

    // Change the list model.
    // Changes on list1 shall not affect the SelectionInList.
    // Changes in list2 shall be the same as for the SelectionInList.
    sil.setListModel(list2);

    list1.addListDataListener(listDataReport1);
    list2.addListDataListener(listDataReport2);
    sil.addListDataListener(listDataReportSel);

    // Modify both list models.
    list1.add("one1");
    list1.add("two1");
    list1.add("three1");
    list1.add("four1");
    list1.remove(1);
    list1.remove(0);
    list1.set(0, "newOne1");
    list1.set(1, "newTwo1");

    assertEquals("Events counted for list model 1", 8, listDataReport1.eventCount());
    assertEquals("No events counted for list model 2", 0, listDataReport2.eventCount());
    assertEquals("No events counted for the SelectionInList", 0, listDataReportSel.eventCount());

    list2.add("one2");
    list2.add("two2");
    list2.add("three2");
    list2.remove(1);
    list2.set(0, "newOne2");

    assertEquals("Events counted for list model 2", 5, listDataReport2.eventCount());
    assertEquals("Events counted for the SelectionInList", 5, listDataReportSel.eventCount());

    // Compare the event lists.
    assertEquals(
        "Events for list2 and SelectionInList differ.", listDataReport2, listDataReportSel);
  }
  /** Checks that list data events from an underlying are reported by the SelectionInList. */
  public static void testFiresListModelListDataEvents() {
    PropertyChangeReport changeReport = new PropertyChangeReport();
    ListDataReport listDataReport1 = new ListDataReport();
    ListDataReport listDataReport2 = new ListDataReport();

    ArrayListModel<String> arrayListModel = new ArrayListModel<String>();
    SelectionInList<String> sil = new SelectionInList<String>((ListModel) arrayListModel);

    arrayListModel.addListDataListener(listDataReport1);
    sil.addListDataListener(listDataReport2);
    sil.addValueChangeListener(changeReport);

    arrayListModel.add("One");
    assertEquals("No list change.", changeReport.eventCount(), 0);
    assertEquals("An element has been added.", listDataReport2.eventCount(), 1);
    assertEquals("An element has been added.", listDataReport2.eventCountAdd(), 1);

    arrayListModel.addAll(Arrays.asList(new String[] {"two", "three", "four"}));
    assertEquals("No list change.", changeReport.eventCount(), 0);
    assertEquals("An element block has been added.", listDataReport2.eventCount(), 2);
    assertEquals("An element block has been added.", listDataReport2.eventCountAdd(), 2);

    arrayListModel.remove(0);
    assertEquals("An element has been removed.", listDataReport2.eventCount(), 3);
    assertEquals("No element has been added.", listDataReport2.eventCountAdd(), 2);
    assertEquals("An element has been removed.", listDataReport2.eventCountRemove(), 1);

    arrayListModel.set(1, "newTwo");
    assertEquals("An element has been replaced.", listDataReport2.eventCount(), 4);
    assertEquals("No element has been added.", listDataReport2.eventCountAdd(), 2);
    assertEquals("No element has been removed.", listDataReport2.eventCountRemove(), 1);
    assertEquals("An element has been changed.", listDataReport2.eventCountChange(), 1);

    // Compare the event counts of the list models listener
    // with the SelectionInList listener.
    assertEquals(
        "Add event counts are equal.",
        listDataReport1.eventCountAdd(),
        listDataReport2.eventCountAdd());
    assertEquals(
        "Remove event counts are equal.",
        listDataReport1.eventCountRemove(),
        listDataReport2.eventCountRemove());
    assertEquals(
        "Change event counts are equal.",
        listDataReport1.eventCountChange(),
        listDataReport2.eventCountChange());
  }
  /**
   * Tests the SelectionInList ListDataEvents fired during list changes. The transitions are {} ->
   * {} -> {a, b} -> {b, c} -> {a, b, c} -> {}.
   */
  public static void testListChangeEvents() {
    List<String> list1 = Collections.emptyList();
    List<String> list2 = Collections.emptyList();
    List<String> list3 = Arrays.asList("a", "b");
    List<String> list4 = Arrays.asList("b", "c");
    List<String> list5 = Arrays.asList("a", "b", "c");
    List<String> list6 = Collections.emptyList();

    SelectionInList<String> sil = new SelectionInList<String>(list1);
    ListDataReport report = new ListDataReport();
    sil.addListDataListener(report);

    sil.setList(list2);
    assertEquals("The transition {} -> {} fires no ListDataEvent.", 0, report.eventCount());

    report.clearEventList();
    sil.setList(list3);
    assertEquals("The transition {} -> {a, b} fires 1 add event.", 1, report.eventCount());
    assertEvent(
        "The transition {} -> {a, b} fires an add event with interval[0, 1].",
        ListDataEvent.INTERVAL_ADDED,
        0,
        1,
        report.lastEvent());

    report.clearEventList();
    sil.setList(list4);
    assertEquals("The transition {a, b} -> {b, c} fires 1 add event.", 1, report.eventCount());
    assertEvent(
        "The transition {a, b} -> {b, c} fires an add event with interval[0, 1].",
        ListDataEvent.CONTENTS_CHANGED,
        0,
        1,
        report.lastEvent());

    report.clearEventList();
    sil.setList(list5);
    assertEquals("The transition {a, b} -> {b, c, d} fires two events.", 2, report.eventCount());
    assertEvent(
        "The transition {b, c} -> {a, b, c} fires an add event with interval[2, 2].",
        ListDataEvent.INTERVAL_ADDED,
        2,
        2,
        report.previousEvent());
    assertEvent(
        "The transition {b, c} -> {a, b, c} fires a contents changed with interval[0, 1].",
        ListDataEvent.CONTENTS_CHANGED,
        0,
        1,
        report.lastEvent());

    report.clearEventList();
    sil.setList(list6);
    assertEquals("The transition {b, c, d} -> {} fires one event.", 1, report.eventCount());
    assertEvent(
        "The transition {b, c, d} -> {} fires a remove event with interval[0, 1].",
        ListDataEvent.INTERVAL_REMOVED,
        0,
        2,
        report.lastEvent());
  }