alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (RowFilter.java)

This example Java source code file (RowFilter.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

after, andfilter, before, entry, equal, generalfilter, illegalargumentexception, m\,i, math, number, object, orfilter, regex, rowfilter, util

The RowFilter.java Java example source code

/*
 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package javax.swing;

import java.util.ArrayList;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 * <code>RowFilter is used to filter out entries from the
 * model so that they are not shown in the view.  For example, a
 * <code>RowFilter associated with a JTable might
 * only allow rows that contain a column with a specific string. The
 * meaning of <em>entry depends on the component type.
 * For example, when a filter is
 * associated with a <code>JTable, an entry corresponds to a
 * row; when associated with a <code>JTree, an entry corresponds
 * to a node.
 * <p>
 * Subclasses must override the <code>include method to
 * indicate whether the entry should be shown in the
 * view.  The <code>Entry argument can be used to obtain the values in
 * each of the columns in that entry.  The following example shows an
 * <code>include method that allows only entries containing one or
 * more values starting with the string "a":
 * <pre>
 * RowFilter<Object,Object> startsWithAFilter = new RowFilter<Object,Object>() {
 *   public boolean include(Entry<? extends Object, ? extends Object> entry) {
 *     for (int i = entry.getValueCount() - 1; i >= 0; i--) {
 *       if (entry.getStringValue(i).startsWith("a")) {
 *         // The value starts with "a", include it
 *         return true;
 *       }
 *     }
 *     // None of the columns start with "a"; return false so that this
 *     // entry is not shown
 *     return false;
 *   }
 * };
 * </pre>
 * <code>RowFilter has two formal type parameters that allow
 * you to create a <code>RowFilter for a specific model. For
 * example, the following assumes a specific model that is wrapping
 * objects of type <code>Person.  Only Persons
 * with an age over 20 will be shown:
 * <pre>
 * RowFilter<PersonModel,Integer> ageFilter = new RowFilter<PersonModel,Integer>() {
 *   public boolean include(Entry<? extends PersonModel, ? extends Integer> entry) {
 *     PersonModel personModel = entry.getModel();
 *     Person person = personModel.getPerson(entry.getIdentifier());
 *     if (person.getAge() > 20) {
 *       // Returning true indicates this row should be shown.
 *       return true;
 *     }
 *     // Age is <= 20, don't show it.
 *     return false;
 *   }
 * };
 * PersonModel model = createPersonModel();
 * TableRowSorter<PersonModel> sorter = new TableRowSorter<PersonModel>(model);
 * sorter.setRowFilter(ageFilter);
 * </pre>
 *
 * @param <M> the type of the model; for example PersonModel
 * @param <I> the type of the identifier; when using
 *            <code>TableRowSorter this will be Integer
 * @see javax.swing.table.TableRowSorter
 * @since 1.6
 */
public abstract class RowFilter<M,I> {
    /**
     * Enumeration of the possible comparison values supported by
     * some of the default <code>RowFilters.
     *
     * @see RowFilter
     * @since 1.6
     */
    public enum ComparisonType {
        /**
         * Indicates that entries with a value before the supplied
         * value should be included.
         */
        BEFORE,

        /**
         * Indicates that entries with a value after the supplied
         * value should be included.
         */
        AFTER,

        /**
         * Indicates that entries with a value equal to the supplied
         * value should be included.
         */
        EQUAL,

        /**
         * Indicates that entries with a value not equal to the supplied
         * value should be included.
         */
        NOT_EQUAL
    }

    /**
     * Throws an IllegalArgumentException if any of the values in
     * columns are {@literal <} 0.
     */
    private static void checkIndices(int[] columns) {
        for (int i = columns.length - 1; i >= 0; i--) {
            if (columns[i] < 0) {
                throw new IllegalArgumentException("Index must be >= 0");
            }
        }
    }

    /**
     * Returns a <code>RowFilter that uses a regular
     * expression to determine which entries to include.  Only entries
     * with at least one matching value are included.  For
     * example, the following creates a <code>RowFilter that
     * includes entries with at least one value starting with
     * "a":
     * <pre>
     *   RowFilter.regexFilter("^a");
     * </pre>
     * <p>
     * The returned filter uses {@link java.util.regex.Matcher#find}
     * to test for inclusion.  To test for exact matches use the
     * characters '^' and '$' to match the beginning and end of the
     * string respectively.  For example, "^foo$" includes only rows whose
     * string is exactly "foo" and not, for example, "food".  See
     * {@link java.util.regex.Pattern} for a complete description of
     * the supported regular-expression constructs.
     *
     * @param regex the regular expression to filter on
     * @param indices the indices of the values to check.  If not supplied all
     *               values are evaluated
     * @return a <code>RowFilter implementing the specified criteria
     * @throws NullPointerException if <code>regex is
     *         <code>null
     * @throws IllegalArgumentException if any of the <code>indices
     *         are < 0
     * @throws PatternSyntaxException if <code>regex is
     *         not a valid regular expression.
     * @see java.util.regex.Pattern
     */
    public static <M,I> RowFilter regexFilter(String regex,
                                                       int... indices) {
        return (RowFilter<M,I>)new RegexFilter(Pattern.compile(regex),
                                               indices);
    }

    /**
     * Returns a <code>RowFilter that includes entries that
     * have at least one <code>Date value meeting the specified
     * criteria.  For example, the following <code>RowFilter includes
     * only entries with at least one date value after the current date:
     * <pre>
     *   RowFilter.dateFilter(ComparisonType.AFTER, new Date());
     * </pre>
     *
     * @param type the type of comparison to perform
     * @param date the date to compare against
     * @param indices the indices of the values to check.  If not supplied all
     *               values are evaluated
     * @return a <code>RowFilter implementing the specified criteria
     * @throws NullPointerException if <code>date is
     *          <code>null
     * @throws IllegalArgumentException if any of the <code>indices
     *         are < 0 or <code>type is
     *         <code>null
     * @see java.util.Calendar
     * @see java.util.Date
     */
    public static <M,I> RowFilter dateFilter(ComparisonType type,
                                            Date date, int... indices) {
        return (RowFilter<M,I>)new DateFilter(type, date.getTime(), indices);
    }

    /**
     * Returns a <code>RowFilter that includes entries that
     * have at least one <code>Number value meeting the
     * specified criteria.  For example, the following
     * filter will only include entries with at
     * least one number value equal to 10:
     * <pre>
     *   RowFilter.numberFilter(ComparisonType.EQUAL, 10);
     * </pre>
     *
     * @param type the type of comparison to perform
     * @param indices the indices of the values to check.  If not supplied all
     *               values are evaluated
     * @return a <code>RowFilter implementing the specified criteria
     * @throws IllegalArgumentException if any of the <code>indices
     *         are < 0, <code>type is null
     *         or <code>number is null
     */
    public static <M,I> RowFilter numberFilter(ComparisonType type,
                                            Number number, int... indices) {
        return (RowFilter<M,I>)new NumberFilter(type, number, indices);
    }

    /**
     * Returns a <code>RowFilter that includes entries if any
     * of the supplied filters includes the entry.
     * <p>
     * The following example creates a <code>RowFilter that will
     * include any entries containing the string "foo" or the string
     * "bar":
     * <pre>
     *   List<RowFilter<Object,Object>> filters = new ArrayList<RowFilter<Object,Object>>(2);
     *   filters.add(RowFilter.regexFilter("foo"));
     *   filters.add(RowFilter.regexFilter("bar"));
     *   RowFilter<Object,Object> fooBarFilter = RowFilter.orFilter(filters);
     * </pre>
     *
     * @param filters the <code>RowFilters to test
     * @throws IllegalArgumentException if any of the filters
     *         are <code>null
     * @throws NullPointerException if <code>filters is null
     * @return a <code>RowFilter implementing the specified criteria
     * @see java.util.Arrays#asList
     */
    public static <M,I> RowFilter orFilter(
            Iterable<? extends RowFilter filters) {
        return new OrFilter<M,I>(filters);
    }

    /**
     * Returns a <code>RowFilter that includes entries if all
     * of the supplied filters include the entry.
     * <p>
     * The following example creates a <code>RowFilter that will
     * include any entries containing the string "foo" and the string
     * "bar":
     * <pre>
     *   List<RowFilter<Object,Object>> filters = new ArrayList<RowFilter<Object,Object>>(2);
     *   filters.add(RowFilter.regexFilter("foo"));
     *   filters.add(RowFilter.regexFilter("bar"));
     *   RowFilter<Object,Object> fooBarFilter = RowFilter.andFilter(filters);
     * </pre>
     *
     * @param filters the <code>RowFilters to test
     * @return a <code>RowFilter implementing the specified criteria
     * @throws IllegalArgumentException if any of the filters
     *         are <code>null
     * @throws NullPointerException if <code>filters is null
     * @see java.util.Arrays#asList
     */
    public static <M,I> RowFilter andFilter(
            Iterable<? extends RowFilter filters) {
        return new AndFilter<M,I>(filters);
    }

    /**
     * Returns a <code>RowFilter that includes entries if the
     * supplied filter does not include the entry.
     *
     * @param filter the <code>RowFilter to negate
     * @return a <code>RowFilter implementing the specified criteria
     * @throws IllegalArgumentException if <code>filter is
     *         <code>null
     */
    public static <M,I> RowFilter notFilter(RowFilter filter) {
        return new NotFilter<M,I>(filter);
    }

    /**
     * Returns true if the specified entry should be shown;
     * returns false if the entry should be hidden.
     * <p>
     * The <code>entry argument is valid only for the duration of
     * the invocation.  Using <code>entry after the call returns
     * results in undefined behavior.
     *
     * @param entry a non-<code>null object that wraps the underlying
     *              object from the model
     * @return true if the entry should be shown
     */
    public abstract boolean include(Entry<? extends M, ? extends I> entry);

    //
    // WARNING:
    // Because of the method signature of dateFilter/numberFilter/regexFilter
    // we can NEVER add a method to RowFilter that returns M,I. If we were
    // to do so it would be possible to get a ClassCastException during normal
    // usage.
    //

    /**
     * An <code>Entry object is passed to instances of
     * <code>RowFilter, allowing the filter to get the value of the
     * entry's data, and thus to determine whether the entry should be shown.
     * An <code>Entry object contains information about the model
     * as well as methods for getting the underlying values from the model.
     *
     * @param <M> the type of the model; for example PersonModel
     * @param <I> the type of the identifier; when using
     *            <code>TableRowSorter this will be Integer
     * @see javax.swing.RowFilter
     * @see javax.swing.DefaultRowSorter#setRowFilter(javax.swing.RowFilter)
     * @since 1.6
     */
    public static abstract class Entry<M, I> {
        /**
         * Creates an <code>Entry.
         */
        public Entry() {
        }

        /**
         * Returns the underlying model.
         *
         * @return the model containing the data that this entry represents
         */
        public abstract M getModel();

        /**
         * Returns the number of values in the entry.  For
         * example, when used with a table this corresponds to the
         * number of columns.
         *
         * @return number of values in the object being filtered
         */
        public abstract int getValueCount();

        /**
         * Returns the value at the specified index.  This may return
         * <code>null.  When used with a table, index
         * corresponds to the column number in the model.
         *
         * @param index the index of the value to get
         * @return value at the specified index
         * @throws IndexOutOfBoundsException if index < 0 or
         *         >= getValueCount
         */
        public abstract Object getValue(int index);

        /**
         * Returns the string value at the specified index.  If
         * filtering is being done based on <code>String values
         * this method is preferred to that of <code>getValue
         * as <code>getValue(index).toString() may return a
         * different result than <code>getStringValue(index).
         * <p>
         * This implementation calls <code>getValue(index).toString()
         * after checking for <code>null.  Subclasses that provide
         * different string conversion should override this method if
         * necessary.
         *
         * @param index the index of the value to get
         * @return {@code non-null} string at the specified index
         * @throws IndexOutOfBoundsException if index < 0 ||
         *         >= getValueCount
         */
        public String getStringValue(int index) {
            Object value = getValue(index);
            return (value == null) ? "" : value.toString();
        }

        /**
         * Returns the identifer (in the model) of the entry.
         * For a table this corresponds to the index of the row in the model,
         * expressed as an <code>Integer.
         *
         * @return a model-based (not view-based) identifier for
         *         this entry
         */
        public abstract I getIdentifier();
    }


    private static abstract class GeneralFilter extends RowFilter<Object,Object> {
        private int[] columns;

        GeneralFilter(int[] columns) {
            checkIndices(columns);
            this.columns = columns;
        }

        public boolean include(Entry<? extends Object,? extends Object> value){
            int count = value.getValueCount();
            if (columns.length > 0) {
                for (int i = columns.length - 1; i >= 0; i--) {
                    int index = columns[i];
                    if (index < count) {
                        if (include(value, index)) {
                            return true;
                        }
                    }
                }
            }
            else {
                while (--count >= 0) {
                    if (include(value, count)) {
                        return true;
                    }
                }
            }
            return false;
        }

        protected abstract boolean include(
              Entry<? extends Object,? extends Object> value, int index);
    }


    private static class RegexFilter extends GeneralFilter {
        private Matcher matcher;

        RegexFilter(Pattern regex, int[] columns) {
            super(columns);
            if (regex == null) {
                throw new IllegalArgumentException("Pattern must be non-null");
            }
            matcher = regex.matcher("");
        }

        protected boolean include(
                Entry<? extends Object,? extends Object> value, int index) {
            matcher.reset(value.getStringValue(index));
            return matcher.find();
        }
    }


    private static class DateFilter extends GeneralFilter {
        private long date;
        private ComparisonType type;

        DateFilter(ComparisonType type, long date, int[] columns) {
            super(columns);
            if (type == null) {
                throw new IllegalArgumentException("type must be non-null");
            }
            this.type = type;
            this.date = date;
        }

        protected boolean include(
                Entry<? extends Object,? extends Object> value, int index) {
            Object v = value.getValue(index);

            if (v instanceof Date) {
                long vDate = ((Date)v).getTime();
                switch(type) {
                case BEFORE:
                    return (vDate < date);
                case AFTER:
                    return (vDate > date);
                case EQUAL:
                    return (vDate == date);
                case NOT_EQUAL:
                    return (vDate != date);
                default:
                    break;
                }
            }
            return false;
        }
    }




    private static class NumberFilter extends GeneralFilter {
        private boolean isComparable;
        private Number number;
        private ComparisonType type;

        NumberFilter(ComparisonType type, Number number, int[] columns) {
            super(columns);
            if (type == null || number == null) {
                throw new IllegalArgumentException(
                    "type and number must be non-null");
            }
            this.type = type;
            this.number = number;
            isComparable = (number instanceof Comparable);
        }

        @SuppressWarnings("unchecked")
        protected boolean include(
                Entry<? extends Object,? extends Object> value, int index) {
            Object v = value.getValue(index);

            if (v instanceof Number) {
                boolean compared = true;
                int compareResult;
                Class vClass = v.getClass();
                if (number.getClass() == vClass && isComparable) {
                    compareResult = ((Comparable)number).compareTo(v);
                }
                else {
                    compareResult = longCompare((Number)v);
                }
                switch(type) {
                case BEFORE:
                    return (compareResult > 0);
                case AFTER:
                    return (compareResult < 0);
                case EQUAL:
                    return (compareResult == 0);
                case NOT_EQUAL:
                    return (compareResult != 0);
                default:
                    break;
                }
            }
            return false;
        }

        private int longCompare(Number o) {
            long diff = number.longValue() - o.longValue();

            if (diff < 0) {
                return -1;
            }
            else if (diff > 0) {
                return 1;
            }
            return 0;
        }
    }


    private static class OrFilter<M,I> extends RowFilter {
        List<RowFilter filters;

        OrFilter(Iterable<? extends RowFilter filters) {
            this.filters = new ArrayList<RowFilter();
            for (RowFilter<? super M, ? super I> filter : filters) {
                if (filter == null) {
                    throw new IllegalArgumentException(
                        "Filter must be non-null");
                }
                this.filters.add(filter);
            }
        }

        public boolean include(Entry<? extends M, ? extends I> value) {
            for (RowFilter<? super M,? super I> filter : filters) {
                if (filter.include(value)) {
                    return true;
                }
            }
            return false;
        }
    }


    private static class AndFilter<M,I> extends OrFilter {
        AndFilter(Iterable<? extends RowFilter filters) {
            super(filters);
        }

        public boolean include(Entry<? extends M, ? extends I> value) {
            for (RowFilter<? super M,? super I> filter : filters) {
                if (!filter.include(value)) {
                    return false;
                }
            }
            return true;
        }
    }


    private static class NotFilter<M,I> extends RowFilter {
        private RowFilter<M,I> filter;

        NotFilter(RowFilter<M,I> filter) {
            if (filter == null) {
                throw new IllegalArgumentException(
                    "filter must be non-null");
            }
            this.filter = filter;
        }

        public boolean include(Entry<? extends M, ? extends I> value) {
            return !filter.include(value);
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java RowFilter.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.