@Before
  @Rollback(false)
  public void setup() {

    // CLEAR THE REPOSITORY
    nodeRepo.deleteAll(TestEntity.class);
    nodeRepo.deleteAll(TestEvent.class);
    assertTrue(nodeRepo.count(TestEntity.class) == 0);
    assertTrue(nodeRepo.count(TestEvent.class) == 0);

    // CLEAR THE REPOSITORY
    edgeRepo.deleteAll(TestPerson2PersonRelationship.class);
    assertTrue(edgeRepo.count(TestRelationship.class) == 0);

    // Save the findable person
    TestPerson findablePerson = TestPerson.randomPerson();
    TestPerson personB = TestPerson.randomPerson();
    nodeRepo.save(Arrays.asList(findablePerson, personB));
    findablePersonId = findablePerson.getId();

    // Save the findable edge
    EdgeLink findableEdge = new TestPerson2PersonRelationship(findablePerson, personB);
    findableEdgeId = findableEdge.getId();
    edgeRepo.save(findableEdge);
  }
  @Transactional
  @Test
  @Rollback(false)
  public void testNodeChangeDetectionCreationAddedOnFind() {

    clearCaches();

    TestPerson personA = nodeRepo.findByAppId(TestPerson.class, this.findablePersonId);

    NodeChangeData changeObject =
        personA.getMetaData(SharedGraphRepoKeys.NODE_CHANGEDATA_KEY, NodeChangeData.class);
    assertNotNull(changeObject);
    assertTrue(changeObject.getPropertyKeysChanged().isEmpty());
    assertTrue(changeObject.getAddedLinks().isEmpty());
    assertTrue(changeObject.getRemovedLinks().isEmpty());
  }
  @Transactional
  @Test
  @Rollback(false)
  public void testChangingRelationships() {

    TestPerson personA = TestPerson.randomPerson();
    TestPerson personB = TestPerson.randomPerson();

    nodeRepo.save(Arrays.asList(personA, personB));

    NodeChangeData changeDO = getChangeData(personA);
    assertNoChanges(changeDO);

    TestPerson2PersonRelationship relationA = new TestPerson2PersonRelationship(personA, personB);

    personA.getRelationMap().addRelation(relationA);

    assertRelationChange(changeDO, 1, 0);
  }
  @Transactional
  @Test
  @Rollback(false)
  public void testEdgePropertyChangeDetection() {

    TestPerson personA = TestPerson.randomPerson();
    TestPerson personB = TestPerson.randomPerson();

    nodeRepo.save(Arrays.asList(personA, personB));

    TestPerson2PersonRelationship relationA = new TestPerson2PersonRelationship(personA, personB);
    TestPerson2PersonRelationship relationB = new TestPerson2PersonRelationship(personB, personA);
    TestPerson2PersonRelationship relationC = new TestPerson2PersonRelationship(personB, personA);

    edgeRepo.save(Arrays.asList(relationA, relationB, relationC));

    // -- PERSON A -- Add 1 property --
    EdgeChangeData changeDO = getEdgeChangeData(relationA);
    assertNoChanges(changeDO);

    // Now CHANGE a property...
    relationA.getPropertyMap().put("X", "New Data");
    assertPropertyMapChanged(changeDO, 1);

    // -- PERSON B -- Add 3 property --
    changeDO = getEdgeChangeData(relationB);
    assertNoChanges(changeDO);
    // Now CHANGE a property...
    relationB.getPropertyMap().put("X", "X New Data");
    // The below does not add another...
    relationB.getPropertyMap().put("X", "Same key Changed");
    relationB.getPropertyMap().put("Y", "Y New Data");
    relationB.getPropertyMap().put("Z", "Z New Data");
    assertPropertyMapChanged(changeDO, 3);

    // -- PERSON C -- Remove a property --
    changeDO = getEdgeChangeData(relationC);
    assertNoChanges(changeDO);
    // Now CHANGE a property...
    relationC.getPropertyMap().remove("frequencyOfContact");
    assertPropertyMapChanged(changeDO, 1);
  }
  @Transactional
  @Test
  @Rollback(false)
  public void testNodeChangeDetectionCreationAddedOnSave() {

    TestPerson personA = TestPerson.randomPerson();

    NodeChangeData changeObject =
        personA.getMetaData(SharedGraphRepoKeys.NODE_CHANGEDATA_KEY, NodeChangeData.class);
    assertNull(changeObject);

    // Saving the node, adds the change detection so that the repo can get changes when it goes to
    // save.
    // Attached to the node, it goes out of scope with the node.
    nodeRepo.save(Arrays.asList(personA));

    changeObject =
        personA.getMetaData(SharedGraphRepoKeys.NODE_CHANGEDATA_KEY, NodeChangeData.class);
    assertNotNull(changeObject);
    assertTrue(changeObject.getPropertyKeysChanged().isEmpty());
    assertTrue(changeObject.getAddedLinks().isEmpty());
    assertTrue(changeObject.getRemovedLinks().isEmpty());
  }
  @Transactional
  @Test
  @Rollback(false)
  public void testEdgeChangeDetectionCreationOnLoadingRelations() {

    clearCaches();

    TestPerson foundPerson = nodeRepo.findByAppId(TestPerson.class, findablePersonId);
    NodeChangeData changeObject =
        foundPerson.getMetaData(SharedGraphRepoKeys.NODE_CHANGEDATA_KEY, NodeChangeData.class);
    assertNoChanges(changeObject);

    Map<String, Set<EdgeLink>> result =
        foundPerson.getRelationMap().getRelationships(IEdgeMap.Direction.BOTH);

    for (Set<EdgeLink> links : result.values()) {
      for (EdgeLink link : links) {
        EdgeChangeData edgeChangeData =
            link.getMetaData(SharedGraphRepoKeys.EDGE_CHANGEDATA_KEY, EdgeChangeData.class);
        assertNoChanges(edgeChangeData);
      }
    }
  }
  @Transactional
  @Test
  @Rollback(false)
  public void testEdgeChangeDetectionCreationAddedOnSave() {

    TestPerson personA = TestPerson.randomPerson();
    TestPerson personB = TestPerson.randomPerson();

    EdgeLink link = new TestPerson2PersonRelationship(personA, personB);

    EdgeChangeData changeObject =
        link.getMetaData(SharedGraphRepoKeys.EDGE_CHANGEDATA_KEY, EdgeChangeData.class);

    assertNull(changeObject);

    // Saving the node, adds the change detection so that the repo can get changes when it goes to
    // save.
    // Attached to the node, it goes out of scope with the node.
    edgeRepo.save(Arrays.asList(link));

    changeObject = link.getMetaData(SharedGraphRepoKeys.EDGE_CHANGEDATA_KEY, EdgeChangeData.class);
    assertNotNull(changeObject);
    assertTrue(changeObject.getPropertyKeysChanged().isEmpty());
  }
  // ===============================================================
  // CHANGE DETECTION -- !ON CHANGE GROUP!
  // --------------------------------
  // Ensure that the ChangeDetection group captures changes correctly
  // when making changes to nodes/edges/relations.
  // ===============================================================
  @Transactional
  @Test
  @Rollback(false)
  public void testNodePropertyChangeDetection() {

    TestPerson personA = TestPerson.randomPerson();
    TestPerson personB = TestPerson.randomPerson();
    TestPerson personC = TestPerson.randomPerson();

    nodeRepo.save(Arrays.asList(personA, personB, personC));

    // -- PERSON A -- Add 1 property --
    NodeChangeData changeDO = getChangeData(personA);
    assertNoChanges(changeDO);

    // Now CHANGE a property...
    personA.getPropertyMap().put("X", "New Data");
    assertPropertyMapChanged(changeDO, 1);

    // -- PERSON B -- Add 3 property --
    changeDO = getChangeData(personB);
    assertNoChanges(changeDO);
    // Now CHANGE a property...
    personB.getPropertyMap().put("X", "X New Data");
    // The below does not add another...
    personB.getPropertyMap().put("X", "Same key Changed");
    personB.getPropertyMap().put("Y", "Y New Data");
    personB.getPropertyMap().put("Z", "Z New Data");
    assertPropertyMapChanged(changeDO, 3);

    // -- PERSON C -- Remove a property --
    changeDO = getChangeData(personC);
    assertNoChanges(changeDO);
    // Now CHANGE a property...
    personC.getPropertyMap().remove("lastName");
    assertPropertyMapChanged(changeDO, 1);
  }