/**
   * Move All Sor Records from one person to another.
   *
   * @param fromPerson person losing sor records.
   * @param toPerson person receiving sor records.
   * @return Result of move. Validation errors if they occurred or the Person receiving sor records.
   */
  public boolean moveAllSystemOfRecordPerson(Person fromPerson, Person toPerson) {
    // get the list of sor person records that will be moving.
    List<SorPerson> sorPersonList = personRepository.getSoRRecordsForPerson(fromPerson);

    // move each sorRecord
    for (final SorPerson sorPerson : sorPersonList) {
      moveSystemOfRecordPerson(fromPerson, toPerson, sorPerson);
    }

    Set<? extends Identifier> oldIdentifiers = fromPerson.getIdentifiers();
    Set<? extends IdCard> oldIdCards = fromPerson.getIdCards();

    this.personRepository.deletePerson(fromPerson);
    logger.info("moveAllSystemOfRecordPerson: Deleted From Person");
    for (Identifier identifier : oldIdentifiers) {

      if (toPerson.getIdentifiersByType().get(identifier.getType().getName()) == null) {
        Identifier oldIdentifierAttachedTotoPerson =
            toPerson.addIdentifier(identifier.getType(), identifier.getValue());
        /// if type of this identifier don't exist then add this identifier as primary and not
        // deleted

        oldIdentifierAttachedTotoPerson.setDeleted(false);
        oldIdentifierAttachedTotoPerson.setPrimary(true);
      }
      // and if this exist then add this identifier as deleted and no primary
      else {
        Identifier oldIdentifierAttachedTotoPerson =
            toPerson.addIdentifier(identifier.getType(), identifier.getValue());
        /// if type of this identifier don't exist then add this identifier as primary and not
        // deleted

        oldIdentifierAttachedTotoPerson.setDeleted(true);
        oldIdentifierAttachedTotoPerson.setPrimary(false);
        ;
      }
    }
    for (IdCard oldIdCard : oldIdCards) {
      if (toPerson.getPrimaryIdCard() == null) {
        toPerson.addIDCard(oldIdCard);
      } else {
        if (oldIdCard.isPrimary()) oldIdCard.setPrimary(false);
        toPerson.addIDCard(oldIdCard);
      }
    }

    this.personRepository.savePerson(toPerson);

    return true;
  }
 @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = IllegalArgumentException.class)
 public void updateChangeExpDate(final Identifier identifierToUpdate, final Date changeExpDate) {
   final Person person =
       this.findPersonByIdentifier(
           identifierToUpdate.getType().getName(), identifierToUpdate.getValue());
   if (person == null)
     throw new IllegalArgumentException(
         format(
             "The person with the provided identifier [%s] does not exist",
             identifierToUpdate.getValue()));
   Identifier identifier =
       person.findIdentifierByValue(
           identifierToUpdate.getType().getName(), identifierToUpdate.getValue());
   identifier.setChangeExpirationDate(changeExpDate);
 }
  public void setConfirmationMessage(
      final ServiceExecutionResult<Person> serviceExecutionResult,
      final ReconciliationResult reconciliationResult,
      final MessageContext context) {
    // if reconciliation result is EXACT or MAYBE then only a role was added, not a new person.
    // a force add, would result in no reconciliationResult.

    if (reconciliationResult != null) {
      if (reconciliationResult.getReconciliationType()
              == ReconciliationResult.ReconciliationType.EXACT
          || reconciliationResult.getReconciliationType()
              == ReconciliationResult.ReconciliationType.MAYBE) {
        context.addMessage(new MessageBuilder().info().code("roleAdded").build());
        return;
      }
    }

    final Person person = serviceExecutionResult.getTargetObject();
    final Identifier netId =
        person.getPrimaryIdentifiersByType().get(this.preferredPersonIdentifierType);

    if (person.getCurrentActivationKey() != null) {
      final MessageResolver message =
          new MessageBuilder()
              .info()
              .code("personAddedFinalConfirm")
              .arg(netId.getValue())
              .arg(person.getCurrentActivationKey().asString())
              .build();
      context.addMessage(message);
    } else {
      context.addMessage(
          new MessageBuilder()
              .info()
              .code("personAddedFinalConfirm")
              .arg(netId.getValue())
              .arg("TempKey")
              .build());
    }
  }
  @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = IllegalArgumentException.class)
  public boolean change(Identifier internalId, String changedId) {
    // check if both identifier are of the same type

    if (internalId == null || StringUtils.isEmpty(changedId)) {
      throw new IllegalArgumentException("new or old identifer couldn't be null");
    }
    if (internalId.getValue().equals(changedId)) {
      logger.debug("new identifier is the same no need to change existing identifier");
      return false;
    }

    final Person person =
        this.findPersonByIdentifier(internalId.getType().getName(), internalId.getValue());
    if (person == null)
      throw new IllegalArgumentException(
          format(
              "The person with the provided identifier [%s] does not exist",
              internalId.getValue()));

    final Person person2 = this.findPersonByIdentifier(internalId.getType().getName(), changedId);
    if (person2 != null && person.getId() != person2.getId()) {
      throw new IllegalArgumentException(
          format("The person with the proposed new identifier [%s] already exists.", changedId));
    }
    Map<String, Identifier> primaryIds = person.getPrimaryIdentifiersByType();
    Identifier currId = primaryIds.get(internalId.getType().getName());
    if (currId == null)
      throw new IllegalStateException("Provided Id doesnt exist as primary identifier ");
    if (currId.getValue().equals(changedId)) {
      logger.debug(
          format(
              "The provided new primary identifier [%s] already assigned to the person.",
              changedId));
    } else if (!currId.getValue().equals(internalId.getValue())) {
      throw new IllegalArgumentException(
          format(
              "The provided primary identifier [%s] does not match the current primary identifier",
              internalId.getValue()));
    }
    // check if the provided new identifier is already there, and if so, do the update, otherwise -
    // do the insert.
    Identifier providedId = person.findIdentifierByValue(internalId.getType().getName(), changedId);
    if (providedId == null) {

      providedId = person.addIdentifier(internalId.getType(), changedId);
    }
    providedId.setPrimary(true);
    providedId.setDeleted(false);
    currId.setPrimary(false);
    currId.setDeleted(true);
    return true;
  }