Merge RowFilter.andFilter with RowFilter.orFilter

1

I have a project that has a table and items to be filtered. They are a JComboBox category, a JTextField , and a JDateCooser date range.

I made all the filters separately with RowFilter.andFilter and now I need to put them together in a RowFilter.orFilter so that anyone can happen at any time.

I need to be able to filter the table data using different combinations of filled fields:

  
  • Category, Name, and Date Range Simultaneously (AndAnd Filters)
  •   
  • category only (FilterCateg)
  •   
  • only name (filterId, yes the name is the same)
  •   
  • only the date range (datafilter)
  •   
  • name and date range simultaneously (filterIdData)
  •   
  • category and name simultaneously (filterIdCateg)
  •   
  • category and date range simultaneously (FilterDatacateg)
  •   

They all need to be possible to happen according to what the program user decides to fill at the time of pressing the filter button.

Representing category by C, name by N, and date range by D What I need to happen would look like this:

((C && N && D) || (C) || (N) || (D) || (N && D) || (C && N) || (C && D))

Filters

    import java.awt.Dimension;
    import java.util.Date;
    import java.util.HashSet;
    import java.util.Set;
    import javax.swing.JButton;
    import javax.swing.JScrollBar;
    import javax.swing.JScrollPane;
    import javax.swing.RowFilter;
    import javax.swing.RowFilter.ComparisonType;
    import javax.swing.table.TableModel;
    import javax.swing.table.TableRowSorter;


    public class Filtros extends javax.swing.JFrame {

        private final int ITENS_POR_PAG = 5;

        public Filtros() {
            initComponents();
        }

        private void initComponents() {

            jScrollPane = new javax.swing.JScrollPane();
            table = new javax.swing.JTable();
            btnFirst = new javax.swing.JButton();
            btnPrevious = new javax.swing.JButton();
            btnNext = new javax.swing.JButton();
            btnLast = new javax.swing.JButton();
            lblCategoria = new javax.swing.JLabel();
            cbxCategoria = new javax.swing.JComboBox<>();
            jLabel1 = new javax.swing.JLabel();
            txtNome = new javax.swing.JTextField();
            btnFiltrar = new javax.swing.JButton();
            lblDataDeInicio = new javax.swing.JLabel();
            jdcDataDeInicio = new com.toedter.calendar.JDateChooser();
            lblDataDeFim = new javax.swing.JLabel();
            jdcDataDeFim = new com.toedter.calendar.JDateChooser();

            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

            jdcDataDeInicio.setDateFormatString("dd/MM/yyyy");
            jdcDataDeFim.setDateFormatString("dd/MM/yyyy");

            model = new MatriculaTableModel(JSONUtils.JSONtoList());
            table.setModel(model);
            sorter = new TableRowSorter<TableModel>(model);
            table.setRowSorter(sorter);   
            table.setDefaultRenderer(Date.class, new MatriculaTableRenderer());

            jScrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
                    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            jScrollPane.setPreferredSize(new Dimension(getPreferredSize().width - 20, table.getRowHeight() * ITENS_POR_PAG + table.getTableHeader().getPreferredSize().height));

            jScrollPane.setViewportView(table);


            btnFirst = new JButton("<<");
            btnFirst.addActionListener(e -> {
                JScrollBar bar = jScrollPane.getVerticalScrollBar();
                bar.setValue(0);
            });

            btnPrevious = new JButton("<");
            btnPrevious.addActionListener(e -> {
                int height = table.getRowHeight() * (ITENS_POR_PAG);
                JScrollBar bar = jScrollPane.getVerticalScrollBar();
                bar.setValue(bar.getValue() - height);
            });

            btnNext = new JButton(">");
            btnNext.addActionListener(e -> {
                int height = table.getRowHeight() * (ITENS_POR_PAG);
                JScrollBar bar = jScrollPane.getVerticalScrollBar();
                bar.setValue(bar.getValue() + height);
            });

            btnLast = new JButton(">>");
            btnLast.addActionListener(e -> {
                JScrollBar bar = jScrollPane.getVerticalScrollBar();
                bar.setValue(bar.getMaximum());
            });

            btnFiltrar.addActionListener(e -> {
                aplicaFiltros();
            });

            lblCategoria.setText("Categoria");

            cbxCategoria.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Todas", "Fundamental", "Médio" }));

            jLabel1.setText("Nome:");

            btnFiltrar.setText("Filtrar");

            lblDataDeInicio.setText("De:");

            lblDataDeFim.setText("Até:");

            javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
            getContentPane().setLayout(layout);
            layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                .addGroup(layout.createSequentialGroup()
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(layout.createSequentialGroup()
                                    .addGap(94, 94, 94)
                                    .addComponent(btnFirst)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(btnPrevious)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(btnNext)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(btnLast))
                                .addGroup(layout.createSequentialGroup()
                                    .addContainerGap()
                                    .addComponent(lblDataDeInicio)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(jdcDataDeInicio, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addGap(18, 18, 18)
                                    .addComponent(lblDataDeFim)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(jdcDataDeFim, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)))
                            .addGap(0, 16, Short.MAX_VALUE))
                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                            .addComponent(lblCategoria)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(cbxCategoria, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                            .addComponent(jLabel1)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(txtNome)
                            .addGap(18, 18, 18)
                            .addComponent(btnFiltrar)))
                    .addContainerGap())
            );
            layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addComponent(jScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 176, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(btnFirst)
                        .addComponent(btnPrevious)
                        .addComponent(btnNext)
                        .addComponent(btnLast))
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 21, Short.MAX_VALUE)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(cbxCategoria, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(lblCategoria)
                        .addComponent(jLabel1)
                        .addComponent(txtNome, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(btnFiltrar))
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(lblDataDeInicio)
                        .addComponent(jdcDataDeInicio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(lblDataDeFim)
                        .addComponent(jdcDataDeFim, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGap(20, 20, 20))
            );

            pack();
        }// </editor-fold>               

            public static void main(String args[]) {
            /* Set the Nimbus look and feel */
            //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
            /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
             * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
             */
            try {
                for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                    if ("Nimbus".equals(info.getName())) {
                        javax.swing.UIManager.setLookAndFeel(info.getClassName());
                        break;
                    }
                }
            } catch (ClassNotFoundException ex) {
                java.util.logging.Logger.getLogger(Filtros.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (InstantiationException ex) {
                java.util.logging.Logger.getLogger(Filtros.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                java.util.logging.Logger.getLogger(Filtros.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (javax.swing.UnsupportedLookAndFeelException ex) {
                java.util.logging.Logger.getLogger(Filtros.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            }
            //</editor-fold>

            /* Create and display the form */
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new Filtros().setVisible(true);
                }
            });
        }

     public void aplicaFiltros(){

            String nome = txtNome.getText().trim(),
                    categoria = cbxCategoria.getSelectedItem().toString().trim();      

            Date dataInicio = jdcDataDeInicio.getDate(),
                    dataFim = jdcDataDeFim.getDate();

            //Filtra Categoria, nome e intervalo de data (AND)
            Set<RowFilter<Object, Object>> filtrosAnd = new HashSet<>();
            String frmNome = String.format("^%s$", nome);
            filtrosAnd.add(RowFilter.regexFilter(frmNome, 1));

            if(!categoria.equals("Todas")) {
                String frmCateg = String.format("^%s$", categoria);
                filtrosAnd.add(RowFilter.regexFilter(frmCateg, 3));
            }

            filtrosAnd.add(RowFilter.dateFilter(ComparisonType.AFTER, dataInicio, 2));
            filtrosAnd.add(RowFilter.dateFilter(ComparisonType.BEFORE, dataFim, 2));
            sorter.setRowFilter(RowFilter.andFilter(filtrosAnd));

/*
            //Filtra só categoria
            Set<RowFilter<Object, Object>> filtroCateg = new HashSet<>();

            if(!categoria.equals("Todas")) {
                String frmCateg = String.format("^%s$", categoria);
                filtroCateg.add(RowFilter.regexFilter(frmCateg, 3));
            }
            sorter.setRowFilter(RowFilter.andFilter(filtroCateg));

            //Filtra só nome
            Set<RowFilter<Object, Object>> filtroId = new HashSet<>();

            frmNome = String.format("^%s$", nome);
            filtroId.add(RowFilter.regexFilter(frmNome, 1));

            sorter.setRowFilter(RowFilter.andFilter(filtroId));

            //Filtra só intervalo de data

            Set<RowFilter<Object, Object>> filtroData = new HashSet<>();

            filtroData.add(RowFilter.dateFilter(ComparisonType.AFTER, dataInicio, 2));
            filtroData.add(RowFilter.dateFilter(ComparisonType.BEFORE, dataFim, 2));

            sorter.setRowFilter(RowFilter.andFilter(filtroData));

            //Filtra nome e intervalo de data
            Set<RowFilter<Object, Object>> filtroIdData = new HashSet<>();

            frmNome = String.format("^%s$", nome);
            filtroId.add(RowFilter.regexFilter(frmNome, 1));

            filtroIdData.add(RowFilter.dateFilter(ComparisonType.AFTER, dataInicio, 2));
            filtroIdData.add(RowFilter.dateFilter(ComparisonType.BEFORE, dataFim, 2));

            sorter.setRowFilter(RowFilter.andFilter(filtroIdData));

            //Filtra categoria e nome
            Set<RowFilter<Object, Object>> filtroIdCateg = new HashSet<>();

            frmNome = String.format("^%s$", nome);
            filtroIdCateg.add(RowFilter.regexFilter(frmNome, 1));

            if(!categoria.equals("Todas")) {
                String frmCateg = String.format("^%s$", categoria);
                filtroIdCateg.add(RowFilter.regexFilter(frmCateg, 3));
            }
            sorter.setRowFilter(RowFilter.andFilter(filtroIdCateg));

            //Filtra categoria e intervalo de data
            Set<RowFilter<Object, Object>> filtroDataCateg = new HashSet<>();

            filtroDataCateg.add(RowFilter.dateFilter(ComparisonType.AFTER, dataInicio, 2));
            filtroDataCateg.add(RowFilter.dateFilter(ComparisonType.BEFORE, dataFim, 2));

            if(!categoria.equals("Todas")) {
                String frmCateg = String.format("^%s$", categoria);
                filtroDataCateg.add(RowFilter.regexFilter(frmCateg, 3));
            }
            sorter.setRowFilter(RowFilter.andFilter(filtroDataCateg)); */

        }

        // Variables declaration - do not modify                     
        private javax.swing.JButton btnFiltrar;
        private javax.swing.JButton btnFirst;
        private javax.swing.JButton btnLast;
        private javax.swing.JButton btnNext;
        private javax.swing.JButton btnPrevious;
        private javax.swing.JComboBox<String> cbxCategoria;
        private com.toedter.calendar.JDateChooser jdcDataDeFim;
        private javax.swing.JLabel jLabel1;
        private JScrollPane jScrollPane;
        private com.toedter.calendar.JDateChooser jdcDataDeInicio;
        private javax.swing.JLabel lblCategoria;
        private javax.swing.JLabel lblDataDeFim;
        private javax.swing.JLabel lblDataDeInicio;
        private javax.swing.JTable table;
        private javax.swing.JTextField txtNome;
            private MatriculaTableModel model;
        private TableRowSorter<TableModel> sorter;
        // End of variables declaration                   
    }

JSONUtils

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

public class JSONUtils {

    private static String strjson = null;

    private JSONUtils() {

        if (strjson == null)
            strjson = lerArquivo();
    }

    public static List<MatriculaModel> JSONtoList() {
        String str = lerArquivo();
        Type type = new TypeToken<List<MatriculaModel>>() {
        }.getType();

        Gson gson = new GsonBuilder().setDateFormat("dd/MM/yyyy").create();      

        List<MatriculaModel> lista = gson.fromJson(str, type);

        for (MatriculaModel teste : lista) {
            System.out.println(teste.getSelecionado());
            System.out.println(teste.getNome());
            System.out.println(teste.getData());
        }
        return lista;
    }

    private static String lerArquivo() {
        String linha = "";

        try {
            FileReader arq = new FileReader("C:\Users\maily\Documents\NetBeansProjects\Filtros\src\filtros\dados.json");
            BufferedReader lerArq = new BufferedReader(arq);

            linha = lerArq.readLine();
            /*
             * while (linha != null) { System.out.printf(linha); linha = lerArq.readLine();
             * // lê da segunda até a última linha }
             */
            arq.close();

        } catch (IOException e) {
            System.err.printf("Erro na abertura do arquivo: %s.\n", e.getMessage());
        }
        // System.out.println(linha);
        return linha;
    }

}

MatriculaModel

import java.util.Date;

public class MatriculaModel {
    private boolean selecionado;
    private String nome;
    private Date data;
    private String categoria;

    public boolean getSelecionado() {
        return selecionado;
    }

    public void setSelecionado(boolean selecionado) {
        this.selecionado = selecionado;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public Date getData() {
        return data;
    }

    public void setData(Date data) {
        this.data = data;
    }

    public String getCategoria() {
        return categoria;
    }

    public void setCategoria(String categoria) {
        this.categoria = categoria;
    }


}

MatriculaTableModel

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.table.AbstractTableModel;

public class MatriculaTableModel extends AbstractTableModel {


    private List<MatriculaModel> dados = new ArrayList<>();
    private final String[] colunas = {"Selecionar", "Nome", "Data", "Categoria"};

    public MatriculaTableModel(List<MatriculaModel> model) {
        this.dados = model;
    }


    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0:
                return Boolean.class;
            case 2:
                return Date.class;
            default:
                return super.getColumnClass(columnIndex);
        }
    }

    @Override
    public String getColumnName(int column){
        return colunas[column];
    }

    @Override
    public int getColumnCount() {
        return colunas.length;
    }

    @Override
    public int getRowCount() {
        return dados.size();
    }

    @Override
    public Object getValueAt(int linha, int coluna) {
        switch(coluna){
            case 0:
                return dados.get(linha).getSelecionado();
            case 1:
                return dados.get(linha).getNome();
            case 2:
                return dados.get(linha).getData();
            case 3:
                return dados.get(linha).getCategoria();
        }

        return null;
    }

    public void setValueAt(Object valor, int linha, int coluna) {
        MatriculaModel tm = dados.get(linha);
        switch (coluna) {
        case 0:
            tm.setSelecionado(new Boolean((Boolean) valor));
            break;
        }
        fireTableDataChanged();
    }

    public void addRow(MatriculaModel tm) {
        this.dados.add(tm);
        this.fireTableDataChanged();    
    }

    public void removeRow(int linha){
        this.dados.remove(linha);
        this.fireTableRowsDeleted(linha, linha);
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return columnIndex == 0; 
    }

    public void deletarLinhas() {
        this.dados.clear();
        this.fireTableDataChanged();
    }

}

MatriculaTableRenderer

import java.awt.Component;
import java.text.SimpleDateFormat;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

public class MatriculaTableRenderer extends DefaultTableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        switch (column) {
            case 2:
                setText(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(value));
                break;
            default:
                break;
        } 
        return this;
    }

    @Override
    protected void setValue(Object value) {
        super.setValue(value); 
    }      
}

data.json

[{"selecionado": false, "nome": "João", "data": "23/10/2000 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Maria", "data": "03/05/2006 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Pedro", "data": "30/02/2002 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Laura", "data": "03/07/2008 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Manoel", "data": "05/11/2018 00:00:00", "categoria": "Fundamental"},{"selecionado": false, "nome": "João", "data": "23/10/2000 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Maria", "data": "03/05/2006 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Pedro", "data": "30/02/2002 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Laura", "data": "03/07/2008 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Manoel", "data": "05/11/2018 00:00:00", "categoria": "Fundamental"},{"selecionado": false, "nome": "João", "data": "23/10/2000 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Maria", "data": "03/05/2006 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Pedro", "data": "30/02/2002 00:00:00", "categoria": "Fundamental"}, {"selecionado": false, "nome": "Laura", "data": "03/07/2008 00:00:00", "categoria": "Médio"}, {"selecionado": false, "nome": "Manoel", "data": "05/11/2018 00:00:00", "categoria": "Fundamental"}]

Download libs: JCalendar , Gson

    
asked by anonymous 11.11.2018 / 14:30

1 answer

1

You do not need this complexity at all, the filter you are using already does this, you just check the fields before adding them, those that are not filled in (are null or blank), you do not add in the andfilters list %.

If you always add all fields, the filter will always require all fields to be filled, or an exception will pop up when you try to apply the filters and there is some null or unfilled field. If you pass only those that the user populates, the filter is applied only to them.

See below:

    
11.11.2018 / 17:03