Untitled

 avatar
unknown
plain_text
5 months ago
6.4 kB
4
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