private boolean extratoLineMatch(
      Lancamento lancto,
      ExtratoLancamentoTransaction line,
      Conta contaOrigemEsperada,
      Conta contaDestinoEsperada) {
    Calendar dataEsperada = line.getData();

    Comparator<Calendar> comparator = new TimeIgnoringComparator();

    boolean dataOk = comparator.compare(lancto.getData(), dataEsperada) == 0;

    boolean origemOk = lancto.getContaOrigem().equals(contaOrigemEsperada);
    boolean destinoOk = lancto.getContaDestino().equals(contaDestinoEsperada);
    boolean valorOk = lancto.getValor().equals(Math.abs(line.getValor()));

    return dataOk && origemOk && destinoOk && valorOk;
  }
  private ExtratoLineAnalyseResult syncTransactionLine(
      List<Lancamento> lancamentoSemExtratoList,
      ContaDAO contaDAO,
      ExtratoLancamentoTransaction line,
      ExtratoAnalyseSwitches switches) {
    ExtratoLineAnalyseResult result = new ExtratoLineAnalyseResult();
    result.setLinhaStatus(StatusLinha.TRANSACTION);

    Conta contaExtrato = resolveReference(contaDAO, line.getReferencia());

    if (contaExtrato == null) {
      result.setLancamentoStatus(LancamentoStatus.CONTA_NOT_FOUND);
      return result;
    }

    TimeIgnoringComparator comparator = new TimeIgnoringComparator();

    for (Lancamento lancamentoSemExtrato : lancamentoSemExtratoList) {
      // Ignora as linhas anteriores ao lancamento sem extrato
      int comparision = comparator.compare(lancamentoSemExtrato.getData(), line.getData());

      if (comparision < 0) {
        continue;
      } else if (comparision > 0) {
        // Se passou da data, sai do loop, não há correspondência
        break;
      }

      Conta contaOrigemEsperada;
      Conta contaDestinoEsperada;

      if (line.getValor() < 0) {
        // Dinheiro saiu da conta
        contaOrigemEsperada = banco;
        contaDestinoEsperada = contaExtrato;
      } else {
        // Dinheiro entrou na conta
        contaOrigemEsperada = contaExtrato;
        contaDestinoEsperada = banco;
      }

      if ((lancamentoSemExtrato.getExtrato() == null)
          && (extratoLineMatch(
              lancamentoSemExtrato, line, contaOrigemEsperada, contaDestinoEsperada))) {
        result.setLancamentoStatus(LancamentoStatus.UPDATE);

        lancamentoSemExtrato.setExtrato(line.getOrigem());

        if (switches.getRealize()) {
          lancamentoDAO.alterar(lancamentoSemExtrato);
        }

        result.setLancamento(lancamentoSemExtrato);

        return result;
      }
    }

    // Nenhum lançamento correspondente encontrado
    result.setLancamentoStatus(LancamentoStatus.NEW);

    Lancamento novoLancamento = new Lancamento();

    result.setLancamento(novoLancamento);

    novoLancamento.setData(line.getData());

    int n = (switches.getRealize() ? lancamentoDAO.getNextN(line.getData()) : -1);
    novoLancamento.setN(n);

    Conta contaOrigemEsperada;
    Conta contaDestinoEsperada;

    if (line.getValor() > 0) {
      // Dinheiro entrou da conta
      contaOrigemEsperada = contaExtrato;
      contaDestinoEsperada = banco;
    } else {
      // Dinheiro saiu na conta
      contaOrigemEsperada = banco;
      contaDestinoEsperada = contaExtrato;
    }

    novoLancamento.setContaOrigem(contaOrigemEsperada);
    novoLancamento.setContaDestino(contaDestinoEsperada);

    novoLancamento.setValor(Math.abs(line.getValor()));

    novoLancamento.setExtrato(line.getOrigem());

    if (switches.getRealize()) {
      lancamentoDAO.inserir(novoLancamento);
    }

    return result;
  }