diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..cc0a705 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,31 @@ +pipeline { + agent any + stages { + stage('Build') { + agent any + steps { + sh 'mvn clean install' + } + } + stage('input') { + steps { + input(message: 'test', id: 'id', ok: 'ij') + } + } + stage('coiso') { + parallel { + stage('coiso') { + steps { + echo 'teste' + } + } + stage('error') { + steps { + echo 'teste2' + sh 'exit 0' + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/github/tennaito/rsql/jpa/PredicateBuilder.java b/src/main/java/com/github/tennaito/rsql/jpa/PredicateBuilder.java index 01b7c89..35e1a46 100755 --- a/src/main/java/com/github/tennaito/rsql/jpa/PredicateBuilder.java +++ b/src/main/java/com/github/tennaito/rsql/jpa/PredicateBuilder.java @@ -24,12 +24,13 @@ */ package com.github.tennaito.rsql.jpa; -import com.github.tennaito.rsql.builder.BuilderTools; -import com.github.tennaito.rsql.parser.ast.ComparisonOperatorProxy; -import cz.jirutka.rsql.parser.ast.ComparisonNode; -import cz.jirutka.rsql.parser.ast.ComparisonOperator; -import cz.jirutka.rsql.parser.ast.LogicalNode; -import cz.jirutka.rsql.parser.ast.Node; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.persistence.EntityManager; import javax.persistence.criteria.CriteriaBuilder; @@ -43,13 +44,14 @@ import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.Metamodel; import javax.persistence.metamodel.PluralAttribute; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; + +import com.github.tennaito.rsql.builder.BuilderTools; +import com.github.tennaito.rsql.parser.ast.ComparisonOperatorProxy; + +import cz.jirutka.rsql.parser.ast.ComparisonNode; +import cz.jirutka.rsql.parser.ast.ComparisonOperator; +import cz.jirutka.rsql.parser.ast.LogicalNode; +import cz.jirutka.rsql.parser.ast.Node; /** * PredicateBuilder @@ -58,13 +60,14 @@ * * @author AntonioRabelo * - * Based from CriterionBuilders of rsql-hibernate created by Jakub Jirutka . + * Based from CriterionBuilders of rsql-hibernate created by Jakub + * Jirutka . * * @since 2015-02-05 */ public final class PredicateBuilder { - private static final Logger LOG = Logger.getLogger(PredicateBuilder.class.getName()); + private static final Logger LOG = Logger.getLogger(PredicateBuilder.class.getName()); public static final Character LIKE_WILDCARD = '*'; @@ -76,38 +79,38 @@ public final class PredicateBuilder { // Use a date range that Oracle can cope with - apparently the years around 1 BC and 1 AD are messed up in Oracle - known bug // Calendar cal = Calendar.getInstance(); - cal.set( 9999, Calendar.DECEMBER, 31); + cal.set(9999, Calendar.DECEMBER, 31); END_DATE = cal.getTime(); - cal.set( 5, Calendar.JANUARY, 1); // Use Jan 1, 5 AD, since that's where the Roman's sort of got it together with leap years. + cal.set(5, Calendar.JANUARY, 1); // Use Jan 1, 5 AD, since that's where the Roman's sort of got it together with leap years. START_DATE = cal.getTime(); } /** * Private constructor. */ - private PredicateBuilder(){ - super(); + private PredicateBuilder() { + super(); } /** * Create a Predicate from the RSQL AST node. * - * @param node RSQL AST node. - * @param root From that predicate expression paths depends on. - * @param entity The main entity of the query. - * @param manager JPA EntityManager. - * @param misc Facade with all necessary tools for predicate creation. - * @return Predicate a predicate representation of the Node. + * @param node RSQL AST node. + * @param root From that predicate expression paths depends on. + * @param entity The main entity of the query. + * @param manager JPA EntityManager. + * @param misc Facade with all necessary tools for predicate creation. + * @return Predicate a predicate representation of the Node. */ public static Predicate createPredicate(Node node, From root, Class entity, EntityManager manager, BuilderTools misc) { LOG.log(Level.INFO, "Creating Predicate for: {0}", node); if (node instanceof LogicalNode) { - return createPredicate((LogicalNode)node, root, entity, manager, misc); + return createPredicate((LogicalNode) node, root, entity, manager, misc); } - + if (node instanceof ComparisonNode) { - return createPredicate((ComparisonNode)node, root, entity, manager, misc); + return createPredicate((ComparisonNode) node, root, entity, manager, misc); } throw new IllegalArgumentException("Unknown expression type: " + node.getClass()); @@ -116,28 +119,30 @@ public static Predicate createPredicate(Node node, From root, Class entit /** * Create a Predicate from the RSQL AST logical node. * - * @param logical RSQL AST logical node. - * @param root From that predicate expression paths depends on. - * @param entity The main entity of the query. - * @param entityManager JPA EntityManager. - * @param misc Facade with all necessary tools for predicate creation. - * @return Predicate a predicate representation of the Node. + * @param logical RSQL AST logical node. + * @param root From that predicate expression paths depends on. + * @param entity The main entity of the query. + * @param entityManager JPA EntityManager. + * @param misc Facade with all necessary tools for predicate creation. + * @return Predicate a predicate representation of the Node. */ public static Predicate createPredicate(LogicalNode logical, From root, Class entity, EntityManager entityManager, BuilderTools misc) { LOG.log(Level.INFO, "Creating Predicate for logical node: {0}", logical); - CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); - List predicates = new ArrayList(); + List predicates = new ArrayList(); - LOG.log(Level.INFO, "Creating Predicates from all children nodes."); - for (Node node : logical.getChildren()) { - predicates.add(createPredicate(node, root, entity, entityManager, misc)); - } + LOG.log(Level.INFO, "Creating Predicates from all children nodes."); + for (Node node : logical.getChildren()) { + predicates.add(createPredicate(node, root, entity, entityManager, misc)); + } switch (logical.getOperator()) { - case AND : return builder.and(predicates.toArray(new Predicate[predicates.size()])); - case OR : return builder.or(predicates.toArray(new Predicate[predicates.size()])); + case AND: + return builder.and(predicates.toArray(new Predicate[predicates.size()])); + case OR: + return builder.or(predicates.toArray(new Predicate[predicates.size()])); } throw new IllegalArgumentException("Unknown operator: " + logical.getOperator()); @@ -146,72 +151,84 @@ public static Predicate createPredicate(LogicalNode logical, From root, Clas /** * Create a Predicate from the RSQL AST comparison node. * - * @param comparison RSQL AST comparison node. - * @param startRoot From that predicate expression paths depends on. - * @param entity The main entity of the query. - * @param entityManager JPA EntityManager. - * @param misc Facade with all necessary tools for predicate creation. - * @return Predicate a predicate representation of the Node. + * @param comparison RSQL AST comparison node. + * @param startRoot From that predicate expression paths depends on. + * @param entity The main entity of the query. + * @param entityManager JPA EntityManager. + * @param misc Facade with all necessary tools for predicate creation. + * @return Predicate a predicate representation of the Node. */ - public static Predicate createPredicate(ComparisonNode comparison, From startRoot, Class entity, EntityManager entityManager, BuilderTools misc) { - if (startRoot == null) { - String msg = "From root node was undefined."; - LOG.log(Level.SEVERE, msg); - throw new IllegalArgumentException(msg); - } - LOG.log(Level.INFO, "Creating Predicate for comparison node: {0}", comparison); + public static Predicate createPredicate(ComparisonNode comparison, From startRoot, Class entity, EntityManager entityManager, + BuilderTools misc) { + if (startRoot == null) { + String msg = "From root node was undefined."; + LOG.log(Level.SEVERE, msg); + throw new IllegalArgumentException(msg); + } + LOG.log(Level.INFO, "Creating Predicate for comparison node: {0}", comparison); LOG.log(Level.INFO, "Property graph path : {0}", comparison.getSelector()); Expression propertyPath = findPropertyPath(comparison.getSelector(), startRoot, entityManager, misc); - LOG.log(Level.INFO, "Cast all arguments to type {0}.", propertyPath.getJavaType().getName()); - List castedArguments = misc.getArgumentParser().parse(comparison.getArguments(), propertyPath.getJavaType()); + LOG.log(Level.INFO, "Cast all arguments to type {0}.", propertyPath.getJavaType().getName()); + List castedArguments = misc.getArgumentParser().parse(comparison.getArguments(), propertyPath.getJavaType()); - try { - // try to create a predicate - return PredicateBuilder.createPredicate(propertyPath, comparison.getOperator(), castedArguments, entityManager); - } catch (IllegalArgumentException e) { - // if operator dont exist try to delegate + try { + // try to create a predicate + return PredicateBuilder.createPredicate(propertyPath, comparison.getOperator(), castedArguments, entityManager); + } catch (IllegalArgumentException e) { + // if operator dont exist try to delegate if (misc.getPredicateBuilder() != null) { - return misc.getPredicateBuilder().createPredicate(comparison, startRoot, entity, entityManager, misc); + return misc.getPredicateBuilder().createPredicate(comparison, startRoot, entity, entityManager, misc); } // if no strategy was defined then there are no more operators. throw e; - } + } } /** * Find a property path in the graph from startRoot * - * @param propertyPath The property path to find. - * @param startRoot From that property path depends on. - * @param entityManager JPA EntityManager. - * @param misc Facade with all necessary tools for predicate creation. - * @return The Path for the property path - * @throws IllegalArgumentException if attribute of the given property name does not exist + * @param propertyPath The property path to find. + * @param startRoot From that property path depends on. + * @param entityManager JPA EntityManager. + * @param misc Facade with all necessary tools for predicate creation. + * @return The Path for the property path + * @throws IllegalArgumentException if attribute of the given property name + * does not exist */ - public static Path findPropertyPath(String propertyPath, Path startRoot, EntityManager entityManager, BuilderTools misc) { - String[] graph = propertyPath.split("\\."); + public static Path findPropertyPath(String propertyPath, Path startRoot, EntityManager entityManager, BuilderTools misc) { Metamodel metaModel = entityManager.getMetamodel(); ManagedType classMetadata = metaModel.managedType(startRoot.getJavaType()); + return findPropertyPath(propertyPath, startRoot, entityManager, misc, new RecursiveHolder>(classMetadata)); + } + + private static Path findPropertyPath(String propertyPath, Path startRoot, EntityManager entityManager, BuilderTools misc, + RecursiveHolder> classMetadata) { + String[] graph = propertyPath.split("\\."); + + Metamodel metaModel = entityManager.getMetamodel(); + Path root = startRoot; for (String property : graph) { - String mappedProperty = misc.getPropertiesMapper().translate(property, classMetadata.getJavaType()); - if( !mappedProperty.equals( property) ) { - root = findPropertyPath( mappedProperty, root, entityManager, misc ); + String mappedProperty = misc.getPropertiesMapper().translate(property, classMetadata.object.getJavaType()); + if (!mappedProperty.equals(property)) { + root = findPropertyPath(mappedProperty, root, entityManager, misc, classMetadata); } else { - if (!hasPropertyName(mappedProperty, classMetadata)) { - throw new IllegalArgumentException("Unknown property: " + mappedProperty + " from entity " + classMetadata.getJavaType().getName()); + if (!hasPropertyName(mappedProperty, classMetadata.object)) { + throw new IllegalArgumentException( + "Unknown property: " + mappedProperty + " from entity " + classMetadata.object.getJavaType().getName()); } - if (isAssociationType(mappedProperty, classMetadata)) { - Class associationType = findPropertyType(mappedProperty, classMetadata); - String previousClass = classMetadata.getJavaType().getName(); - classMetadata = metaModel.managedType(associationType); - LOG.log(Level.INFO, "Create a join between {0} and {1}.", new Object[]{previousClass, classMetadata.getJavaType().getName()}); + if (isAssociationType(mappedProperty, classMetadata.object)) { + Class associationType = findPropertyType(mappedProperty, classMetadata.object); + String previousClass = classMetadata.object.getJavaType().getName(); + classMetadata.object = metaModel.managedType(associationType); + LOG.log(Level.INFO, "Create a join between {0} and {1}.", + new Object[]{previousClass, classMetadata.object.getJavaType().getName()}); if (root instanceof Join) { root = root.get(mappedProperty); @@ -219,12 +236,13 @@ public static Path findPropertyPath(String propertyPath, Path startRoot, root = ((From) root).join(mappedProperty); } } else { - LOG.log(Level.INFO, "Create property path for type {0} property {1}.", new Object[]{classMetadata.getJavaType().getName(), mappedProperty}); + LOG.log(Level.INFO, "Create property path for type {0} property {1}.", + new Object[]{classMetadata.object.getJavaType().getName(), mappedProperty}); root = root.get(mappedProperty); - if (isEmbeddedType(mappedProperty, classMetadata)) { - Class embeddedType = findPropertyType(mappedProperty, classMetadata); - classMetadata = metaModel.managedType(embeddedType); + if (isEmbeddedType(mappedProperty, classMetadata.object)) { + Class embeddedType = findPropertyType(mappedProperty, classMetadata.object); + classMetadata.object = metaModel.managedType(embeddedType); } } } @@ -238,39 +256,40 @@ public static Path findPropertyPath(String propertyPath, Path startRoot, /** * Create Predicate for comparison operators. * - * @param propertyPath Property path that we want to compare. - * @param operator Comparison operator. - * @param arguments Arguments (1 for binary comparisons, n for multi-value comparisons [in, not in (out)]) - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param operator Comparison operator. + * @param arguments Arguments (1 for binary comparisons, n for multi-value + * comparisons [in, not in (out)]) + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createPredicate(Expression propertyPath, ComparisonOperator operator, List arguments, EntityManager manager) { - LOG.log(Level.INFO, "Creating predicate: propertyPath {0} {1}", new Object[]{operator, arguments}); - - if (ComparisonOperatorProxy.asEnum(operator) != null) { - switch (ComparisonOperatorProxy.asEnum(operator)) { - case EQUAL : { - Object argument = arguments.get(0); - if (argument instanceof String) { - return createLike(propertyPath, (String) argument, manager); - } else if (isNullArgument(argument)) { - return createIsNull(propertyPath, manager); - } else { - return createEqual(propertyPath, argument, manager); - } - } - case NOT_EQUAL : { - Object argument = arguments.get(0); - if (argument instanceof String) { - return createNotLike(propertyPath, (String) argument, manager); - } else if (isNullArgument(argument)) { - return createIsNotNull(propertyPath, manager); - } else { - return createNotEqual(propertyPath, argument, manager); - } - } - case GREATER_THAN : { - Object argument = arguments.get(0); + LOG.log(Level.INFO, "Creating predicate: propertyPath {0} {1}", new Object[]{operator, arguments}); + + if (ComparisonOperatorProxy.asEnum(operator) != null) { + switch (ComparisonOperatorProxy.asEnum(operator)) { + case EQUAL: { + Object argument = arguments.get(0); + if (argument instanceof String) { + return createLike(propertyPath, (String) argument, manager); + } else if (isNullArgument(argument)) { + return createIsNull(propertyPath, manager); + } else { + return createEqual(propertyPath, argument, manager); + } + } + case NOT_EQUAL: { + Object argument = arguments.get(0); + if (argument instanceof String) { + return createNotLike(propertyPath, (String) argument, manager); + } else if (isNullArgument(argument)) { + return createIsNotNull(propertyPath, manager); + } else { + return createNotEqual(propertyPath, argument, manager); + } + } + case GREATER_THAN: { + Object argument = arguments.get(0); Predicate predicate; if (argument instanceof Date) { int days = 1; @@ -284,13 +303,13 @@ private static Predicate createPredicate(Expression propertyPath, ComparisonOper } return predicate; } - case GREATER_THAN_OR_EQUAL : { - Object argument = arguments.get(0); + case GREATER_THAN_OR_EQUAL: { + Object argument = arguments.get(0); Predicate predicate; - if (argument instanceof Date){ - predicate = createBetweenThan(propertyPath, (Date)argument, END_DATE, manager); + if (argument instanceof Date) { + predicate = createBetweenThan(propertyPath, (Date) argument, END_DATE, manager); } else if (argument instanceof Number || argument == null) { - predicate = createGreaterEqual(propertyPath, (Number)argument, manager); + predicate = createGreaterEqual(propertyPath, (Number) argument, manager); } else if (argument instanceof Comparable) { predicate = createGreaterEqualComparable(propertyPath, (Comparable) argument, manager); } else { @@ -298,9 +317,9 @@ private static Predicate createPredicate(Expression propertyPath, ComparisonOper } return predicate; - } - case LESS_THAN : { - Object argument = arguments.get(0); + } + case LESS_THAN: { + Object argument = arguments.get(0); Predicate predicate; if (argument instanceof Date) { int days = -1; @@ -314,14 +333,14 @@ private static Predicate createPredicate(Expression propertyPath, ComparisonOper } return predicate; } - case LESS_THAN_OR_EQUAL : { - Object argument = arguments.get(0); + case LESS_THAN_OR_EQUAL: { + Object argument = arguments.get(0); Predicate predicate; - if (argument instanceof Date){ - predicate = createBetweenThan(propertyPath,START_DATE, (Date)argument, manager); + if (argument instanceof Date) { + predicate = createBetweenThan(propertyPath, START_DATE, (Date) argument, manager); } else if (argument instanceof Number || argument == null) { - predicate = createLessEqual(propertyPath, (Number)argument, manager); + predicate = createLessEqual(propertyPath, (Number) argument, manager); } else if (argument instanceof Comparable) { predicate = createLessEqualComparable(propertyPath, (Comparable) argument, manager); } else { @@ -329,35 +348,38 @@ private static Predicate createPredicate(Expression propertyPath, ComparisonOper } return predicate; } - case IN : return createIn(propertyPath, arguments, manager); - case NOT_IN : return createNotIn(propertyPath, arguments, manager); - } - } + case IN: + return createIn(propertyPath, arguments, manager); + case NOT_IN: + return createNotIn(propertyPath, arguments, manager); + } + } throw new IllegalArgumentException("Unknown operator: " + operator); } /** - + * Creates the between than. - + * - + * @param propertyPath the property path - + * @param startDate the start date - + * @param argument the argument - + * @param manager the manager - + * @return the predicate - + */ + * + * Creates the between than. + * + * + * + * @param propertyPath the property path + * + * @param startDate the start date + * + * @param argument the argument + * + * @param manager the manager + * + * @return the predicate + * + + */ private static Predicate createBetweenThan(Expression propertyPath, Date start, Date end, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); - return builder.between(propertyPath, start, end); + CriteriaBuilder builder = manager.getCriteriaBuilder(); + return builder.between(propertyPath, start, end); } /** * Apply a case-insensitive "like" constraint to the property path. Value * should contains wildcards "*" (% in SQL) and "_". * - * @param propertyPath Property path that we want to compare. - * @param argument Argument with/without wildcards - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument with/without wildcards + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createLike(Expression propertyPath, String argument, EntityManager manager) { String like = argument.replace(LIKE_WILDCARD, '%'); @@ -368,38 +390,38 @@ private static Predicate createLike(Expression propertyPath, String argu /** * Apply an "is null" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createIsNull(Expression propertyPath, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); - return builder.isNull(propertyPath); + CriteriaBuilder builder = manager.getCriteriaBuilder(); + return builder.isNull(propertyPath); } /** * Apply an "equal" constraint to property path. * - * @param propertyPath Property path that we want to compare. - * @param argument Argument - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createEqual(Expression propertyPath, Object argument, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); - return builder.equal(propertyPath, argument); + CriteriaBuilder builder = manager.getCriteriaBuilder(); + return builder.equal(propertyPath, argument); } /** * Apply a "not equal" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param argument Argument - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createNotEqual(Expression propertyPath, Object argument, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); + CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.notEqual(propertyPath, argument); } @@ -407,50 +429,51 @@ private static Predicate createNotEqual(Expression propertyPath, Object argum * Apply a negative case-insensitive "like" constraint to the property path. * Value should contains wildcards "*" (% in SQL) and "_". * - * @param propertyPath Property path that we want to compare. - * @param argument Argument with/without wildcards - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument with/without wildcards + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createNotLike(Expression propertyPath, String argument, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); + CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.not(createLike(propertyPath, argument, manager)); } /** * Apply an "is not null" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createIsNotNull(Expression propertyPath, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); + CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.isNotNull(propertyPath); } /** * Apply a "greater than" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param argument Argument number. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument number. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createGreaterThan(Expression propertyPath, Number argument, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); + CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.gt(propertyPath, argument); } /** * Apply a "greater than" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param argument Argument. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ - private static > Predicate createGreaterThanComparable(Expression propertyPath, Y argument, EntityManager manager) { + private static > Predicate createGreaterThanComparable(Expression propertyPath, Y argument, + EntityManager manager) { CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.greaterThan(propertyPath, argument); } @@ -458,25 +481,26 @@ private static > Predicate createGreaterThanComp /** * Apply a "greater than or equal" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param argument Argument number. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument number. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createGreaterEqual(Expression propertyPath, Number argument, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); + CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.ge(propertyPath, argument); } /** * Apply a "greater than or equal" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param argument Argument. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ - private static > Predicate createGreaterEqualComparable(Expression propertyPath, Y argument, EntityManager manager) { + private static > Predicate createGreaterEqualComparable(Expression propertyPath, Y argument, + EntityManager manager) { CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.greaterThanOrEqualTo(propertyPath, argument); } @@ -484,25 +508,26 @@ private static > Predicate createGreaterEqualCom /** * Apply a "less than" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param argument Argument number. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument number. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createLessThan(Expression propertyPath, Number argument, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); + CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.lt(propertyPath, argument); } /** * Apply a "less than" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param argument Argument. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ - private static > Predicate createLessThanComparable(Expression propertyPath, Y argument, EntityManager manager) { + private static > Predicate createLessThanComparable(Expression propertyPath, Y argument, + EntityManager manager) { CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.lessThan(propertyPath, argument); } @@ -510,25 +535,26 @@ private static > Predicate createLessThanCompara /** * Apply a "less than or equal" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param argument Argument number. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument number. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createLessEqual(Expression propertyPath, Number argument, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); + CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.le(propertyPath, argument); } /** * Apply a "less than or equal" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param argument Argument. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param argument Argument. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ - private static > Predicate createLessEqualComparable(Expression propertyPath, Y argument, EntityManager manager) { + private static > Predicate createLessEqualComparable(Expression propertyPath, Y argument, + EntityManager manager) { CriteriaBuilder builder = manager.getCriteriaBuilder(); return builder.lessThanOrEqualTo(propertyPath, argument); } @@ -536,61 +562,65 @@ private static > Predicate createLessEqualCompar /** * Apply a "in" constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param arguments List of arguments. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param arguments List of arguments. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createIn(Expression propertyPath, List arguments, EntityManager manager) { - return propertyPath.in(arguments); + return propertyPath.in(arguments); } /** * Apply a "not in" (out) constraint to the property path. * - * @param propertyPath Property path that we want to compare. - * @param arguments List of arguments. - * @param manager JPA EntityManager. - * @return Predicate a predicate representation. + * @param propertyPath Property path that we want to compare. + * @param arguments List of arguments. + * @param manager JPA EntityManager. + * @return Predicate a predicate representation. */ private static Predicate createNotIn(Expression propertyPath, List arguments, EntityManager manager) { - CriteriaBuilder builder = manager.getCriteriaBuilder(); - return builder.not(createIn(propertyPath,arguments, manager)); + CriteriaBuilder builder = manager.getCriteriaBuilder(); + return builder.not(createIn(propertyPath, arguments, manager)); } /** * Verify if a property is an Association type. * - * @param property Property to verify. - * @param classMetadata Metamodel of the class we want to check. - * @return true if the property is an associantion, false otherwise. + * @param property Property to verify. + * @param classMetadata Metamodel of the class we want to check. + * @return true if the property is an associantion, false + * otherwise. */ - private static boolean isAssociationType(String property, ManagedType classMetadata){ - return classMetadata.getAttribute(property).isAssociation(); + private static boolean isAssociationType(String property, ManagedType classMetadata) { + return classMetadata.getAttribute(property).isAssociation(); } /** * Verify if a property is an Embedded type. * - * @param property Property to verify. - * @param classMetadata Metamodel of the class we want to check. - * @return true if the property is an embedded attribute, false otherwise. + * @param property Property to verify. + * @param classMetadata Metamodel of the class we want to check. + * @return true if the property is an embedded attribute, + * false otherwise. */ - private static boolean isEmbeddedType(String property, ManagedType classMetadata){ + private static boolean isEmbeddedType(String property, ManagedType classMetadata) { return classMetadata.getAttribute(property).getPersistentAttributeType() == PersistentAttributeType.EMBEDDED; } /** * Verifies if a class metamodel has the specified property. * - * @param property Property name. - * @param classMetadata Class metamodel that may hold that property. - * @return true if the class has that property, false otherwise. + * @param property Property name. + * @param classMetadata Class metamodel that may hold that property. + * @return true if the class has that property, false + * otherwise. */ - private static boolean hasPropertyName(String property, ManagedType classMetadata) { + private static boolean hasPropertyName(String property, ManagedType classMetadata) { Set> names = classMetadata.getAttributes(); for (Attribute name : names) { - if (name.getName().equals(property)) return true; + if (name.getName().equals(property)) + return true; } return false; } @@ -598,18 +628,19 @@ private static boolean hasPropertyName(String property, ManagedType clas /** * Get the property Type out of the metamodel. * - * @param property Property name for type extraction. - * @param classMetadata Reference class metamodel that holds property type. - * @return Class java type for the property, - * if the property is a pluralAttribute it will take the bindable java type of that collection. + * @param property Property name for type extraction. + * @param classMetadata Reference class metamodel that holds property type. + * @return Class java type for the property, + * if the property is a pluralAttribute it will take the bindable + * java type of that collection. */ private static Class findPropertyType(String property, ManagedType classMetadata) { - Class propertyType = null; - if (classMetadata.getAttribute(property).isCollection()) { - propertyType = ((PluralAttribute)classMetadata.getAttribute(property)).getBindableJavaType(); - } else { - propertyType = classMetadata.getAttribute(property).getJavaType(); - } + Class propertyType = null; + if (classMetadata.getAttribute(property).isCollection()) { + propertyType = ((PluralAttribute) classMetadata.getAttribute(property)).getBindableJavaType(); + } else { + propertyType = classMetadata.getAttribute(property).getJavaType(); + } return propertyType; } @@ -623,14 +654,13 @@ private static boolean isNullArgument(Object argument) { return argument == null; } - /** - * Get date regarding the operation (less then or greater than) + * Get date regarding the operation (less then or greater than) * - * @param argument Date to be modified - * @param days Days to be added or removed form argument; - *@return Date modified date - */ + * @param argument Date to be modified + * @param days Days to be added or removed form argument; + * @return Date modified date + */ private static Date modifyDate(Object argument, int days) { Date date = (Date) argument; Calendar c = Calendar.getInstance(); @@ -641,15 +671,24 @@ private static Date modifyDate(Object argument, int days) { } /** - * Builds an error message that reports that the argument is not suitable for use with the comparison operator. + * Builds an error message that reports that the argument is not suitable + * for use with the comparison operator. + * * @param operator operator from the RSQL query * @param argument actual argument produced from the ArgumentParser * @return Error message for use in an Exception */ private static String buildNotComparableMessage(ComparisonOperator operator, Object argument) { - return String.format("Invalid type for comparison operator: %s type: %s must implement Comparable<%s>", - operator, - argument.getClass().getName(), - argument.getClass().getSimpleName()); + return String.format("Invalid type for comparison operator: %s type: %s must implement Comparable<%s>", operator, + argument.getClass().getName(), argument.getClass().getSimpleName()); + } + + private static class RecursiveHolder { + + public RecursiveHolder(T object) { + this.object = object; + } + + public T object; } } diff --git a/src/test/java/com/github/tennaito/rsql/jpa/JpaVisitorTest.java b/src/test/java/com/github/tennaito/rsql/jpa/JpaVisitorTest.java index c61a0c5..2c2eecb 100644 --- a/src/test/java/com/github/tennaito/rsql/jpa/JpaVisitorTest.java +++ b/src/test/java/com/github/tennaito/rsql/jpa/JpaVisitorTest.java @@ -23,7 +23,6 @@ */ package com.github.tennaito.rsql.jpa; - import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; @@ -38,6 +37,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import javax.persistence.EntityManager; @@ -68,392 +68,397 @@ */ public class JpaVisitorTest extends AbstractVisitorTest { - final static XorNode xorNode = new XorNode(new ArrayList()); - + final static XorNode xorNode = new XorNode(new ArrayList()); + @Before public void setUp() throws Exception { - entityManager = EntityManagerFactoryInitializer.getEntityManagerFactory().createEntityManager(); + entityManager = EntityManagerFactoryInitializer.getEntityManagerFactory().createEntityManager(); entityClass = Course.class; } @Test public void testUnknowProperty() throws Exception { - try { - Node rootNode = new RSQLParser().parse("invalid==1"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - fail(); - } catch (IllegalArgumentException e) { - assertEquals("Unknown property: invalid from entity " + Course.class.getName(), e.getMessage()); - } - } - + try { + Node rootNode = new RSQLParser().parse("invalid==1"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Unknown property: invalid from entity " + Course.class.getName(), e.getMessage()); + } + } + @Test public void testSimpleSelection() throws Exception { - Node rootNode = new RSQLParser().parse("id==1"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("id==1"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); } - + @Test public void testSimpleSelectionWhenPassingArgumentInTemplate() throws Exception { - Node rootNode = new RSQLParser().parse("id==1"); - // not a recommended usage - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(new Course()); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("id==1"); + // not a recommended usage + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(new Course()); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); } - @Test public void testNotEqualSelection() throws Exception { - Node rootNode = new RSQLParser().parse("id!=1"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("id!=1"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals(0, courses.size()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(0, courses.size()); } @Test public void testGreaterThanSelection() throws Exception { - Node rootNode = new RSQLParser().parse("id=gt=1"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals(0, courses.size()); - } - - @Test - public void testGreaterThanDate() throws Exception { - Node rootNode = new RSQLParser().parse("startDate=gt='2001-01-01'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals(1, courses.size()); - } - - @Test - public void testGreaterThanString() throws Exception { - Node rootNode = new RSQLParser().parse("code=gt='ABC'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals(1, courses.size()); - } - - @Test - public void testGreaterThanNotComparable() throws Exception { - try { - Node rootNode = new RSQLParser().parse("details.teacher=gt='ABC'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - rootNode.accept(visitor, entityManager); - fail("should have failed since type isn't Comparable"); - } catch (IllegalArgumentException e) { - assertEquals("Invalid type for comparison operator: =gt= type: com.github.tennaito.rsql.jpa.entity.Teacher must implement Comparable", e.getMessage()); - } - } - - @Test - public void testGreaterThanEqualSelection() throws Exception { - Node rootNode = new RSQLParser().parse("id=ge=1"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - } - - @Test - public void testGreaterThanEqualSelectionForDate() throws Exception { - Node rootNode = new RSQLParser().parse("startDate=ge='2016-01-01'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - } - - @Test - public void testGreaterThanEqualSelectionForString() throws Exception { - Node rootNode = new RSQLParser().parse("code=ge='MI-MDW'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - } - - @Test - public void testGreaterThanEqualNotComparable() throws Exception { - try { - Node rootNode = new RSQLParser().parse("details.teacher=ge='ABC'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - rootNode.accept(visitor, entityManager); - fail("should have failed since type isn't Comparable"); - } catch (IllegalArgumentException e) { - assertEquals("Invalid type for comparison operator: =ge= type: com.github.tennaito.rsql.jpa.entity.Teacher must implement Comparable", e.getMessage()); - } - } - - @Test + Node rootNode = new RSQLParser().parse("id=gt=1"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(0, courses.size()); + } + + @Test + public void testGreaterThanDate() throws Exception { + Node rootNode = new RSQLParser().parse("startDate=gt='2001-01-01'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(1, courses.size()); + } + + @Test + public void testGreaterThanString() throws Exception { + Node rootNode = new RSQLParser().parse("code=gt='ABC'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(1, courses.size()); + } + + @Test + public void testGreaterThanNotComparable() throws Exception { + try { + Node rootNode = new RSQLParser().parse("details.teacher=gt='ABC'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + rootNode.accept(visitor, entityManager); + fail("should have failed since type isn't Comparable"); + } catch (IllegalArgumentException e) { + assertEquals( + "Invalid type for comparison operator: =gt= type: com.github.tennaito.rsql.jpa.entity.Teacher must implement Comparable", + e.getMessage()); + } + } + + @Test + public void testGreaterThanEqualSelection() throws Exception { + Node rootNode = new RSQLParser().parse("id=ge=1"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } + + @Test + public void testGreaterThanEqualSelectionForDate() throws Exception { + Node rootNode = new RSQLParser().parse("startDate=ge='2016-01-01'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } + + @Test + public void testGreaterThanEqualSelectionForString() throws Exception { + Node rootNode = new RSQLParser().parse("code=ge='MI-MDW'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } + + @Test + public void testGreaterThanEqualNotComparable() throws Exception { + try { + Node rootNode = new RSQLParser().parse("details.teacher=ge='ABC'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + rootNode.accept(visitor, entityManager); + fail("should have failed since type isn't Comparable"); + } catch (IllegalArgumentException e) { + assertEquals( + "Invalid type for comparison operator: =ge= type: com.github.tennaito.rsql.jpa.entity.Teacher must implement Comparable", + e.getMessage()); + } + } + + @Test public void testLessThanSelection() throws Exception { - Node rootNode = new RSQLParser().parse("id=lt=1"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("id=lt=1"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals(0, courses.size()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(0, courses.size()); } @Test public void testLessThanEqualSelection() throws Exception { - Node rootNode = new RSQLParser().parse("id=le=1"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - } - - @Test - public void testLessThanDate() throws Exception { - Node rootNode = new RSQLParser().parse("startDate=lt='2222-02-02'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals(1, courses.size()); - } - - @Test - public void testLessThanString() throws Exception { - Node rootNode = new RSQLParser().parse("code=lt='MI-MDZ'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals(1, courses.size()); - } - - @Test - public void testLessThanNotComparable() throws Exception { - try { - Node rootNode = new RSQLParser().parse("details.teacher=lt='ABC'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - rootNode.accept(visitor, entityManager); - fail("should have failed since type isn't Comparable"); - } catch (IllegalArgumentException e) { - assertEquals("Invalid type for comparison operator: =lt= type: com.github.tennaito.rsql.jpa.entity.Teacher must implement Comparable", e.getMessage()); - } - } - - @Test - public void testLessThanEqualSelectionForDate() throws Exception { - Node rootNode = new RSQLParser().parse("startDate=le='2100-01-01'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - } - - @Test - public void testLessThanEqualSelectionForString() throws Exception { - Node rootNode = new RSQLParser().parse("code=le='MI-MDW'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - } - - @Test - public void testLessThanEqualNotComparable() throws Exception { - try { - Node rootNode = new RSQLParser().parse("details.teacher=le='ABC'"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - rootNode.accept(visitor, entityManager); - fail("should have failed since type isn't Comparable"); - } catch (IllegalArgumentException e) { - assertEquals("Invalid type for comparison operator: =le= type: com.github.tennaito.rsql.jpa.entity.Teacher must implement Comparable", e.getMessage()); - } - } - - - @Test + Node rootNode = new RSQLParser().parse("id=le=1"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } + + @Test + public void testLessThanDate() throws Exception { + Node rootNode = new RSQLParser().parse("startDate=lt='2222-02-02'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(1, courses.size()); + } + + @Test + public void testLessThanString() throws Exception { + Node rootNode = new RSQLParser().parse("code=lt='MI-MDZ'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(1, courses.size()); + } + + @Test + public void testLessThanNotComparable() throws Exception { + try { + Node rootNode = new RSQLParser().parse("details.teacher=lt='ABC'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + rootNode.accept(visitor, entityManager); + fail("should have failed since type isn't Comparable"); + } catch (IllegalArgumentException e) { + assertEquals( + "Invalid type for comparison operator: =lt= type: com.github.tennaito.rsql.jpa.entity.Teacher must implement Comparable", + e.getMessage()); + } + } + + @Test + public void testLessThanEqualSelectionForDate() throws Exception { + Node rootNode = new RSQLParser().parse("startDate=le='2100-01-01'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } + + @Test + public void testLessThanEqualSelectionForString() throws Exception { + Node rootNode = new RSQLParser().parse("code=le='MI-MDW'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } + + @Test + public void testLessThanEqualNotComparable() throws Exception { + try { + Node rootNode = new RSQLParser().parse("details.teacher=le='ABC'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + rootNode.accept(visitor, entityManager); + fail("should have failed since type isn't Comparable"); + } catch (IllegalArgumentException e) { + assertEquals( + "Invalid type for comparison operator: =le= type: com.github.tennaito.rsql.jpa.entity.Teacher must implement Comparable", + e.getMessage()); + } + } + + @Test public void testInSelection() throws Exception { - Node rootNode = new RSQLParser().parse("id=in=(1,2,3,4)"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("id=in=(1,2,3,4)"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); } @Test public void testOutSelection() throws Exception { - Node rootNode = new RSQLParser().parse("id=out=(1,2,3,4)"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("id=out=(1,2,3,4)"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals(0, courses.size()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(0, courses.size()); } @Test public void testLikeSelection() throws Exception { - Node rootNode = new RSQLParser().parse("name==*Course"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("name==*Course"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); } @Test public void testNotLikeSelection() throws Exception { - Node rootNode = new RSQLParser().parse("name!=*Course"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("name!=*Course"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals(0, courses.size()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(0, courses.size()); } - @Test public void testIsNullSelection() throws Exception { - Node rootNode = new RSQLParser().parse("name==null"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("name==null"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals(0, courses.size()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(0, courses.size()); } @Test public void testNotIsNullSelection() throws Exception { - Node rootNode = new RSQLParser().parse("name!=null"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("name!=null"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); } @Test public void testSetEntity() { Node rootNode = new RSQLParser().parse("id==1"); RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - ((JpaCriteriaQueryVisitor)visitor).setEntityClass(Course.class); + ((JpaCriteriaQueryVisitor) visitor).setEntityClass(Course.class); CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = (List)entityManager.createQuery(query).getResultList(); + List courses = (List) entityManager.createQuery(query).getResultList(); assertEquals(1, courses.size()); } @Test - public void testUndefinedComparisonOperator() { - try { - ComparisonOperator newOp = new ComparisonOperator("=def="); - Set set = new HashSet(); - set.add(newOp); - Node rootNode = new RSQLParser(set).parse("id=def=null"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - fail(); - } catch(Exception e) { - assertEquals("Unknown operator: =def=", e.getMessage()); - } - } + public void testUndefinedComparisonOperator() { + try { + ComparisonOperator newOp = new ComparisonOperator("=def="); + Set set = new HashSet(); + set.add(newOp); + Node rootNode = new RSQLParser(set).parse("id=def=null"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + List courses = entityManager.createQuery(query).getResultList(); + fail(); + } catch (Exception e) { + assertEquals("Unknown operator: =def=", e.getMessage()); + } + } - @Test + @Test public void testDefinedComparisonOperator() { - // define the new operator - ComparisonOperator newOp = new ComparisonOperator("=def="); - Set set = new HashSet(); - set.add(newOp); - // execute parser - Node rootNode = new RSQLParser(set).parse("id=def=1"); - - JpaCriteriaQueryVisitor visitor = new JpaCriteriaQueryVisitor(); - createDefOperator(visitor); - - CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - } - - private void createDefOperator(JpaCriteriaQueryVisitor visitor) { - // define new operator resolver - PredicateBuilderStrategy predicateStrategy = new PredicateBuilderStrategy() { - public Predicate createPredicate(Node node, From root, Class entity, - EntityManager manager, BuilderTools tools) - throws IllegalArgumentException { - ComparisonNode comp = ((ComparisonNode)node); - ComparisonNode def = new ComparisonNode(ComparisonOperatorProxy.EQUAL.getOperator(), comp.getSelector(), comp.getArguments()); - return PredicateBuilder.createPredicate(def, root, entity, manager, tools); - } - }; - visitor.getBuilderTools().setPredicateBuilder(predicateStrategy); - } + // define the new operator + ComparisonOperator newOp = new ComparisonOperator("=def="); + Set set = new HashSet(); + set.add(newOp); + // execute parser + Node rootNode = new RSQLParser(set).parse("id=def=1"); + + JpaCriteriaQueryVisitor visitor = new JpaCriteriaQueryVisitor(); + createDefOperator(visitor); + + CriteriaQuery query = rootNode.accept(visitor, entityManager); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } + + private void createDefOperator(JpaCriteriaQueryVisitor visitor) { + // define new operator resolver + PredicateBuilderStrategy predicateStrategy = new PredicateBuilderStrategy() { + + public Predicate createPredicate(Node node, From root, Class entity, EntityManager manager, + BuilderTools tools) throws IllegalArgumentException { + ComparisonNode comp = ((ComparisonNode) node); + ComparisonNode def = new ComparisonNode(ComparisonOperatorProxy.EQUAL.getOperator(), comp.getSelector(), comp.getArguments()); + return PredicateBuilder.createPredicate(def, root, entity, manager, tools); + } + }; + visitor.getBuilderTools().setPredicateBuilder(predicateStrategy); + } @Test public void testAssociationSelection() throws Exception { - Node rootNode = new RSQLParser().parse("department.id==1"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - } - - @Test - public void testAssociationAliasSelection() throws Exception { - Node rootNode = new RSQLParser().parse("dept.id==1"); - JpaCriteriaQueryVisitor visitor = new JpaCriteriaQueryVisitor(); - // add to SimpleMapper - assertNotNull(((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).getMapping()); - ((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, new HashMap()); - ((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, "dept", "department"); - - CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - - ((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).setMapping(null); - assertNull(((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).getMapping()); - } - - @Test - public void testAssociationAliasSelectionWithAssociationAlias() throws Exception { - Node rootNode = new RSQLParser().parse("dept_id==1"); - JpaCriteriaQueryVisitor visitor = new JpaCriteriaQueryVisitor(); - // add to SimpleMapper - assertNotNull(((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).getMapping()); - ((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, new HashMap()); - ((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, "dept_id", "department.id"); - - CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - - ((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).setMapping(null); - assertNull(((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).getMapping()); - } - - @Test + Node rootNode = new RSQLParser().parse("department.id==1"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } + + @Test + public void testAssociationAliasSelection() throws Exception { + Node rootNode = new RSQLParser().parse("dept.id==1"); + JpaCriteriaQueryVisitor visitor = new JpaCriteriaQueryVisitor(); + // add to SimpleMapper + assertNotNull(((SimpleMapper) visitor.getBuilderTools().getPropertiesMapper()).getMapping()); + ((SimpleMapper) visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, new HashMap()); + ((SimpleMapper) visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, "dept", "department"); + + CriteriaQuery query = rootNode.accept(visitor, entityManager); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + + ((SimpleMapper) visitor.getBuilderTools().getPropertiesMapper()).setMapping(null); + assertNull(((SimpleMapper) visitor.getBuilderTools().getPropertiesMapper()).getMapping()); + } + + @Test + public void testAssociationAliasSelectionWithAssociationAlias() throws Exception { + Node rootNode = new RSQLParser().parse("dept_id==1"); + JpaCriteriaQueryVisitor visitor = new JpaCriteriaQueryVisitor(); + // add to SimpleMapper + assertNotNull(((SimpleMapper) visitor.getBuilderTools().getPropertiesMapper()).getMapping()); + ((SimpleMapper) visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, new HashMap()); + ((SimpleMapper) visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, "dept_id", "department.id"); + + CriteriaQuery query = rootNode.accept(visitor, entityManager); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + + ((SimpleMapper) visitor.getBuilderTools().getPropertiesMapper()).setMapping(null); + assertNull(((SimpleMapper) visitor.getBuilderTools().getPropertiesMapper()).getMapping()); + } + + @Test public void testAndSelection() throws Exception { Node rootNode = new RSQLParser().parse("department.id==1;id==2"); RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); @@ -463,37 +468,37 @@ public void testAndSelection() throws Exception { assertEquals(0, courses.size()); } - @Test - public void testBasicSelectionCount() throws Exception { - Node rootNode = new RSQLParser().parse("department.id==1"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaCountQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + @Test + public void testBasicSelectionCount() throws Exception { + Node rootNode = new RSQLParser().parse("department.id==1"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaCountQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - Long courseCount = entityManager.createQuery(query).getSingleResult(); - assertEquals((Long)1l, courseCount); - Root root = ((JpaCriteriaCountQueryVisitor)visitor).getRoot(); - assertNotNull(root); - ((JpaCriteriaCountQueryVisitor)visitor).setRoot(root); - } + Long courseCount = entityManager.createQuery(query).getSingleResult(); + assertEquals((Long) 1l, courseCount); + Root root = ((JpaCriteriaCountQueryVisitor) visitor).getRoot(); + assertNotNull(root); + ((JpaCriteriaCountQueryVisitor) visitor).setRoot(root); + } - @Test + @Test public void testAndSelectionCount() throws Exception { Node rootNode = new RSQLParser().parse("department.id==1;id==2"); RSQLVisitor, EntityManager> visitor = new JpaCriteriaCountQueryVisitor(); CriteriaQuery query = rootNode.accept(visitor, entityManager); Long courseCount = entityManager.createQuery(query).getSingleResult(); - assertEquals((Long)0l, courseCount); + assertEquals((Long) 0l, courseCount); } @Test public void testOrSelection() throws Exception { - Node rootNode = new RSQLParser().parse("department.id==1,id==2"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("department.id==1,id==2"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); } @Test @@ -503,172 +508,187 @@ public void testOrSelectionCount() throws Exception { CriteriaQuery query = rootNode.accept(visitor, entityManager); Long courseCount = entityManager.createQuery(query).getSingleResult(); - assertEquals((Long)1l, courseCount); + assertEquals((Long) 1l, courseCount); } @Test public void testVariousNodesSelection() throws Exception { - Node rootNode = new RSQLParser().parse("((department.id==1;id==2),id<3);department.id=out=(3,4,5)"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("((department.id==1;id==2),id<3);department.id=out=(3,4,5)"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); } - + @Test public void testNavigateThroughCollectionSelection() throws Exception { - Node rootNode = new RSQLParser().parse("department.head.titles.name==Phd"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); + Node rootNode = new RSQLParser().parse("department.head.titles.name==Phd"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); } - + @Test public void testUnsupportedNode() throws Exception { - try{ - PredicateBuilder.createPredicate(new OtherNode(), null, null, null, null); - fail(); - } catch (IllegalArgumentException e) { - assertEquals("Unknown expression type: class com.github.tennaito.rsql.jpa.JpaVisitorTest$OtherNode", e.getMessage()); - } + try { + PredicateBuilder.createPredicate(new OtherNode(), null, null, null, null); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Unknown expression type: class com.github.tennaito.rsql.jpa.JpaVisitorTest$OtherNode", e.getMessage()); + } } - + @Test public void testSetBuilderTools() throws Exception { - JpaCriteriaQueryVisitor visitor = new JpaCriteriaQueryVisitor(); - visitor.setBuilderTools(null); - assertNotNull(visitor.getBuilderTools()); - - visitor.getBuilderTools().setArgumentParser(null); - assertNotNull(visitor.getBuilderTools().getArgumentParser()); - - visitor.getBuilderTools().setPropertiesMapper(null); - assertNotNull(visitor.getBuilderTools().getPropertiesMapper()); - - visitor.getBuilderTools().setPredicateBuilder(null); - assertNull(visitor.getBuilderTools().getPredicateBuilder()); - } - + JpaCriteriaQueryVisitor visitor = new JpaCriteriaQueryVisitor(); + visitor.setBuilderTools(null); + assertNotNull(visitor.getBuilderTools()); + + visitor.getBuilderTools().setArgumentParser(null); + assertNotNull(visitor.getBuilderTools().getArgumentParser()); + + visitor.getBuilderTools().setPropertiesMapper(null); + assertNotNull(visitor.getBuilderTools().getPropertiesMapper()); + + visitor.getBuilderTools().setPredicateBuilder(null); + assertNull(visitor.getBuilderTools().getPredicateBuilder()); + } + @Test public void testUnsupportedLogicalNode() throws Exception { - try{ - PredicateBuilder.createPredicate(JpaVisitorTest.xorNode, null, Course.class, entityManager, null); - fail(); - } catch (IllegalArgumentException e) { - assertEquals("Unknown operator: ^", e.getMessage()); - } + try { + PredicateBuilder.createPredicate(JpaVisitorTest.xorNode, null, Course.class, entityManager, null); + fail(); + } catch (IllegalArgumentException e) { + assertEquals("Unknown operator: ^", e.getMessage()); + } } - + @Test public void testPrivateConstructor() throws Exception { - Constructor priv = PredicateBuilder.class.getDeclaredConstructor(); - // It is really private? - assertFalse(priv.isAccessible()); - priv.setAccessible(true); - Object predicateBuilder = priv.newInstance(); - // When used it returns a instance? - assertNotNull(predicateBuilder); - } - + Constructor priv = PredicateBuilder.class.getDeclaredConstructor(); + // It is really private? + assertFalse(priv.isAccessible()); + priv.setAccessible(true); + Object predicateBuilder = priv.newInstance(); + // When used it returns a instance? + assertNotNull(predicateBuilder); + } + ////////////////////////// Mocks ////////////////////////// - + protected static class OtherNode extends AbstractNode { - public R accept(RSQLVisitor visitor, A param) { - throw new UnsupportedOperationException(); - } + public R accept(RSQLVisitor visitor, A param) { + throw new UnsupportedOperationException(); + } } - + protected static class XorNode extends LogicalNode { - final static LogicalOperator XOR = createLogicalOperatorXor(); - - public XorNode(List children) { - super(XOR, children); - } - - public static void setStaticFinalField(Field field, Object value) throws NoSuchFieldException, IllegalAccessException { - // we mark the field to be public - field.setAccessible(true); - // next we change the modifier in the Field instance to - // not be final anymore, thus tricking reflection into - // letting us modify the static final field - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - int modifiers = modifiersField.getInt(field); - // blank out the final bit in the modifiers int - modifiers &= ~Modifier.FINAL; - modifiersField.setInt(field, modifiers); - sun.reflect.FieldAccessor fa = sun.reflect.ReflectionFactory.getReflectionFactory().newFieldAccessor(field, false); - fa.set(null, value); - } - - private static LogicalOperator createLogicalOperatorXor() { - LogicalOperator xor = null; - try { - Constructor cstr = LogicalOperator.class.getDeclaredConstructor(String.class, int.class, String.class); - sun.reflect.ReflectionFactory factory = sun.reflect.ReflectionFactory.getReflectionFactory(); - xor = (LogicalOperator) factory.newConstructorAccessor(cstr).newInstance(new Object[]{"XOR", 2, "^"}); - - Field ordinalField = Enum.class.getDeclaredField("ordinal"); - ordinalField.setAccessible(true); - - LogicalOperator[] values = xor.values(); - Field valuesField = LogicalOperator.class.getDeclaredField("ENUM$VALUES"); - valuesField.setAccessible(true); - LogicalOperator[] newValues = Arrays.copyOf(values, values.length + 1); - newValues[newValues.length - 1] = xor; - setStaticFinalField(valuesField, newValues); - int ordinal = newValues.length - 1; - ordinalField.set(xor, ordinal); - } catch (ReflectiveOperationException e) { - // do nothing - e.printStackTrace(); - } - return xor; - } - - @Override - public LogicalNode withChildren(List children) { - return new XorNode(children); - } - - public R accept(RSQLVisitor visitor, A param) { - throw new UnsupportedOperationException(); - } - } - + final static LogicalOperator XOR = createLogicalOperatorXor(); + + public XorNode(List children) { + super(XOR, children); + } + + public static void setStaticFinalField(Field field, Object value) throws NoSuchFieldException, IllegalAccessException { + // we mark the field to be public + field.setAccessible(true); + // next we change the modifier in the Field instance to + // not be final anymore, thus tricking reflection into + // letting us modify the static final field + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + int modifiers = modifiersField.getInt(field); + // blank out the final bit in the modifiers int + modifiers &= ~Modifier.FINAL; + modifiersField.setInt(field, modifiers); + sun.reflect.FieldAccessor fa = sun.reflect.ReflectionFactory.getReflectionFactory().newFieldAccessor(field, false); + fa.set(null, value); + } + + private static LogicalOperator createLogicalOperatorXor() { + LogicalOperator xor = null; + try { + Constructor cstr = LogicalOperator.class.getDeclaredConstructor(String.class, int.class, String.class); + sun.reflect.ReflectionFactory factory = sun.reflect.ReflectionFactory.getReflectionFactory(); + xor = (LogicalOperator) factory.newConstructorAccessor(cstr).newInstance(new Object[]{"XOR", 2, "^"}); + + Field ordinalField = Enum.class.getDeclaredField("ordinal"); + ordinalField.setAccessible(true); + + LogicalOperator[] values = xor.values(); + Field valuesField = LogicalOperator.class.getDeclaredField("ENUM$VALUES"); + valuesField.setAccessible(true); + LogicalOperator[] newValues = Arrays.copyOf(values, values.length + 1); + newValues[newValues.length - 1] = xor; + setStaticFinalField(valuesField, newValues); + int ordinal = newValues.length - 1; + ordinalField.set(xor, ordinal); + } catch (ReflectiveOperationException e) { + // do nothing + e.printStackTrace(); + } + return xor; + } + + @Override + public LogicalNode withChildren(List children) { + return new XorNode(children); + } + + public R accept(RSQLVisitor visitor, A param) { + throw new UnsupportedOperationException(); + } + } + @Test public void testUndefinedRootForPredicate() throws Exception { - try { - Node rootNode = new RSQLParser().parse("id==1"); - RSQLVisitor visitor = new JpaPredicateVisitor(); - Predicate query = rootNode.accept(visitor, entityManager); - } catch (IllegalArgumentException e) { - assertEquals("From root node was undefined.", e.getMessage()); - } - } - - @Test - public void testSelectionUsingEmbeddedField() throws Exception { - Node rootNode = new RSQLParser().parse("details.description==test"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - } - - @Test - public void testSelectionUsingEmbeddedAssociationField() throws Exception { - Node rootNode = new RSQLParser().parse("details.teacher.specialtyDescription==Maths"); - RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); - CriteriaQuery query = rootNode.accept(visitor, entityManager); - - List courses = entityManager.createQuery(query).getResultList(); - assertEquals("Testing Course", courses.get(0).getName()); - } + try { + Node rootNode = new RSQLParser().parse("id==1"); + RSQLVisitor visitor = new JpaPredicateVisitor(); + Predicate query = rootNode.accept(visitor, entityManager); + } catch (IllegalArgumentException e) { + assertEquals("From root node was undefined.", e.getMessage()); + } + } + + @Test + public void testSelectionUsingEmbeddedField() throws Exception { + Node rootNode = new RSQLParser().parse("details.description==test"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } + + @Test + public void testSelectionUsingEmbeddedAssociationField() throws Exception { + Node rootNode = new RSQLParser().parse("details.teacher.specialtyDescription==Maths"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } + + @Test + public void testSelectionUsingEmbeddedAssociationFieldWithMapping() throws Exception { + Node rootNode = new RSQLParser().parse("details2.teacher.specialtyDescription==Maths"); + JpaCriteriaQueryVisitor visitor = new JpaCriteriaQueryVisitor(); + SimpleMapper mapper = new SimpleMapper(); + Map mappingSelector = new HashMap(); + mappingSelector.put("details2", "details"); + mapper.addMapping(Course.class, mappingSelector); + visitor.getBuilderTools().setPropertiesMapper(mapper); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals("Testing Course", courses.get(0).getName()); + } }