/**
* 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);
}
}