Versão ALPHA! Este artigo está em versão 'Alpha' e, portanto, não foi ainda revisado corretamente

Estado/comportamento de objetos nos filtros

Introdução

Para facilitar a usabilidade de uma aplicação, é comum disponibilizarmos um dropdown-list para o usuário filtrar o resultado de uma consulta. Por exemplo, o usuário da aplicação quer filtrar as disciplinas de um determinado aluno pelos seguintes status: todas as disciplinas, disciplinas que o aluno esteja matriculado ou disciplinas que o aluno tenha dependência.

Exemplo de uma dropdown-list utilizado para filtros:

Primeira opção

Antes tudo, é necessário implementar no teste referente a esse buscador, os testes para todos os filtros desejados, para ler mais sobre filtros clique aqui.

Na implementação do filtro dentro do método newPager(), teríamos a seguinte implementação:

private NativeSql newPager(String what, AlunoKey key, RequestWrapper wrapper) {
  String nome = wrapper.param("nome");
                                                                                 
  DisciplinaStatus status = wrapper.enumParam(DisciplinaStatus.class, "status");

  DisciplinaStatus statusMatriculado = status != null ? DisciplinaStatus.MATRICULADO : null;

  DisciplinaStatus statusDependencia = status != null ? DisciplinaStatus.DEPENDENCIA : null;

  return newSelect(what)

      .add("where DISCIPLINA.ALUNO_ID = ?").param(key.getId())

      .addIf("and DISCIPLINA.MATRICULADO = ?").paramNotNull(statusMatriculado.booleanValue())
      .addIf("and DISCIPLINA.DEPENDENCIA = ?").paramNotNull(statusDependencia.booleanValue())

      .addIf("and ALUNO.NOME like concat('%', ?, '%')").paramNotNull(nome)

      .add("order by")
      .add("ALUNO.NOME");
}

Para entender como será construída a consulta desse filtro, em tempo de execução será considerado:
Todos os registros: statusMatriculado e statusDependencia serão iguais a null
Alunos matriculados: statusMatriculado = true e statusDependencia = false
Alunos com dependência: statusMatriculado = false e statusDependencia = true

O enum DisciplinaStatus tem os tipos de status disponíveis para o filtro: TODAS, MATRICULADO e DEPENDENCIA. Nossa primeira solução é utilizar um operador ternário que seria o mesmo que utizar um if para obter o filtro invocado, e caso filtro não tenha sido incodado é atribuido nullpara o status, assim ao construir a consulta SQL será decidido qual status será incluso.

O código DisciplinaStatus statusMatriculado = status != null ? DisciplinaStatus.MATRICULADO : null; seria o mesmo que:

if(status != null) {
  status = DisciplinaStatus.MATRICULADO;
}else{
  status = null;
}

Note então que o primeiro meio para resolver qual filtro será selecionado é utilizando o operador ternário para todas as combinações de filtros possíveis para esse filto. Essa solução funciona, mas não estamos tratando um tipo de DisciplinaStatus como objeto, que tem estado e comportamento. Abaixo veremos a mesma implementação sem utilizar operador ternário.

Segunda opção

Agora temos o enum DisciplinaStatus com a seguinte estrutura:

public enum DisciplinaStatus {

 TODAS("Todas"),
 MATRICULADO("Matriculado") {
   @Override
   public Boolean matriculadoValue() {
     return Boolean.TRUE;
   }

   @Override
   public Boolean depedenciaValue() {
     return Boolean.FALSE;
   }
 },

 DEPENDENCIA("Com dependência") {

   @Override
   public Boolean matriculadoValue() {
     return Boolean.FALSE;
   }

   @Override
   public Boolean depedenciaValue() {
     return Boolean.TRUE;
   }

 };

 private final String descricao;

 private DisciplinaStatus(String descricao) {
   this.descricao = descricao;
 }

 public String getDescricao() {
   return descricao;
 }

 public Boolean matriculadoValue() {
   return null;
 }

 public Boolean depedenciaValue() {
   return null;
 }

}

Conseguimos definir um estado distindo para cada tipo do enum DisciplinaStatus, então para cada instância teremos o seguinte comportamento:
TODOS: matriculadoValue() e depedenciaValue() retornarão null, esse é estado padrão.
MATRICULADO: matriculadoValue() retornará true e depedenciaValue() retornará false.
DEPENDENCIA: matriculadoValue() retornará false e depedenciaValue() retornará true.

Nesse momento sabemos quais estados de DisciplinaStatus terá o comportamento que esperamos em nosso filtro, para isso o método newPager() terá a estrutura abaixo:

private NativeSql newPager(String what, AlunoKey alunoKey, RequestWrapper wrapper) {
  String nome = wrapper.param("nome");

  DisciplinaStatus status = wrapper.enumParam(DisciplinaStatus.class, "status");
  status = status != null ? status : DisciplinaStatus.TODAS;

  return newSelect(what)

      .add("where DISCIPLINA.ALUNO_ID = ?").param(alunoKey.getId())

      .addIf("and DISCIPLINA.MATRICULADO = ?").paramNotNull(status.matriculadoValue())
      .addIf("and DISCIPLINA.DEPENDENCIA = ?").paramNotNull(status.depedenciaValue())

      .addIf("and ALUNO.NOME like concat('%', ?, '%')").paramNotNull(nome)

      .add("order by")
      .add("ALUNO.NOME");
}

Feito isso, temos apenas um operador ternário chegando se a variável status não é null, caso seja, o valor padrão é DisciplinaStatus.TODAS, caso contrário é a instância que foi construída a partir do filtro selecionado pelo usuário. Então para cada instância, teremos um comportamento distindo quando a variável de referência status chamar os métodos matriculadoValue() e depedenciaValue().

Códigos-fonte

BuscarDisciplinaGuice.java
DisciplinaStatus.java


 
 

objectos, Fábrica de Software LTDA

  • R. Demóstenes, 627. cj 123
  • 04614-013 - Campo Belo
  • São Paulo - SP - Brasil
  • +55 11 5093-8640
  • +55 11 2359-8699
  • contato@objectos.com.br