Untitled
unknown
plain_text
a year ago
6.4 kB
15
Indexable
public final class ApprovalFilterUtils {
private ApprovalFilterUtils() {}
public static boolean matches(
@NonNull Map<String, Object> requestedFilters,
@NonNull List<ApprovalFilterModel> storedFilters) {
Assert.notNull(requestedFilters, "requestedFilters cannot be null");
Assert.notNull(storedFilters, "storedFilters cannot be null");
Assert.noNullElements(storedFilters, "storedFilters must not contain null elements");
for (ApprovalFilterModel filter : storedFilters) {
Object requestedValue = requestedFilters.get(filter.getName());//DISCOUNT
if (!validate(requestedValue, filter.getType(), filter.getOperation())) {
return false;
}
boolean match = switch (filter.getOperation()) {
case EQUALS -> Objects.equals(requestedValue, filter.getValue());
case NOT_EQUALS -> !Objects.equals(requestedValue, filter.getValue());
case GREATER_THAN -> compare(requestedValue, filter.getValue()) > 0;
case GREATER_THAN_EQUALS -> compare(requestedValue, filter.getValue()) >= 0;
case LESS_THAN -> compare(requestedValue, filter.getValue()) < 0;
case LESS_THAN_EQUALS -> compare(requestedValue, filter.getValue()) <= 0;
case IN -> listContains(filter.getValue(), requestedValue);
case NIN -> !listContains(filter.getValue(), requestedValue);
default -> throw new UnsupportedOperationException(
"Unsupported operation: " + filter.getOperation());
};
if (!match) {
return false;
}
}
return true;
}
private static final Map<Class<?>, Function<String, Comparable<?>>> CONVERTERS = Map.of(
LocalDateTime.class, str -> LocalDateTime.parse(str),
OffsetDateTime.class, str -> OffsetDateTime.parse(str),
BigDecimal.class, str -> new BigDecimal(str)
);
private static int compare(Object o1, Object o2) {
if (o1 == null || o2 == null) {
throw new IllegalArgumentException("Cannot compare null values");
}
Comparable<Object> c1 = (Comparable<Object>) convertIfString(o1);
Comparable<Object> c2 = (Comparable<Object>) convertIfString(o2);
if (!c1.getClass().equals(c2.getClass())) {
throw new IllegalArgumentException("Cannot compare different types: " + c1.getClass() + " and " + c2.getClass());
}
return c1.compareTo(c2);
}
private static Comparable<?> convertIfString(Object obj) {
if (obj instanceof String str) {
for (var entry : CONVERTERS.entrySet()) {
try {
return entry.getValue().apply(str);
} catch (Exception ignored) {
}
}
return str;
}
return (Comparable<?>) obj;
}
private static boolean listContains(Object storedValue, Object requestedValue) {
if (storedValue instanceof List<?> list) {
return list.contains(requestedValue);
} else if (storedValue instanceof String str) {
return Arrays.asList(str.split(",\\s*")).contains(String.valueOf(requestedValue));
}
return false;
}
private static final Map<ApprovalFilterValueType, Class<?>> CLASSES =
Map.of(
ApprovalFilterValueType.STRING, String.class,
ApprovalFilterValueType.NUMBER, BigDecimal.class,
ApprovalFilterValueType.DATE, LocalDate.class,
ApprovalFilterValueType.DATE_TIME, LocalDateTime.class,
ApprovalFilterValueType.DATE_TIME_WITH_TIMEZONE, OffsetDateTime.class);
private static final Set<ApprovalFilterOperation> LIST_OPERATIONS =
EnumSet.of(ApprovalFilterOperation.IN, ApprovalFilterOperation.NIN);
private static final Map<ApprovalFilterValueType, Set<ApprovalFilterOperation>>
UNSUPPORTED_OPERATIONS =
Map.of(
ApprovalFilterValueType.STRING,
EnumSet.complementOf(
EnumSet.of(
ApprovalFilterOperation.EQUALS,
ApprovalFilterOperation.NOT_EQUALS,
ApprovalFilterOperation.IN,
ApprovalFilterOperation.NIN)));
private static final ApplicationConversionService CONVERSION_SERVICE =
new ApplicationConversionService();
/**
* Validates if the provided object can be converted to value of given type that can be used to
* provide the requested operation. Not all types support all operations.
*
* @param o the object to validate. nulls are allowed
* @param type the type of the value to consider
* @param operation the operation that has to be performed
* @return whether the object of requested type supports requested operation
*/
public static boolean validate(
@Nullable Object o,
@NonNull ApprovalFilterValueType type,
@NonNull ApprovalFilterOperation operation) {
//dis,string,eq
if (o == null) {
return true;
}
var unsupportedOperations = UNSUPPORTED_OPERATIONS.getOrDefault(type, Set.of());
if (unsupportedOperations.contains(operation)) {
return false;
}
TypeDescriptor td = TypeDescriptor.valueOf(getTargetClass(type));
if (LIST_OPERATIONS.contains(operation)) {
td = TypeDescriptor.collection(List.class, td);
}
return CONVERSION_SERVICE.canConvert(TypeDescriptor.forObject(o), td);
}
@NonNull
private static Class<?> getTargetClass(@NonNull ApprovalFilterValueType type) {
Assert.notNull(type, "ApprovalFilterValueType must not be null");
var clazz = CLASSES.get(type);
if (clazz == null) {
throw new IllegalArgumentException(
"ApprovalFilterValueType " + type + " not supported");
}
return clazz;
}
}Editor is loading...
Leave a Comment