package org.sculptor.framework.accessapi; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.sculptor.framework.accessapi.ConditionalCriteriaBuilder.criteriaFor; import static org.sculptor.framework.accessapi.ConditionalCriteriaBuilderTest.PersonProperties.aaa; import static org.sculptor.framework.accessapi.ConditionalCriteriaBuilderTest.PersonProperties.bbb; import static org.sculptor.framework.accessapi.ConditionalCriteriaBuilderTest.PersonProperties.ccc; import static org.sculptor.framework.accessapi.ConditionalCriteriaBuilderTest.PersonProperties.ddd; import static org.sculptor.framework.accessapi.ConditionalCriteriaBuilderTest.PersonProperties.primaryAddress; import java.util.List; import org.junit.Test; import org.sculptor.framework.accessapi.ConditionalCriteria; import org.sculptor.framework.accessapi.ConditionalCriteriaBuilderTest.AddressProperties.AddressProperty; import org.sculptor.framework.domain.LeafProperty; import org.sculptor.framework.domain.PropertiesCollection; import org.sculptor.framework.domain.Property; public class ConditionalCriteriaBuilderTest { @Test public void testLongPathElements() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(PersonProperties.boss().boss().boss().aaa()).eq(1234) .buildSingle(); assertEquals("aaa", criteria.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Equal, criteria.getOperator()); assertEquals(1234, criteria.getFirstOperant()); assertNull(criteria.getSecondOperant()); for (String path : criteria.getPropertyPath()) { assertEquals("boss", path); } } @Test public void shouldBuildSimpleEqualsCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(PersonProperties.aaa()).eq(1234) .buildSingle(); assertEquals("aaa", criteria.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Equal, criteria.getOperator()); assertEquals(1234, criteria.getFirstOperant()); assertNull(criteria.getSecondOperant()); } @Test public void shouldBuildNestedProperties() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty( PersonProperties.primaryAddress().city()) .eq("Stockholm") .buildSingle(); assertEquals("primaryAddress.city", criteria.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Equal, criteria.getOperator()); assertEquals("Stockholm", criteria.getFirstOperant()); assertNull(criteria.getSecondOperant()); } @Test public void shouldBuildWithStaticImportProperty() { // import static org.sculptor.framework.accessapi.ConditionalCriteriaBuilderTest.Person.PersonProperties.primaryAddress; ConditionalCriteria criteria = criteriaFor(Person.class).withProperty( primaryAddress().city()) .eq("Stockholm").buildSingle(); assertEquals("primaryAddress.city", criteria.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Equal, criteria.getOperator()); assertEquals("Stockholm", criteria.getFirstOperant()); assertNull(criteria.getSecondOperant()); } @Test public void shouldBuildWithEqObjectProperty() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(primaryAddress()).eq( new Address("Kungsgatan 10", "Stockholm")) .buildSingle(); assertEquals("primaryAddress", criteria.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Equal, criteria.getOperator()); assertNull(criteria.getSecondOperant()); } @Test public void shouldBuildSimpleBetweenCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).between(1234, 6789) .buildSingle(); assertEquals(ConditionalCriteria.Operator.Between, criteria.getOperator()); assertEquals(1234, criteria.getFirstOperant()); assertEquals(6789, criteria.getSecondOperant()); } @Test public void shouldBuildLessThanCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).lessThan(1234).buildSingle(); assertEquals(ConditionalCriteria.Operator.LessThan, criteria.getOperator()); assertEquals(1234, criteria.getFirstOperant()); } @Test public void shouldBuildLikeCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).like("A").buildSingle(); assertEquals(ConditionalCriteria.Operator.Like, criteria.getOperator()); assertEquals("A", criteria.getFirstOperant()); } @Test public void shouldBuildInCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).in("A", "B").buildSingle(); assertEquals(ConditionalCriteria.Operator.In, criteria.getOperator()); } @Test public void shouldBuildIsNullCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).isNull().buildSingle(); assertEquals(ConditionalCriteria.Operator.IsNull, criteria.getOperator()); } @Test public void shouldBuildEqualsPropertyCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(PersonProperties.aaa()).eq( PersonProperties.bbb()).buildSingle(); assertEquals("aaa", criteria.getPropertyName()); assertEquals(ConditionalCriteria.Operator.EqualProperty, criteria.getOperator()); assertEquals("bbb", criteria.getFirstOperant()); } @Test public void shouldBuildBetweenToCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).between(1234).to(6789) .buildSingle(); assertEquals(ConditionalCriteria.Operator.Between, criteria.getOperator()); assertEquals(1234, criteria.getFirstOperant()); assertEquals(6789, criteria.getSecondOperant()); } @Test public void shouldBuildAndCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).eq(1234).and().withProperty(bbb()) .eq("zzz") .buildSingle(); assertEquals(ConditionalCriteria.Operator.And, criteria.getOperator()); ConditionalCriteria firstOperant = (ConditionalCriteria) criteria.getFirstOperant(); ConditionalCriteria secondOperant = (ConditionalCriteria) criteria.getSecondOperant(); assertEquals("aaa", firstOperant.property.getName()); assertEquals("bbb", secondOperant.property.getName()); } @Test public void shouldBuildAndConditionWithoutAndKeyword() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).eq(1234).withProperty(bbb()).eq( "zzz") .buildSingle(); assertEquals(ConditionalCriteria.Operator.And, criteria.getOperator()); ConditionalCriteria firstOperant = (ConditionalCriteria) criteria.getFirstOperant(); ConditionalCriteria secondOperant = (ConditionalCriteria) criteria.getSecondOperant(); assertEquals("aaa", firstOperant.property.getName()); assertEquals("bbb", secondOperant.property.getName()); } @Test public void shouldBuildSingleListOfConditions() { ConditionalCriteria criteriaS = criteriaFor(Person.class).withProperty(aaa()).eq(1234).and().withProperty(bbb()) .eq("zzz") .and() .withProperty(ccc()).eq("xxx").buildSingle(); assertEquals(ConditionalCriteria.Operator.And, criteriaS.getOperator()); @SuppressWarnings("unchecked") List<ConditionalCriteria> criteria=(List<ConditionalCriteria>) criteriaS.getFirstOperant(); ConditionalCriteria first=(ConditionalCriteria) criteria.get(0); ConditionalCriteria second=(ConditionalCriteria) criteria.get(1); ConditionalCriteria third=(ConditionalCriteria) criteria.get(2); assertEquals("aaa", first.property.getName()); assertEquals("bbb", second.property.getName()); assertEquals("ccc", third.property.getName()); } @Test public void shouldBuildListOfConditions() { List<ConditionalCriteria> criteria = criteriaFor(Person.class) .withProperty(aaa()).eq(1234) .and().withProperty(bbb()).eq("zzz") .and().withProperty(ccc()).eq("xxx") .build(); ConditionalCriteria first=(ConditionalCriteria) criteria.get(0); ConditionalCriteria second=(ConditionalCriteria) criteria.get(1); ConditionalCriteria third=(ConditionalCriteria) criteria.get(2); assertEquals("aaa", first.property.getName()); assertEquals("bbb", second.property.getName()); assertEquals("ccc", third.property.getName()); } @Test public void shouldBuildOrCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).eq(1234).or().withProperty(bbb()) .eq("zzz") .buildSingle(); assertNull(criteria.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Or, criteria.getOperator()); ConditionalCriteria left = (ConditionalCriteria) criteria.getFirstOperant(); assertEquals("aaa", left.property.getName()); ConditionalCriteria right = (ConditionalCriteria) criteria.getSecondOperant(); assertEquals("bbb", right.property.getName()); } @Test public void shouldBuildNotCondition() { ConditionalCriteria criteria = criteriaFor(Person.class).not().withProperty(aaa()).eq(1234).buildSingle(); assertNull(criteria.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Not, criteria.getOperator()); ConditionalCriteria op = (ConditionalCriteria) criteria.getFirstOperant(); assertEquals("aaa", op.property.getName()); } @Test public void shouldBuildOrderByAsc() { ConditionalCriteria criteria = criteriaFor(Person.class).orderBy(ccc()).ascending().buildSingle(); assertEquals(ConditionalCriteria.Operator.OrderAsc, criteria.getOperator()); assertEquals("ccc", criteria.getPropertyName()); } @Test public void shouldBuildOrderByDesc() { ConditionalCriteria criteria = criteriaFor(Person.class).orderBy(ccc()).descending().buildSingle(); assertEquals(ConditionalCriteria.Operator.OrderDesc, criteria.getOperator()); assertEquals("ccc", criteria.getPropertyName()); } @Test public void shouldBuildEqualsWithOrderBy() { List<ConditionalCriteria> criteriaList = criteriaFor(Person.class) .withProperty(aaa()).eq(1234) .withProperty(bbb()).eq("qqq") .orderBy(ccc()).ascending() .build(); assertEquals(3, criteriaList.size()); ConditionalCriteria criteria1 = criteriaList.get(0); assertEquals("aaa", criteria1.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Equal, criteria1.getOperator()); assertEquals(1234, criteria1.getFirstOperant()); assertNull(criteria1.getSecondOperant()); ConditionalCriteria criteria2 = criteriaList.get(1); assertEquals("bbb", criteria2.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Equal, criteria2.getOperator()); assertEquals("qqq", criteria2.getFirstOperant()); assertNull(criteria2.getSecondOperant()); ConditionalCriteria criteria3 = criteriaList.get(2); assertEquals(ConditionalCriteria.Operator.OrderAsc, criteria3.getOperator()); assertEquals("ccc", criteria3.getPropertyName()); } @Test public void shouldBuildEqualsConditionWithBraces() { ConditionalCriteria criteria = criteriaFor(Person.class).lbrace().withProperty(aaa()).eq(1234).rbrace() .buildSingle(); assertEquals("aaa", criteria.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Equal, criteria.getOperator()); assertEquals(1234, criteria.getFirstOperant()); assertNull(criteria.getSecondOperant()); } @Test public void shouldBuildOrConditionWithBraces() { ConditionalCriteria criteria = criteriaFor(Person.class).lbrace().withProperty(aaa()).eq(1234).or() .withProperty(bbb()).eq("zzz").rbrace() .buildSingle(); assertNull(criteria.getPropertyName()); assertEquals(ConditionalCriteria.Operator.Or, criteria.getOperator()); ConditionalCriteria left = (ConditionalCriteria) criteria.getFirstOperant(); assertEquals("aaa", left.property.getName()); ConditionalCriteria right = (ConditionalCriteria) criteria.getSecondOperant(); assertEquals("bbb", right.property.getName()); } @Test public void shouldBuildEmptyBraces() { ConditionalCriteria criteria = criteriaFor(Person.class).lbrace().rbrace().buildSingle(); assertNull(criteria); } @Test public void shouldBuildMultipleEmptyBraces() { ConditionalCriteria criteria = criteriaFor(Person.class).lbrace().lbrace().lbrace().rbrace().rbrace() .rbrace().buildSingle(); assertNull(criteria); } /** * A and B or C * <pre> * or * / \ * and C * / \ * A B * * </pre> */ @Test public void shouldBuildUngroupedAndOr() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).eq("A").and().withProperty(bbb()) .eq("B") .or() .withProperty(ccc()).eq("C") .buildSingle(); assertEquals(ConditionalCriteria.Operator.Or, criteria.getOperator()); ConditionalCriteria left1 = (ConditionalCriteria) criteria.getFirstOperant(); assertEquals(ConditionalCriteria.Operator.And, left1.getOperator()); ConditionalCriteria right1 = (ConditionalCriteria) criteria.getSecondOperant(); assertEquals(ConditionalCriteria.Operator.Equal, right1.getOperator()); assertEquals("ccc", right1.property.getName()); assertEquals("C", right1.getFirstOperant()); } /** * A and !B or C * * <pre> * or * / \ * and C * / \ * A not * | * B * * </pre> */ @Test public void shouldBuildUngroupedNotAndOr() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).eq("A").and().not().withProperty( bbb()).eq("B").or().withProperty(ccc()).eq("C").buildSingle(); assertEquals(ConditionalCriteria.Operator.Or, criteria.getOperator()); ConditionalCriteria left1 = (ConditionalCriteria) criteria.getFirstOperant(); assertEquals(ConditionalCriteria.Operator.And, left1.getOperator()); ConditionalCriteria notCriteria = ((ConditionalCriteria) left1.getSecondOperant()); assertEquals(ConditionalCriteria.Operator.Not, notCriteria.getOperator()); ConditionalCriteria firstOper=(ConditionalCriteria) notCriteria.getFirstOperant(); assertEquals("bbb", firstOper.property.getName()); ConditionalCriteria right1 = (ConditionalCriteria) criteria.getSecondOperant(); assertEquals(ConditionalCriteria.Operator.Equal, right1.getOperator()); assertEquals("ccc", right1.getPropertyName()); assertEquals("C", right1.getFirstOperant()); } /** * !(A and B) or C * * <pre> * or * / \ * not C * | * and * / \ * A B * * </pre> */ @Test public void shouldBuildGroupedNotAndOr() { ConditionalCriteria criteria = criteriaFor(Person.class).not().lbrace().withProperty(aaa()).eq("A").and() .withProperty(bbb()).eq("B").rbrace().or().withProperty(ccc()).eq("C").buildSingle(); assertEquals(ConditionalCriteria.Operator.Or, criteria.getOperator()); ConditionalCriteria left1 = (ConditionalCriteria) criteria.getFirstOperant(); assertEquals(ConditionalCriteria.Operator.Not, left1.getOperator()); ConditionalCriteria andCriteria = ((ConditionalCriteria) left1.getFirstOperant()); assertEquals(ConditionalCriteria.Operator.And, andCriteria.getOperator()); assertEquals("aaa", ((ConditionalCriteria) andCriteria.getFirstOperant()).getPropertyName()); assertEquals("bbb", ((ConditionalCriteria) andCriteria.getSecondOperant()).getPropertyName()); ConditionalCriteria right1 = (ConditionalCriteria) criteria.getSecondOperant(); assertEquals(ConditionalCriteria.Operator.Equal, right1.getOperator()); assertEquals("ccc", right1.getPropertyName()); assertEquals("C", right1.getFirstOperant()); } /** * A and (B or C) * <pre> * and * / \ * A or * / \ * B C * * </pre> */ @Test public void shouldBuildGroupedAndOr1() { ConditionalCriteria criteria = criteriaFor(Person.class).withProperty(aaa()).eq("A").and().lbrace() .withProperty(bbb()).eq("B").or().withProperty(ccc()).eq("C").rbrace() .buildSingle(); assertEquals(ConditionalCriteria.Operator.And, criteria.getOperator()); ConditionalCriteria left1 = (ConditionalCriteria) criteria.getFirstOperant(); assertEquals(ConditionalCriteria.Operator.Equal, left1.getOperator()); assertEquals("aaa", left1.getPropertyName()); assertEquals("A", left1.getFirstOperant()); ConditionalCriteria right1 = (ConditionalCriteria) criteria.getSecondOperant(); assertEquals(ConditionalCriteria.Operator.Or, right1.getOperator()); } /** * (A and B) or (C and D) * <pre> * or * / \ * and and * / \ / \ * A B C D * * </pre> */ @Test public void shouldBuildGroupedAndOr2() { ConditionalCriteria criteria = criteriaFor(Person.class).lbrace().withProperty(aaa()).eq("A").and() .withProperty(bbb()).eq("B").rbrace() .or() .lbrace().withProperty(ccc()).eq("C").and().withProperty( ddd()).eq("D").rbrace() .buildSingle(); assertEquals(ConditionalCriteria.Operator.Or, criteria.getOperator()); ConditionalCriteria leftAnd = (ConditionalCriteria) criteria.getFirstOperant(); assertEquals(ConditionalCriteria.Operator.And, leftAnd.getOperator()); ConditionalCriteria rightAnd = (ConditionalCriteria) criteria.getSecondOperant(); assertEquals(ConditionalCriteria.Operator.And, rightAnd.getOperator()); assertEquals(ConditionalCriteria.Operator.Equal, ((ConditionalCriteria) leftAnd.getFirstOperant()) .getOperator()); assertEquals(ConditionalCriteria.Operator.Equal, ((ConditionalCriteria) leftAnd.getSecondOperant()) .getOperator()); assertEquals("aaa", ((ConditionalCriteria) leftAnd.getFirstOperant()).getPropertyName()); assertEquals("bbb", ((ConditionalCriteria) leftAnd.getSecondOperant()).getPropertyName()); assertEquals(ConditionalCriteria.Operator.Equal, ((ConditionalCriteria) rightAnd.getFirstOperant()) .getOperator()); assertEquals(ConditionalCriteria.Operator.Equal, ((ConditionalCriteria) rightAnd.getSecondOperant()) .getOperator()); assertEquals("ccc", ((ConditionalCriteria) rightAnd.getFirstOperant()).getPropertyName()); assertEquals("ddd", ((ConditionalCriteria) rightAnd.getSecondOperant()).getPropertyName()); } @Test(expected = IllegalStateException.class) public void shouldDetectTooManyLeftBraces() { criteriaFor(Person.class).lbrace().withProperty(aaa()).eq("A").buildSingle(); } @Test(expected = IllegalStateException.class) public void shouldDetectTooManyRightBraces() { criteriaFor(Person.class).lbrace().withProperty(aaa()).eq("A").rbrace().rbrace().buildSingle(); } // Entity public static class Person { private String aaa; private String bbb; private int ccc; private Long ddd; private Address primaryAddress; private Address secondaryAddress; public String getAaa() { return aaa; } public void setAaa(String aaa) { this.aaa = aaa; } public String getBbb() { return bbb; } public void setBbb(String bbb) { this.bbb = bbb; } public int getCcc() { return ccc; } public void setCcc(int ccc) { this.ccc = ccc; } public Long getDdd() { return ddd; } public void setDdd(Long ddd) { this.ddd = ddd; } public Address getPrimaryAddress() { return primaryAddress; } public void setPrimaryAddress(Address primaryAddress) { this.primaryAddress = primaryAddress; } public Address getSecondaryAddress() { return secondaryAddress; } public void setSecondaryAddress(Address secondaryAddress) { this.secondaryAddress = secondaryAddress; } } // this class is the starting point, i.e. root of the criteria // note that it doesn't implements Property public static class PersonProperties { private static final PersonPropertiesImpl<Person> sharedInstance = new PersonPropertiesImpl<Person>(Person.class); private PersonProperties() { } public static Property<Person> aaa() { return sharedInstance.aaa(); } public static Property<Person> bbb() { return sharedInstance.bbb(); } public static Property<Person> ccc() { return sharedInstance.ccc(); } public static Property<Person> ddd() { return sharedInstance.ddd(); } public static AddressProperty<Person> primaryAddress() { return sharedInstance.primaryAddress(); } public static AddressProperty<Person> secondaryAddress() { return sharedInstance.secondaryAddress(); } public static PersonProperty<Person> boss() { return sharedInstance.boss(); } } // this class is used for references to Person, i.e. nested property public static class PersonProperty<T> extends PersonPropertiesImpl<T> implements Property<T> { private static final long serialVersionUID = 1L; public PersonProperty(String parentPath, String additionalPath, Class<T> owningClass) { super(parentPath, additionalPath, owningClass); } } // note private visibility private static class PersonPropertiesImpl<T> extends PropertiesCollection { private static final long serialVersionUID = 1L; Class<T> owningClass; PersonPropertiesImpl(Class<T> owningClass) { super(null); this.owningClass=owningClass; } PersonPropertiesImpl(String parentPath, String additionalPath, Class<T> owningClass) { super(parentPath, additionalPath); this.owningClass=owningClass; } public Property<T> aaa() { return new LeafProperty<T>(getParentPath(), "aaa", false, owningClass); } public Property<T> bbb() { return new LeafProperty<T>(getParentPath(), "bbb", false, owningClass); } public Property<T> ccc() { return new LeafProperty<T>(getParentPath(), "ccc", false, owningClass); } public Property<T> ddd() { return new LeafProperty<T>(getParentPath(), "ddd", false, owningClass); } public AddressProperty<T> primaryAddress() { return new AddressProperty<T>(getParentPath(), "primaryAddress", owningClass); } public AddressProperty<T> secondaryAddress() { return new AddressProperty<T>(getParentPath(), "secondaryAddress", owningClass); } public PersonProperty<T> boss() { return new PersonProperty<T>(getParentPath(), "boss", owningClass); } } // BasicType public static class Address { private final String street; private final String city; public Address(String street, String city) { this.street = street; this.city = city; } public String getStreet() { return street; } public String getCity() { return city; } } public static class AddressProperties { // note that static methods are not generated in BasicType, since they can't be root of the criteria public static class AddressProperty<T> extends AddressPropertiesImpl<T> implements Property<T> { private static final long serialVersionUID = 1L; public AddressProperty(String parentPath, String additionalPath, Class<T> owningClass) { super(parentPath, additionalPath, owningClass); } } private static class AddressPropertiesImpl<T> extends PropertiesCollection { private static final long serialVersionUID = 1L; Class<T> owningClass; AddressPropertiesImpl(String parentPath, Class<T> owningClass) { super(parentPath); this.owningClass=owningClass; } AddressPropertiesImpl(String parentPath, String additionalPath, Class<T> owningClass) { super(parentPath, additionalPath); this.owningClass=owningClass; } public Property<T> city() { return new LeafProperty<T>(getParentPath(), "city", true, owningClass); } } } }