private boolean hasPersonServiceExemption(
     GiafProfessionalData giafProfessionalData,
     LocalDate beginDate,
     LocalDate endDate,
     ServiceExemption serviceExemption,
     String serviceExemptionGiafId,
     DateTime creationDate,
     DateTime modifiedDate) {
   for (PersonProfessionalExemption personProfessionalExemption :
       giafProfessionalData.getPersonProfessionalExemptionsSet()) {
     if (personProfessionalExemption instanceof PersonServiceExemption) {
       PersonServiceExemption personServiceExemption =
           (PersonServiceExemption) personProfessionalExemption;
       if (personServiceExemption.getAnulationDate() == null
           && Objects.equals(personServiceExemption.getBeginDate(), beginDate)
           && Objects.equals(endDate, personServiceExemption.getEndDate())
           && Objects.equals(serviceExemption, personServiceExemption.getServiceExemption())
           && Objects.equals(
               serviceExemptionGiafId, personServiceExemption.getServiceExemptionGiafId())
           && Objects.equals(creationDate, personServiceExemption.getCreationDate())
           && Objects.equals(modifiedDate, personServiceExemption.getModifiedDate())) {
         return true;
       }
     }
   }
   return false;
 }
  @Override
  public List<Modification> processChanges(GiafMetadata metadata, PrintWriter log, Logger logger)
      throws Exception {
    List<Modification> modifications = new ArrayList<>();
    PersistentSuportGiaf oracleConnection = PersistentSuportGiaf.getInstance();
    PreparedStatement preparedStatement = oracleConnection.prepareStatement(getQuery());
    ResultSet result = preparedStatement.executeQuery();
    int count = 0;
    int news = 0;
    int notImported = 0;
    int dontExist = 0;
    Set<Person> importedButInvalid = new HashSet<Person>();
    while (result.next()) {
      count++;
      String numberString = result.getString("emp_num");
      Person person = metadata.getPerson(numberString, logger);
      if (person == null) {
        logger.debug("Invalid person with number: " + numberString);
        dontExist++;
        continue;
      }
      PersonProfessionalData personProfessionalData = person.getPersonProfessionalData();
      if (personProfessionalData == null) {
        logger.debug("Empty personProfessionalData: " + numberString);
        dontExist++;
        continue;
      }
      final GiafProfessionalData giafProfessionalData =
          personProfessionalData.getGiafProfessionalDataByGiafPersonIdentification(numberString);
      if (giafProfessionalData == null) {
        logger.debug("Empty giafProfessionalData: " + numberString);
        dontExist++;
        continue;
      }
      final String serviceExemptionGiafId = result.getString("tip_disp");
      final ServiceExemption serviceExemption = metadata.exemption(serviceExemptionGiafId);
      if (serviceExemption == null) {
        logger.debug(
            "Empty serviceExemption: "
                + serviceExemptionGiafId
                + " for person number: "
                + numberString);
        importedButInvalid.add(person);
      }
      String beginDateString = result.getString("DATA_INICIO");
      final LocalDate beginDate =
          Strings.isNullOrEmpty(beginDateString)
              ? null
              : new LocalDate(Timestamp.valueOf(beginDateString));
      if (beginDate == null) {
        logger.debug(
            "Empty beginDate. Person number: "
                + numberString
                + " ServiceExemption: "
                + serviceExemptionGiafId);
        importedButInvalid.add(person);
      }
      String endDateString = result.getString("DATA_FIM");
      final LocalDate endDate =
          Strings.isNullOrEmpty(endDateString)
              ? null
              : new LocalDate(Timestamp.valueOf(endDateString));
      if (beginDate != null && endDate != null) {
        if (beginDate.isAfter(endDate)) {
          logger.debug(
              "BeginDate after endDate. Person number: "
                  + numberString
                  + " begin: "
                  + beginDate
                  + " end: "
                  + endDate);
          importedButInvalid.add(person);
        }
      }
      String creationDateString = result.getString("data_criacao");
      if (Strings.isNullOrEmpty(creationDateString)) {
        logger.debug(
            "Empty creationDate. Person number: "
                + numberString
                + " ServiceExemption: "
                + serviceExemptionGiafId);
        notImported++;
        continue;
      }
      final DateTime creationDate = new DateTime(Timestamp.valueOf(creationDateString));

      String modifiedDateString = result.getString("data_alteracao");
      final DateTime modifiedDate =
          Strings.isNullOrEmpty(modifiedDateString)
              ? null
              : new DateTime(Timestamp.valueOf(modifiedDateString));

      if (!hasPersonServiceExemption(
          giafProfessionalData,
          beginDate,
          endDate,
          serviceExemption,
          serviceExemptionGiafId,
          creationDate,
          modifiedDate)) {
        modifications.add(
            new Modification() {
              @Override
              public void execute() {
                new PersonServiceExemption(
                    giafProfessionalData,
                    beginDate,
                    endDate,
                    serviceExemption,
                    serviceExemptionGiafId,
                    creationDate,
                    modifiedDate);
              }
            });
        news++;
      }
    }
    result.close();
    preparedStatement.close();

    int deleted = 0;
    int totalInFenix = 0;
    int repeted = 0;
    for (GiafProfessionalData giafProfessionalData :
        Bennu.getInstance().getGiafProfessionalDataSet()) {
      for (PersonProfessionalExemption personProfessionalExemption :
          giafProfessionalData.getPersonProfessionalExemptionsSet()) {
        if (personProfessionalExemption instanceof PersonServiceExemption
            && personProfessionalExemption.getAnulationDate() == null) {
          final PersonServiceExemption personServiceExemption =
              (PersonServiceExemption) personProfessionalExemption;
          int countThisPersonServiceExemptionOnGiaf =
              countThisPersonServiceExemptionOnGiaf(
                  oracleConnection, personServiceExemption, logger);
          if (countThisPersonServiceExemptionOnGiaf == 0) {
            modifications.add(
                new Modification() {
                  @Override
                  public void execute() {
                    personServiceExemption.setAnulationDate(new DateTime());
                  }
                });
            deleted++;
          } else {
            totalInFenix++;
            if (countThisPersonServiceExemptionOnGiaf > 1) {
              repeted += countThisPersonServiceExemptionOnGiaf - 1;
            }
          }
        }
      }
    }

    oracleConnection.closeConnection();
    log.println("-- Service Exemptions --");
    log.println("Total GIAF: " + count);
    log.println("New: " + news);
    log.println("Deleted: " + deleted);
    log.println("Not imported: " + notImported);
    log.println("Imported with errors: " + importedButInvalid.size());
    log.println("Repeted: " + repeted);
    log.println("Invalid persons: " + dontExist);
    log.println("Total Fénix: " + totalInFenix);
    log.println("Total Fénix without errors: " + (totalInFenix - importedButInvalid.size()));
    log.println("Missing in Fénix: " + (count - totalInFenix));
    return modifications;
  }