/* * The MIT License * * Copyright 2015 Antonio Rabelo. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.github.tennaito.rsql.jpa; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.fail; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.persistence.EntityManager; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.From; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.junit.Before; import org.junit.Test; import com.github.tennaito.rsql.builder.BuilderTools; import com.github.tennaito.rsql.jpa.entity.Course; import com.github.tennaito.rsql.misc.SimpleMapper; import com.github.tennaito.rsql.parser.ast.ComparisonOperatorProxy; import cz.jirutka.rsql.parser.RSQLParser; import cz.jirutka.rsql.parser.ast.AbstractNode; 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.LogicalOperator; import cz.jirutka.rsql.parser.ast.Node; import cz.jirutka.rsql.parser.ast.RSQLVisitor; /** * @author AntonioRabelo */ public class JpaVisitorTest extends AbstractVisitorTest<Course> { final static XorNode xorNode = new XorNode(new ArrayList<Node>()); @Before public void setUp() throws Exception { entityManager = EntityManagerFactoryInitializer.getEntityManagerFactory().createEntityManager(); entityClass = Course.class; } @Test public void testUnknowProperty() throws Exception { try { Node rootNode = new RSQLParser().parse("invalid==1"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(new Course()); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals(0, courses.size()); } @Test public void testGreaterThanSelection() throws Exception { Node rootNode = new RSQLParser().parse("id=gt=1"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals(1, courses.size()); } @Test public void testGreaterThanString() throws Exception { Node rootNode = new RSQLParser().parse("code=gt='ABC'"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); 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<Teacher>", e.getMessage()); } } @Test public void testGreaterThanEqualSelection() throws Exception { Node rootNode = new RSQLParser().parse("id=ge=1"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); 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<Teacher>", e.getMessage()); } } @Test public void testLessThanSelection() throws Exception { Node rootNode = new RSQLParser().parse("id=lt=1"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals(0, courses.size()); } @Test public void testLessThanEqualSelection() throws Exception { Node rootNode = new RSQLParser().parse("id=le=1"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); 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<Teacher>", e.getMessage()); } } @Test public void testLessThanEqualSelectionForDate() throws Exception { Node rootNode = new RSQLParser().parse("startDate=le='2100-01-01'"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); 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<Teacher>", e.getMessage()); } } @Test public void testInSelection() throws Exception { Node rootNode = new RSQLParser().parse("id=in=(1,2,3,4)"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals(0, courses.size()); } @Test public void testLikeSelection() throws Exception { Node rootNode = new RSQLParser().parse("name==*Course"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals(0, courses.size()); } @Test public void testIsNullSelection() throws Exception { Node rootNode = new RSQLParser().parse("name==null"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals(0, courses.size()); } @Test public void testNotIsNullSelection() throws Exception { Node rootNode = new RSQLParser().parse("name!=null"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals("Testing Course", courses.get(0).getName()); } @Test public void testSetEntity() { Node rootNode = new RSQLParser().parse("id==1"); RSQLVisitor<CriteriaQuery<?>, EntityManager> visitor = new JpaCriteriaQueryVisitor(); ((JpaCriteriaQueryVisitor)visitor).setEntityClass(Course.class); CriteriaQuery<?> query = rootNode.accept(visitor, entityManager); List<Course> courses = (List<Course>)entityManager.createQuery(query).getResultList(); assertEquals(1, courses.size()); } @Test public void testUndefinedComparisonOperator() { try { ComparisonOperator newOp = new ComparisonOperator("=def="); Set<ComparisonOperator> set = new HashSet<ComparisonOperator>(); set.add(newOp); Node rootNode = new RSQLParser(set).parse("id=def=null"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); fail(); } catch(Exception e) { assertEquals("Unknown operator: =def=", e.getMessage()); } } @Test public void testDefinedComparisonOperator() { // define the new operator ComparisonOperator newOp = new ComparisonOperator("=def="); Set<ComparisonOperator> set = new HashSet<ComparisonOperator>(); set.add(newOp); // execute parser Node rootNode = new RSQLParser(set).parse("id=def=1"); JpaCriteriaQueryVisitor<Course> visitor = new JpaCriteriaQueryVisitor<Course>(); createDefOperator(visitor); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals("Testing Course", courses.get(0).getName()); } private void createDefOperator(JpaCriteriaQueryVisitor<Course> visitor) { // define new operator resolver PredicateBuilderStrategy predicateStrategy = new PredicateBuilderStrategy() { public <T> Predicate createPredicate(Node node, From root, Class<T> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<Course> visitor = new JpaCriteriaQueryVisitor<Course>(); // add to SimpleMapper assertNotNull(((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).getMapping()); ((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, new HashMap<String, String>()); ((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, "dept", "department"); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<Course> visitor = new JpaCriteriaQueryVisitor<Course>(); // add to SimpleMapper assertNotNull(((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).getMapping()); ((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, new HashMap<String, String>()); ((SimpleMapper)visitor.getBuilderTools().getPropertiesMapper()).addMapping(Course.class, "dept_id", "department.id"); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals(0, courses.size()); } @Test public void testBasicSelectionCount() throws Exception { Node rootNode = new RSQLParser().parse("department.id==1"); RSQLVisitor<CriteriaQuery<Long>, EntityManager> visitor = new JpaCriteriaCountQueryVisitor<Course>(); CriteriaQuery<Long> query = rootNode.accept(visitor, entityManager); Long courseCount = entityManager.createQuery(query).getSingleResult(); assertEquals((Long)1l, courseCount); Root<Course> root = ((JpaCriteriaCountQueryVisitor<Course>)visitor).getRoot(); assertNotNull(root); ((JpaCriteriaCountQueryVisitor<Course>)visitor).setRoot(root); } @Test public void testAndSelectionCount() throws Exception { Node rootNode = new RSQLParser().parse("department.id==1;id==2"); RSQLVisitor<CriteriaQuery<Long>, EntityManager> visitor = new JpaCriteriaCountQueryVisitor<Course>(); CriteriaQuery<Long> query = rootNode.accept(visitor, entityManager); Long courseCount = entityManager.createQuery(query).getSingleResult(); assertEquals((Long)0l, courseCount); } @Test public void testOrSelection() throws Exception { Node rootNode = new RSQLParser().parse("department.id==1,id==2"); RSQLVisitor<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals("Testing Course", courses.get(0).getName()); } @Test public void testOrSelectionCount() throws Exception { Node rootNode = new RSQLParser().parse("department.id==1,id==2"); RSQLVisitor<CriteriaQuery<Long>, EntityManager> visitor = new JpaCriteriaCountQueryVisitor<Course>(); CriteriaQuery<Long> query = rootNode.accept(visitor, entityManager); Long courseCount = entityManager.createQuery(query).getSingleResult(); 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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()); } } @Test public void testSetBuilderTools() throws Exception { JpaCriteriaQueryVisitor<Course> visitor = new JpaCriteriaQueryVisitor<Course>(); 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()); } } @Test public void testPrivateConstructor() throws Exception { Constructor<PredicateBuilder> 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, A> R accept(RSQLVisitor<R, A> visitor, A param) { throw new UnsupportedOperationException(); } } protected static class XorNode extends LogicalNode { final static LogicalOperator XOR = createLogicalOperatorXor(); public XorNode(List<? extends Node> 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<LogicalOperator> 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<? extends Node> children) { return new XorNode(children); } public <R, A> R accept(RSQLVisitor<R, A> visitor, A param) { throw new UnsupportedOperationException(); } } @Test public void testUndefinedRootForPredicate() throws Exception { try { Node rootNode = new RSQLParser().parse("id==1"); RSQLVisitor<Predicate, EntityManager> visitor = new JpaPredicateVisitor<Course>(); 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> 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<CriteriaQuery<Course>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Course>(); CriteriaQuery<Course> query = rootNode.accept(visitor, entityManager); List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals("Testing Course", courses.get(0).getName()); } }