@Test
  public void testCreateThenUpdate() {
    c = new ChangeCollector();
    c.initialise(Arrays.asList(new Object[] {question3}));

    c.objectInserted(new ObjectInsertedEventMock("1", question1));
    c.objectInserted(new ObjectInsertedEventMock("2", question2));
    question1.setPreLabel("What is answer 1a?");
    question1.setAnswer("answer1a");
    c.objectUpdated(new ObjectUpdatedEventMock("1", question1, question1));
    question3.setPreLabel("What is answer 3a?");
    question3.setAnswer("answer3a");
    c.objectUpdated(new ObjectUpdatedEventMock("3", question3, question3));

    assertEquals(2, c.getCreate().size());
    createIterator = getCreateSorted(c).entrySet().iterator();
    createEntry = createIterator.next();
    assertEquals("1", createEntry.getValue().toExternalForm());
    assertEquals("answer1a", ((Question) createEntry.getKey()).getAnswer());
    createEntry = createIterator.next();
    assertEquals("2", createEntry.getValue().toExternalForm());
    assertEquals("answer2", ((Question) createEntry.getKey()).getAnswer());
    assertEquals(1, c.getUpdate().size());
    updateIterator = getUpdateSorted(c).iterator();
    assertEquals("answer3a", ((Question) updateIterator.next()).getAnswer());
    assertNull(c.getDelete());
  }
  @Test
  public void testDeleteInactive() {
    c = new ChangeCollector();
    question4.setActive(false);
    c.initialise(Arrays.asList(new Object[] {question4}));

    c.objectRetracted(new ObjectRetractedEventMock("4", question4));

    assertNull(c.getCreate());
    assertNull(c.getUpdate());
    assertNull(c.getDelete());
  }
  @Test
  public void testUpdateOnlyChangedAnswerAndIsSame() {
    c = new ChangeCollector();
    c.initialise(Arrays.asList(new Object[] {question5, answer5New}));

    question5.setAnswer("answer5New");
    c.objectUpdated(new ObjectUpdatedEventMock("5", question5, question5));
    c.objectRetracted(new ObjectRetractedEventMock("a", answer5New));

    assertNull(c.getCreate());
    assertNull(c.getUpdate());
    assertNull(c.getDelete());
  }
  @Test
  public void testUpdateActiveToInactive() {
    c = new ChangeCollector();
    c.initialise(Arrays.asList(new Object[] {question4}));

    question4.setActive(false);
    c.objectUpdated(new ObjectUpdatedEventMock("4", question4, question4));

    assertNull(c.getCreate());
    assertNull(c.getUpdate());
    assertEquals(1, c.getDelete().size());
    deleteIterator = getDeleteSorted(c).iterator();
    assertEquals("question4", ((ItemId) deleteIterator.next()).getId());
  }
  @Test
  public void testUpdateOnlyChangedAnswerAndIsDifferent() {
    c = new ChangeCollector();
    c.initialise(Arrays.asList(new Object[] {question5, answer5Old}));

    question5.setAnswer("answer5New");
    c.objectUpdated(new ObjectUpdatedEventMock("5", question5, question5));
    c.objectRetracted(new ObjectRetractedEventMock("a", answer5Old));

    assertNull(c.getCreate());
    assertEquals(1, c.getUpdate().size());
    updateIterator = getUpdateSorted(c).iterator();
    assertEquals("answer5New", ((Question) updateIterator.next()).getAnswer());
    assertNull(c.getDelete());
  }
  @Test
  public void testDeleteThenRecreate() {
    c = new ChangeCollector();
    c.initialise(Arrays.asList(new Object[] {question1}));

    c.objectRetracted(new ObjectRetractedEventMock("1", question1));
    question1.setPreLabel("What is answer 1a?");
    question1.setAnswer("answer1a");
    c.objectInserted(new ObjectInsertedEventMock("1", question1));

    assertNull(c.getCreate());
    assertEquals(1, c.getUpdate().size());
    updateIterator = getUpdateSorted(c).iterator();
    assertEquals("answer1a", ((Question) updateIterator.next()).getAnswer());
    assertNull(c.getDelete());
  }
  @Test
  public void testUpdateInactiveToActive() {
    c = new ChangeCollector();
    question4.setActive(false);
    c.initialise(Arrays.asList(new Object[] {question4}));

    question4.setActive(true);
    question4.setAnswer("answer4Active");
    c.objectUpdated(new ObjectUpdatedEventMock("4", question4, question4));

    assertEquals(1, c.getCreate().size());
    createIterator = getCreateSorted(c).entrySet().iterator();
    createEntry = createIterator.next();
    assertEquals("4", createEntry.getValue().toExternalForm());
    assertEquals("answer4Active", ((Question) createEntry.getKey()).getAnswer());
    assertNull(c.getUpdate());
    assertNull(c.getDelete());
  }
  @Test
  public void testDelete() {
    c = new ChangeCollector();
    c.initialise(Arrays.asList(new Object[] {question1, question2, invalidAnswer1, dummy}));

    c.objectRetracted(new ObjectRetractedEventMock("2", question2));
    c.objectRetracted(new ObjectRetractedEventMock("dummy", dummy));
    c.objectRetracted(new ObjectRetractedEventMock("1", question1));
    c.objectRetracted(new ObjectRetractedEventMock("ia1", invalidAnswer1));

    assertNull(c.getCreate());
    assertNull(c.getUpdate());
    assertEquals(3, c.getDelete().size());
    deleteIterator = getDeleteSorted(c).iterator();
    assertEquals("question1", ((ItemId) deleteIterator.next()).getId());
    assertEquals("question1", ((InvalidAnswer) deleteIterator.next()).getQuestionId());
    assertEquals("question2", ((ItemId) deleteIterator.next()).getId());
  }
  @Test
  public void testCreateThenDelete() {
    c = new ChangeCollector();
    c.initialise(Arrays.asList(new Object[] {question3}));

    c.objectInserted(new ObjectInsertedEventMock("2", question2));
    c.objectInserted(new ObjectInsertedEventMock("1", question1));
    c.objectRetracted(new ObjectRetractedEventMock("3", question3));
    c.objectRetracted(new ObjectRetractedEventMock("2", question2));

    assertEquals(1, c.getCreate().size());
    createIterator = getCreateSorted(c).entrySet().iterator();
    createEntry = createIterator.next();
    assertEquals("1", createEntry.getValue().toExternalForm());
    assertEquals("answer1", ((Question) createEntry.getKey()).getAnswer());
    assertNull(c.getUpdate());
    assertEquals(1, c.getDelete().size());
    deleteIterator = getDeleteSorted(c).iterator();
    assertEquals("question3", ((ItemId) deleteIterator.next()).getId());
  }
  @Test
  public void testUpdate() {
    c = new ChangeCollector();
    c.initialise(Arrays.asList(new Object[] {question1, question2, dummy}));

    question1.setPreLabel("What is answer 1a?");
    question1.setAnswer("answer1a");
    question2.setPreLabel("What is answer 2a?");
    question2.setAnswer("answer2a");

    c.objectUpdated(new ObjectUpdatedEventMock("2", question2, question2));
    c.objectUpdated(new ObjectUpdatedEventMock("dummy", dummy, dummy));
    c.objectUpdated(new ObjectUpdatedEventMock("1", question1, question1));

    assertNull(c.getCreate());
    assertEquals(2, c.getUpdate().size());
    updateIterator = getUpdateSorted(c).iterator();
    assertEquals("answer1a", ((Question) updateIterator.next()).getAnswer());
    assertEquals("answer2a", ((Question) updateIterator.next()).getAnswer());
    assertNull(c.getDelete());
  }
  @Test
  public void testCreate() {
    c = new ChangeCollector();
    c.initialise(Collections.emptySet());

    c.objectInserted(new ObjectInsertedEventMock("2", question2));
    c.objectInserted(new ObjectInsertedEventMock("dummy", dummy));
    c.objectInserted(new ObjectInsertedEventMock("1", question1));
    c.objectInserted(new ObjectInsertedEventMock("ia1", invalidAnswer1));

    assertEquals(3, c.getCreate().size());
    createIterator = getCreateSorted(c).entrySet().iterator();
    createEntry = createIterator.next();
    assertEquals("1", createEntry.getValue().toExternalForm());
    assertEquals("answer1", ((Question) createEntry.getKey()).getAnswer());
    createEntry = createIterator.next();
    assertEquals("2", createEntry.getValue().toExternalForm());
    assertEquals("answer2", ((Question) createEntry.getKey()).getAnswer());
    createEntry = createIterator.next();
    assertEquals("ia1", createEntry.getValue().toExternalForm());
    assertEquals("invalid answer 1", ((InvalidAnswer) createEntry.getKey()).getReason());
    assertNull(c.getUpdate());
    assertNull(c.getDelete());
  }
 private Map<Object, FactHandle> getCreateSorted(ChangeCollector c2) {
   TreeMap<Object, FactHandle> map = new TreeMap<Object, FactHandle>(new ItemComparator());
   map.putAll(c.getCreate());
   return map;
 }