ComparatorBuilder.java
/*
* Copyright 2019-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bremersee.comparator;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import org.bremersee.comparator.model.SortOrder;
import org.bremersee.comparator.model.SortOrderItem;
/**
* The comparator builder.
*
* @author Christian Bremer
*/
public interface ComparatorBuilder {
/**
* Creates a new comparator builder.
*
* @return the new comparator builder
*/
static ComparatorBuilder newInstance() {
return new DefaultComparatorBuilder();
}
/**
* Adds the given comparator to this builder.
*
* @param comparator the comparator (can be {@code null} - then no comparator is added)
* @return the comparator builder
*/
ComparatorBuilder add(Comparator<?> comparator);
/**
* Adds a default comparator for the given field (the value of the field must be comparable).
*
* @param field the field
* @return the comparator builder
*/
default ComparatorBuilder add(String field) {
return add(SortOrderItem.by(field));
}
/**
* Adds the given comparator for the given field name or path to this builder.
*
* @param field the field name or path (can be {@code null})
* @param comparator the comparator (can be {@code null} - then no comparator is added)
* @return the comparator builder
*/
default ComparatorBuilder add(String field, Comparator<?> comparator) {
return add(field, null, comparator);
}
/**
* Adds the given comparator for the given field name or path to this builder. A custom value
* extractor can be specified.
*
* @param field the field name or path (can be {@code null})
* @param valueExtractor the value extractor (can be {@code null})
* @param comparator the comparator (can be {@code null} - then no comparator is added)
* @return the comparator builder
*/
default ComparatorBuilder add(
String field,
ValueExtractor valueExtractor,
Comparator<?> comparator) {
return Optional.ofNullable(comparator)
.map(c -> add(new DelegatingComparator(field, valueExtractor, c)))
.orElse(this);
}
/**
* Creates and adds a value comparator for the given field ordering description.
*
* @param field the field ordering description (can be {@code null})
* @return the comparator builder
*/
default ComparatorBuilder add(SortOrderItem field) {
return add(field, null);
}
/**
* Creates and adds a value comparator for the given field ordering description. A custom value
* extractor can be specified.
*
* @param field the field ordering description (can be {@code null})
* @param valueExtractor the value extractor (can be {@code null})
* @return the comparator builder
*/
default ComparatorBuilder add(SortOrderItem field, ValueExtractor valueExtractor) {
return add(new ValueComparator(field, valueExtractor));
}
/**
* Creates and adds value comparators for the given field ordering descriptions.
*
* @param sortOrders the ordering descriptions (can be {@code null} - no comparator will be
* added)
* @return the comparator builder
*/
default ComparatorBuilder addAll(Collection<? extends SortOrderItem> sortOrders) {
return addAll(sortOrders, (ValueExtractor) null);
}
/**
* Creates and adds value comparators for the given field ordering descriptions. A custom value
* extractor can be specified.
*
* @param sortOrders the ordering descriptions (can be {@code null} - no comparator will be
* added)
* @param valueExtractor the value extractor (can be {@code null})
* @return the comparator builder
*/
default ComparatorBuilder addAll(
Collection<? extends SortOrderItem> sortOrders,
ValueExtractor valueExtractor) {
Optional.ofNullable(sortOrders)
.ifPresent(orders -> orders.stream()
.filter(Objects::nonNull)
.forEach(sortOrder -> add(sortOrder, valueExtractor)));
return this;
}
/**
* Adds comparators for the given sortOrders ordering descriptions.
*
* @param sortOrders the ordering descriptions (can be {@code null} - no comparator will be
* added)
* @param comparatorFunction the comparator function
* @return the comparator builder
*/
default ComparatorBuilder addAll(
Collection<? extends SortOrderItem> sortOrders,
Function<SortOrderItem, Comparator<?>> comparatorFunction) {
Optional.ofNullable(sortOrders)
.ifPresent(orders -> orders.stream()
.filter(Objects::nonNull)
.forEach(sortOrder -> add(comparatorFunction.apply(sortOrder))));
return this;
}
/**
* Creates and adds value comparators for the given field ordering descriptions.
*
* @param sortOrder the ordering descriptions (can be {@code null} - no comparator will be
* added)
* @return the comparator builder
*/
default ComparatorBuilder addAll(SortOrder sortOrder) {
return addAll(sortOrder, (ValueExtractor) null);
}
/**
* Creates and adds value comparators for the given field ordering descriptions. A custom value
* extractor can be specified.
*
* @param sortOrder the ordering descriptions (can be {@code null} - no comparator will be
* added)
* @param valueExtractor the value extractor (can be {@code null})
* @return the comparator builder
*/
default ComparatorBuilder addAll(
SortOrder sortOrder,
ValueExtractor valueExtractor) {
return Optional.ofNullable(sortOrder)
.map(orders -> addAll(orders.getItems(), valueExtractor))
.orElse(this);
}
/**
* Add all comparator builder.
*
* @param sortOrder the sort orders
* @param comparatorFunction the comparator function
* @return the comparator builder
*/
default ComparatorBuilder addAll(
SortOrder sortOrder,
Function<SortOrderItem, Comparator<?>> comparatorFunction) {
return Optional.ofNullable(sortOrder)
.map(orders -> addAll(orders.getItems(), comparatorFunction))
.orElse(this);
}
/**
* Creates and adds value comparators for the given field ordering descriptions.
*
* @param sortOrderText the ordering descriptions (can be {@code null} - no comparator will be
* added)
* @return the comparator builder
*/
default ComparatorBuilder addAll(String sortOrderText) {
return addAll(SortOrder.fromSortOrderText(sortOrderText));
}
/**
* Creates and adds value comparators for the given field ordering descriptions. A custom value
* extractor can be specified.
*
* @param sortOrderText the ordering descriptions (can be {@code null} - no comparator will be
* added)
* @param valueExtractor the value extractor (can be {@code null})
* @return the comparator builder
*/
default ComparatorBuilder addAll(
String sortOrderText,
ValueExtractor valueExtractor) {
return addAll(SortOrder.fromSortOrderText(sortOrderText), valueExtractor);
}
/**
* Add all comparator builder.
*
* @param sortOrderText the sort orders
* @param comparatorFunction the comparator function
* @return the comparator builder
*/
default ComparatorBuilder addAll(
String sortOrderText,
Function<SortOrderItem, Comparator<?>> comparatorFunction) {
return addAll(SortOrder.fromSortOrderText(sortOrderText), comparatorFunction);
}
/**
* Build comparator.
*
* @param <T> the type parameter
* @return the comparator
*/
<T> Comparator<T> build();
/**
* The default comparator builder.
*/
class DefaultComparatorBuilder implements ComparatorBuilder {
@SuppressWarnings("rawtypes")
private final List<Comparator> comparatorChain = new LinkedList<>();
/**
* Instantiates a new default comparator builder.
*/
public DefaultComparatorBuilder() {
super();
}
@Override
public ComparatorBuilder add(Comparator<?> comparator) {
Optional.ofNullable(comparator)
.ifPresent(comparatorChain::add);
return this;
}
@Override
public <T> Comparator<T> build() {
//noinspection unchecked
return (Comparator<T>) new ComparatorChain(comparatorChain);
}
}
}