/** * Copyright (C) 2018, 2022, 2024, 2025 Adrien Hopkins * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package sevenUnitsGUI; import java.util.Comparator; import java.util.Objects; /** * A comparator that compares strings using a filter. * * @param type of element being compared * * @author Adrien Hopkins * @since 2019-01-15 * @since v0.1.0 */ final class FilterComparator implements Comparator { /** * The filter that the comparator is filtered by. * * @since 2019-01-15 * @since v0.1.0 */ private final String filter; /** * The comparator to use if the arguments are otherwise equal. * * @since 2019-01-15 * @since v0.1.0 */ private final Comparator comparator; /** * Whether or not the comparison is case-sensitive. * * @since 2019-04-14 * @since v0.2.0 */ private final boolean caseSensitive; /** * Creates the {@code FilterComparator}. * * @param filter * @since 2019-01-15 * @since v0.1.0 */ public FilterComparator(final String filter) { this(filter, null); } /** * Creates the {@code FilterComparator}. * * @param filter string to filter by * @param comparator comparator to fall back to if all else fails, null is * compareTo. * @throws NullPointerException if filter is null * @since 2019-01-15 * @since v0.1.0 */ public FilterComparator(final String filter, final Comparator comparator) { this(filter, comparator, false); } /** * Creates the {@code FilterComparator}. * * @param filter string to filter by * @param comparator comparator to fall back to if all else fails, null is * compareTo. * @param caseSensitive whether or not the comparator is case-sensitive * @throws NullPointerException if filter is null * @since 2019-04-14 * @since v0.2.0 */ public FilterComparator(final String filter, final Comparator comparator, final boolean caseSensitive) { Objects.requireNonNull(filter, "filter must not be null."); this.filter = caseSensitive ? filter : filter.toLowerCase(); this.comparator = comparator; this.caseSensitive = caseSensitive; } /** * Compares two objects according to whether or not they match a filter. * Objects whose string representation starts with the filter's text go * first, then those that contain it but don't start with it, then those that * don't contain it. Objects in the same order here are sorted by their * string representation's compareTo or the provided comparator. */ @Override public int compare(final T arg0, final T arg1) { // if this is case insensitive, make them lowercase final String str0, str1; if (this.caseSensitive) { str0 = arg0.toString(); str1 = arg1.toString(); } else { str0 = arg0.toString().toLowerCase(); str1 = arg1.toString().toLowerCase(); } // elements that start with the filter always go first if (str0.startsWith(this.filter) && !str1.startsWith(this.filter)) return -1; if (!str0.startsWith(this.filter) && str1.startsWith(this.filter)) return 1; // elements that contain the filter but don't start with them go next if (str0.contains(this.filter) && !str1.contains(this.filter)) return -1; if (!str0.contains(this.filter) && !str1.contains(this.filter)) return 1; // other elements go last if (this.comparator == null) return str0.compareTo(str1); return this.comparator.compare(arg0, arg1); } }