/**
  * Move one Sor Record from one person to another.
  *
  * @param fromPerson person losing sor record.
  * @param toPerson person receiving sor record.
  * @return Success or failure.
  */
 public boolean moveSystemOfRecordPerson(
     Person fromPerson, Person toPerson, SorPerson movingSorPerson) {
   movingSorPerson.setPersonId(toPerson.getId());
   updateCalculatedPersonsOnMoveOfSor(toPerson, fromPerson, movingSorPerson);
   this.personRepository.savePerson(fromPerson);
   this.personRepository.savePerson(toPerson);
   this.personRepository.saveSorPerson(movingSorPerson);
   return true;
 }
  public ServiceExecutionResult<Person> addPersonAndLink(
      final ReconciliationCriteria reconciliationCriteria, final Person person)
      throws IllegalArgumentException, IllegalStateException, SorPersonAlreadyExistsException {
    Assert.notNull(reconciliationCriteria, "reconciliationCriteria cannot be null.");
    Assert.notNull(person, "person cannot be null.");
    logger.info(" addPersonAndLink start");
    final ReconciliationResult result = this.criteriaCache.get(reconciliationCriteria);

    if (result == null) {
      throw new IllegalStateException("No ReconciliationResult found for provided criteria.");
    }

    for (final PersonMatch personMatch : result.getMatches()) {
      if (personMatch.getPerson().getId().equals(person.getId())) {
        addSorPersonAndLink(reconciliationCriteria, person);
        final Person savedPerson = this.personRepository.findByInternalId(person.getId());
        return new GeneralServiceExecutionResult<Person>(savedPerson);
      }
    }
    logger.info("addPersonAndLink end");
    throw new IllegalStateException("Person not found in ReconciliationResult.");
  }
  protected Person addSorPersonAndLink(
      final ReconciliationCriteria reconciliationCriteria, final Person person)
      throws SorPersonAlreadyExistsException {
    final SorPerson sorPerson = reconciliationCriteria.getSorPerson();
    final SorPerson registrySorPerson =
        this.findByPersonIdAndSorIdentifier(person.getId(), sorPerson.getSourceSor());

    if (registrySorPerson != null) {
      // throw new IllegalStateException("Oops! An error occurred. A person already exists from this
      // SoR linked to this ID!");
      throw new SorPersonAlreadyExistsException(registrySorPerson);
    }

    if (!StringUtils.hasText(sorPerson.getSorId())) {
      sorPerson.setSorId(this.identifierGenerator.generateNextString());
    }

    // Iterate over any sorRoles setting sorid and source id
    for (final SorRole sorRole : sorPerson.getRoles()) {
      setRoleIdAndSource(sorRole, sorPerson.getSourceSor());
    }

    sorPerson.setPersonId(person.getId());
    final SorPerson savedSorPerson = this.personRepository.saveSorPerson(sorPerson);

    // Create calculated roles.
    for (final SorRole newSorRole : savedSorPerson.getRoles()) {
      // let sor role elector decide if this new role can be converted to calculated one
      sorRoleElector.addSorRole(newSorRole, person);
    }

    // loop through all identifiers to see if addition of this new sor person will have a new
    // identifier created at calculated level
    for (final IdentifierAssigner ia : this.identifierAssigners) {
      ia.addIdentifierTo(sorPerson, person);
    }
    Person p = recalculatePersonBiodemInfo(person, savedSorPerson, RecalculationType.UPDATE, false);
    return this.personRepository.savePerson(p);
  }
 /**
  * Move one Sor Record from one person to another where the to person is not in the registry
  *
  * @param fromPerson person losing sor record.
  * @param movingSorPerson record that is moving.
  * @return Success or failure.
  */
 public boolean moveSystemOfRecordPersonToNewPerson(Person fromPerson, SorPerson movingSorPerson) {
   Person savedPerson =
       recalculatePersonBiodemInfo(
           this.personObjectFactory.getObject(), movingSorPerson, RecalculationType.ADD, false);
   for (final IdentifierAssigner ia : this.identifierAssigners) {
     ia.addIdentifierTo(movingSorPerson, savedPerson);
   }
   // remove identifiers assigned to new person from old person
   fromPerson.getIdentifiers().removeAll(savedPerson.getIdentifiers());
   updateCalculatedPersonsOnMoveOfSor(savedPerson, fromPerson, movingSorPerson);
   fromPerson = this.personRepository.savePerson(fromPerson);
   savedPerson = this.personRepository.savePerson(savedPerson);
   movingSorPerson.setPersonId(savedPerson.getId());
   this.personRepository.saveSorPerson(movingSorPerson);
   return true;
 }
  /**
   * Current workflow for converting an SorPerson into the actual Person.
   *
   * @param reconciliationCriteria the original search criteria.
   * @return the newly saved Person.
   */
  protected Person saveSorPersonAndConvertToCalculatedPerson(
      final ReconciliationCriteria reconciliationCriteria) {
    if (!StringUtils.hasText(reconciliationCriteria.getSorPerson().getSorId())) {
      reconciliationCriteria.getSorPerson().setSorId(this.identifierGenerator.generateNextString());
    }

    logger.info("Executing new code!!!!!!");

    // Iterate over any sorRoles setting sorid and source id
    for (final SorRole sorRole : reconciliationCriteria.getSorPerson().getRoles()) {
      setRoleIdAndSource(sorRole, reconciliationCriteria.getSorPerson().getSourceSor());
    }

    logger.info(
        "Creating sorPerson: person_id: " + reconciliationCriteria.getSorPerson().getPersonId());
    // Save Sor Person
    final SorPerson sorPerson =
        this.personRepository.saveSorPerson(reconciliationCriteria.getSorPerson());
    Person savedPerson =
        recalculatePersonBiodemInfo(
            this.personObjectFactory.getObject(), sorPerson, RecalculationType.ADD, false);
    savedPerson = this.personRepository.savePerson(savedPerson);

    for (final IdentifierAssigner ia : this.identifierAssigners) {
      ia.addIdentifierTo(sorPerson, savedPerson);
    }
    idCardGenerator.addIDCard(savedPerson);

    // Create calculated roles.
    for (final SorRole newSorRole : sorPerson.getRoles()) {
      // let sor role elector decide if this new role can be converted to calculated one
      sorRoleElector.addSorRole(newSorRole, savedPerson);
    }

    final Person newPerson = this.personRepository.savePerson(savedPerson);

    logger.info("Verifying Number of calculated Roles: " + newPerson.getRoles().size());

    // Now connect the SorPerson to the actual person
    sorPerson.setPersonId(newPerson.getId());
    this.personRepository.saveSorPerson(sorPerson);
    logger.info("Created sorPerson: person_id: " + sorPerson.getPersonId());

    return newPerson;
  }