From 21d19b2bd29510f75d6e508a9a4cf872784d757a Mon Sep 17 00:00:00 2001 From: SirWayne Date: Mon, 1 Feb 2016 16:17:07 +0100 Subject: [PATCH] Fix conversion for boolean (and other types) for the jpa criteria builder Signed-off-by: SirWayne --- .../hawkbit/repository/rsql/RSQLUtility.java | 54 +++++++++++-------- .../rsql/RSQLDistributionSetFieldTest.java | 8 ++- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/rsql/RSQLUtility.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/rsql/RSQLUtility.java index 44bd5d352..7b50a4c3e 100644 --- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/rsql/RSQLUtility.java +++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/rsql/RSQLUtility.java @@ -27,6 +27,8 @@ import org.eclipse.hawkbit.repository.FieldNameProvider; import org.eclipse.hawkbit.repository.FieldValueConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.SimpleTypeConverter; +import org.springframework.beans.TypeMismatchException; import org.springframework.data.jpa.domain.Specification; import cz.jirutka.rsql.parser.RSQLParser; @@ -76,7 +78,6 @@ public final class RSQLUtility { * private constructor due utility class. */ private RSQLUtility() { - } /** @@ -163,11 +164,13 @@ public final class RSQLUtility { private final Root root; private final CriteriaBuilder cb; private final Class enumType; + private final SimpleTypeConverter simpleTypeConverter; private JpqQueryRSQLVisitor(final Root root, final CriteriaBuilder cb, final Class enumType) { this.root = root; this.cb = cb; this.enumType = enumType; + this.simpleTypeConverter = new SimpleTypeConverter(); } @Override @@ -199,10 +202,8 @@ public final class RSQLUtility { validateMapParamter(propertyEnum, node, graph); // sub entity need minium 1 dot - if (!propertyEnum.getSubEntityAttributes().isEmpty()) { - if (graph.length < 2) { - throw createRSQLParameterUnsupportedException(node); - } + if (!propertyEnum.getSubEntityAttributes().isEmpty() && graph.length < 2) { + throw createRSQLParameterUnsupportedException(node); } for (int i = 1; i < graph.length; i++) { @@ -353,7 +354,12 @@ public final class RSQLUtility { return convertedValue; } } - return value; + + try { + return simpleTypeConverter.convertIfNecessary(value, javaType); + } catch (final TypeMismatchException e) { + throw new RSQLParameterSyntaxException(); + } } @SuppressWarnings({ "rawtypes", "unchecked" }) @@ -377,7 +383,7 @@ public final class RSQLUtility { } } - private List mapToPredicate(final ComparisonNode node, Path fieldPath, + private List mapToPredicate(final ComparisonNode node, final Path fieldPath, final List values, final List transformedValues, final A enumField) { // only 'equal' and 'notEqual' can handle transformed value like // enums. The JPA API @@ -391,29 +397,38 @@ public final class RSQLUtility { singleList.add(mapPredicate); } - fieldPath = getMapValueFieldPath(enumField, fieldPath); + final Path mappedFieldPath = getMapValueFieldPath(enumField, fieldPath); + addPredicateByOperator(node, fieldPath, transformedValues, transformedValue, value, singleList, + mappedFieldPath); + return Collections.unmodifiableList(singleList); + } + + private void addPredicateByOperator(final ComparisonNode node, final Path fieldPath, + final List transformedValues, final Object transformedValue, final String value, + final List singleList, final Path mappedFieldPath) { switch (node.getOperator().getSymbol()) { case "=li=": - singleList.add(cb.like(cb.upper(pathOfString(fieldPath)), transformedValue.toString().toUpperCase())); + singleList.add( + cb.like(cb.upper(pathOfString(mappedFieldPath)), transformedValue.toString().toUpperCase())); break; case "==": - singleList.add(getEqualToPredicate(transformedValue, fieldPath)); + singleList.add(getEqualToPredicate(transformedValue, mappedFieldPath)); break; case "!=": - singleList.add(cb.notEqual(fieldPath, transformedValue)); + singleList.add(cb.notEqual(mappedFieldPath, transformedValue)); break; case "=gt=": - singleList.add(cb.greaterThan(pathOfString(fieldPath), value)); + singleList.add(cb.greaterThan(pathOfString(mappedFieldPath), value)); break; case "=ge=": - singleList.add(cb.greaterThanOrEqualTo(pathOfString(fieldPath), value)); + singleList.add(cb.greaterThanOrEqualTo(pathOfString(mappedFieldPath), value)); break; case "=lt=": - singleList.add(cb.lessThan(pathOfString(fieldPath), value)); + singleList.add(cb.lessThan(pathOfString(mappedFieldPath), value)); break; case "=le=": - singleList.add(cb.lessThanOrEqualTo(pathOfString(fieldPath), value)); + singleList.add(cb.lessThanOrEqualTo(pathOfString(mappedFieldPath), value)); break; case "=in=": singleList.add(fieldPath.in(transformedValues)); @@ -424,13 +439,8 @@ public final class RSQLUtility { default: LOGGER.info("operator symbol {} is either not supported or not implemented"); } - return Collections.unmodifiableList(singleList); } - /** - * @param enumField - * @return - */ private Path getMapValueFieldPath(final A enumField, final Path fieldPath) { if (!enumField.isMap() || enumField.getValueFieldName() == null) { return fieldPath; @@ -446,7 +456,7 @@ public final class RSQLUtility { final String[] graph = node.getSelector().split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR); final String keyValue = graph[graph.length - 1]; if (fieldPath instanceof MapJoin) { - return cb.equal(((MapJoin) fieldPath).key(), keyValue); + return cb.equal(((MapJoin) fieldPath).key(), keyValue); } return cb.equal(fieldPath.get(enumField.getKeyFieldName()), keyValue); @@ -455,7 +465,7 @@ public final class RSQLUtility { private Predicate getEqualToPredicate(final Object transformedValue, final Path fieldPath) { if (transformedValue instanceof String) { final String preFormattedValue = ((String) transformedValue).replace(LIKE_WILDCARD, '%'); - return cb.like(cb.upper(pathOfString(fieldPath)), preFormattedValue.toString().toUpperCase()); + return cb.like(cb.upper(pathOfString(fieldPath)), preFormattedValue.toUpperCase()); } return cb.equal(fieldPath, transformedValue); } diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLDistributionSetFieldTest.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLDistributionSetFieldTest.java index 014b7a055..c4c5a181a 100644 --- a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLDistributionSetFieldTest.java +++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/rsql/RSQLDistributionSetFieldTest.java @@ -9,6 +9,7 @@ package org.eclipse.hawkbit.repository.rsql; import static org.fest.assertions.api.Assertions.assertThat; +import static org.junit.Assert.fail; import java.util.Arrays; @@ -94,7 +95,12 @@ public class RSQLDistributionSetFieldTest extends AbstractIntegrationTest { @Description("Test filter distribution set by complete property") public void testFilterByAttribute() { assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "==true", 4); - assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "==noExist*", 0); + try { + assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "==noExist*", 0); + fail(); + } catch (final RSQLParameterSyntaxException e) { + // excepted + } assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "=in=(true)", 4); assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "=out=(true)", 0); }