vineey / archelix-rsql

This library brings the convenience of SQL declarative nature to restful APIs in the form of RSQL but without the danger of sql injection by using a typesafe mapping of allowed field paths defined via integration with querydsl library. Like sql, it supports clauses such as select, filter, pagination and sorting that can easily be represented in http request parameters. It primarily supports JPA model and MongoDB query via Querydsl.
MIT License
39 stars 9 forks source link

Issue with EnumPathConverter #14

Closed dskrashchuk closed 8 years ago

dskrashchuk commented 8 years ago

It doesn't convert to enum in case of "in" and "out" queries.

And exception as a result:

Caused by: java.lang.IllegalArgumentException: Parameter value [ACTIVE] did not match expected type [com.***.Status (n/a)] at org.hibernate.jpa.spi.BaseQueryImpl.validateBinding(BaseQueryImpl.java:874) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.jpa.internal.QueryImpl.access$000(QueryImpl.java:80) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.jpa.internal.QueryImpl$ParameterRegistrationImpl.bindValue(QueryImpl.java:248) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.jpa.internal.QueryImpl$JpaPositionalParameterRegistrationImpl.bindValue(QueryImpl.java:337) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.jpa.spi.BaseQueryImpl.setParameter(BaseQueryImpl.java:674) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:198) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:49) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] at com.mysema.query.jpa.impl.JPAUtil.setConstants(JPAUtil.java:55) ~[querydsl-jpa-3.6.5.jar:na] at com.mysema.query.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:130) ~[querydsl-jpa-3.6.5.jar:na] at com.mysema.query.jpa.impl.AbstractJPAQuery.count(AbstractJPAQuery.java:81) ~[querydsl-jpa-3.6.5.jar:na]

_Proposed solution: _

public BooleanExpression evaluate(EnumPath path, ComparisonNode comparisonNode) {
        ComparisonOperator comparisonOperator = comparisonNode.getOperator();
        List<String> args = comparisonNode.getArguments();

        Function<String, Enum<?>> toEnumFunction = (String arg) -> {
            Enum enumArg = EnumUtils.getEnum(path.getType(), arg.toUpperCase());
            if (enumArg == null && !NULL.equalsIgnoreCase(arg)) {
                throw new IllegalArgumentException("Nonexistent enum value: " + arg);
            }
            return enumArg;
        };

        List<Enum> enumArgs = args.stream().map(toEnumFunction).collect(Collectors.toList());
        String firstArg = args.get(0);
        Enum firstEnumArg = enumArgs.get(0);

        if (EQUAL.equals(comparisonOperator)) {
            return NULL.equalsIgnoreCase(firstArg) ? path.isNull() : path.eq(firstEnumArg);
        } else if (NOT_EQUAL.equals(comparisonOperator)) {
            return NULL.equalsIgnoreCase(firstArg) ? path.isNotNull() : path.ne(firstEnumArg);
        } else if (IN.equals(comparisonOperator)) {
            return path.in(enumArgs);
        } else if (NOT_IN.equals(comparisonOperator)) {
            return path.notIn(enumArgs);
        }
        throw new UnsupportedRqlOperatorException(comparisonNode, path.getClass());
    }
vineey commented 8 years ago

I miss that out in my test cases, thank you for reporting this bug. I just need to convert all arguments for operators in and out.