cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ntimof...@apache.org
Subject [1/6] cayenne git commit: CAY-2467 New type-aware Property API core API
Date Wed, 26 Dec 2018 12:19:05 GMT
Repository: cayenne
Updated Branches:
  refs/heads/master bf7dba998 -> 9ea878c02


http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
index 66c947d..13c6761 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQueryMetadata.java
@@ -31,9 +31,9 @@ import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.access.types.ValueObjectType;
 import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
+import org.apache.cayenne.exp.property.BaseProperty;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.exp.TraversalHandler;
 import org.apache.cayenne.exp.parser.ASTDbPath;
 import org.apache.cayenne.exp.parser.ASTFunctionCall;
@@ -108,7 +108,7 @@ class SelectQueryMetadata extends BaseQueryMetadata {
 
 		if(query.getColumns() != null && !query.getColumns().isEmpty()) {
 			traversalHandler = new ToCacheKeyTraversalHandler(resolver.getValueObjectTypeRegistry(), key);
-			for(Property<?> property : query.getColumns()) {
+			for(BaseProperty<?> property : query.getColumns()) {
 				key.append("/c:");
 				property.getExpression().traverse(traversalHandler);
 			}
@@ -220,7 +220,7 @@ class SelectQueryMetadata extends BaseQueryMetadata {
 		}
 		
 		SQLResult result = new SQLResult();
-		for(Property<?> column : query.getColumns()) {
+		for(BaseProperty<?> column : query.getColumns()) {
 			Expression exp = column.getExpression();
 			String name = column.getName() == null ? exp.expName() : column.getName();
 			boolean fullObject = false;
@@ -260,7 +260,7 @@ class SelectQueryMetadata extends BaseQueryMetadata {
 	 * @param resolver entity resolver
 	 * @return Entity result
 	 */
-	private EntityResult buildEntityIdResultForColumn(Property<?> column, EntityResolver resolver) {
+	private EntityResult buildEntityIdResultForColumn(BaseProperty<?> column, EntityResolver resolver) {
 		EntityResult result = new EntityResult(column.getType());
 		DbEntity entity = resolver.getObjEntity(column.getType()).getDbEntity();
 		for(DbAttribute attribute : entity.getPrimaryKeys()) {
@@ -293,7 +293,7 @@ class SelectQueryMetadata extends BaseQueryMetadata {
 	 * @param resolver entity resolver to get ObjEntity and ClassDescriptor
 	 * @return Entity result
 	 */
-	private EntityResult buildEntityResultForColumn(SelectQuery<?> query, Property<?> column, EntityResolver resolver) {
+	private EntityResult buildEntityResultForColumn(SelectQuery<?> query, BaseProperty<?> column, EntityResolver resolver) {
 		final EntityResult result = new EntityResult(column.getType());
 
 		// Collecting visitor for ObjAttributes and toOne relationships

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionTest.java
index 2d62312..707144e 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionTest.java
@@ -144,7 +144,7 @@ public class ExpressionTest {
 	public void testIsNotNullEx() {
 		Expression e = Artist.ARTIST_NAME.isNotNull();
 		String ejbql = e.toEJBQL("x");
-		assertEquals("not (x.artistName is null)", ejbql);
+		assertEquals("x.artistName is not null", ejbql);
 	}
 
 	@Test

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/FunctionExpressionFactoryTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/FunctionExpressionFactoryTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/FunctionExpressionFactoryTest.java
index 7a9859c..78f8d72 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/FunctionExpressionFactoryTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/FunctionExpressionFactoryTest.java
@@ -53,14 +53,14 @@ public class FunctionExpressionFactoryTest {
 
     @Test
     public void substringExp() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.substringExp(Artist.ARTIST_NAME.path(), 10, 15);
+        Expression exp1 = FunctionExpressionFactory.substringExp(Artist.ARTIST_NAME.getExpression(), 10, 15);
         Expression exp2 = FunctionExpressionFactory.substringExp(Artist.ARTIST_NAME.getName(), 10, 15);
-        Expression exp3 = FunctionExpressionFactory.substringExp(Artist.ARTIST_NAME.path(), new ASTScalar(10), new ASTScalar(15));
+        Expression exp3 = FunctionExpressionFactory.substringExp(Artist.ARTIST_NAME.getExpression(), new ASTScalar(10), new ASTScalar(15));
 
         assertTrue(exp1 instanceof ASTSubstring);
 
         assertEquals(3, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
         assertEquals(10, exp1.getOperand(1));
         assertEquals(15, exp1.getOperand(2));
 
@@ -70,52 +70,52 @@ public class FunctionExpressionFactoryTest {
 
     @Test
     public void trimExp() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.trimExp(Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.trimExp(Artist.ARTIST_NAME.getExpression());
         Expression exp2 = FunctionExpressionFactory.trimExp(Artist.ARTIST_NAME.getName());
 
         assertTrue(exp1 instanceof ASTTrim);
 
         assertEquals(1, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
 
         assertEquals(exp1, exp2);
     }
 
     @Test
     public void lowerExp() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.lowerExp(Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.lowerExp(Artist.ARTIST_NAME.getExpression());
         Expression exp2 = FunctionExpressionFactory.lowerExp(Artist.ARTIST_NAME.getName());
 
         assertTrue(exp1 instanceof ASTLower);
 
         assertEquals(1, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
 
         assertEquals(exp1, exp2);
     }
 
     @Test
     public void upperExp() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.upperExp(Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.upperExp(Artist.ARTIST_NAME.getExpression());
         Expression exp2 = FunctionExpressionFactory.upperExp(Artist.ARTIST_NAME.getName());
 
         assertTrue(exp1 instanceof ASTUpper);
 
         assertEquals(1, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
 
         assertEquals(exp1, exp2);
     }
 
     @Test
     public void lengthExp() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.lengthExp(Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.lengthExp(Artist.ARTIST_NAME.getExpression());
         Expression exp2 = FunctionExpressionFactory.lengthExp(Artist.ARTIST_NAME.getName());
 
         assertTrue(exp1 instanceof ASTLength);
 
         assertEquals(1, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
 
         assertEquals(exp1, exp2);
     }
@@ -123,15 +123,15 @@ public class FunctionExpressionFactoryTest {
 
     @Test
     public void locateExp() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.locateExp("abc", Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.locateExp("abc", Artist.ARTIST_NAME.getExpression());
         Expression exp2 = FunctionExpressionFactory.locateExp("abc", Artist.ARTIST_NAME.getName());
-        Expression exp3 = FunctionExpressionFactory.locateExp(new ASTScalar("abc"), Artist.ARTIST_NAME.path());
+        Expression exp3 = FunctionExpressionFactory.locateExp(new ASTScalar("abc"), Artist.ARTIST_NAME.getExpression());
 
         assertTrue(exp1 instanceof ASTLocate);
 
         assertEquals(2, exp1.getOperandCount());
         assertEquals("abc", exp1.getOperand(0));
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(1));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(1));
 
         assertEquals(exp1, exp2);
         assertEquals(exp2, exp3);
@@ -140,26 +140,26 @@ public class FunctionExpressionFactoryTest {
 
     @Test
     public void absExp() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.absExp(Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.absExp(Artist.ARTIST_NAME.getExpression());
         Expression exp2 = FunctionExpressionFactory.absExp(Artist.ARTIST_NAME.getName());
 
         assertTrue(exp1 instanceof ASTAbs);
 
         assertEquals(1, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
 
         assertEquals(exp1, exp2);
     }
 
     @Test
     public void sqrtExp() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.sqrtExp(Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.sqrtExp(Artist.ARTIST_NAME.getExpression());
         Expression exp2 = FunctionExpressionFactory.sqrtExp(Artist.ARTIST_NAME.getName());
 
         assertTrue(exp1 instanceof ASTSqrt);
 
         assertEquals(1, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
 
         assertEquals(exp1, exp2);
     }
@@ -167,14 +167,14 @@ public class FunctionExpressionFactoryTest {
 
     @Test
     public void modExp() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.modExp(Artist.ARTIST_NAME.path(), 10);
+        Expression exp1 = FunctionExpressionFactory.modExp(Artist.ARTIST_NAME.getExpression(), 10);
         Expression exp2 = FunctionExpressionFactory.modExp(Artist.ARTIST_NAME.getName(), 10);
-        Expression exp3 = FunctionExpressionFactory.modExp(Artist.ARTIST_NAME.path(), new ASTScalar(10));
+        Expression exp3 = FunctionExpressionFactory.modExp(Artist.ARTIST_NAME.getExpression(), new ASTScalar(10));
 
         assertTrue(exp1 instanceof ASTMod);
 
         assertEquals(2, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
         assertEquals(10, exp1.getOperand(1));
 
         assertEquals(exp1, exp2);
@@ -184,22 +184,22 @@ public class FunctionExpressionFactoryTest {
 
     @Test
     public void concatExp() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.concatExp(Artist.ARTIST_NAME.path(), new ASTScalar("abc"), Artist.DATE_OF_BIRTH.path());
+        Expression exp1 = FunctionExpressionFactory.concatExp(Artist.ARTIST_NAME.getExpression(), new ASTScalar("abc"), Artist.DATE_OF_BIRTH.getExpression());
         assertTrue(exp1 instanceof ASTConcat);
         assertEquals(3, exp1.getOperandCount());
 
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
         assertEquals("abc", exp1.getOperand(1));
-        assertEquals(Artist.DATE_OF_BIRTH.path(), exp1.getOperand(2));
+        assertEquals(Artist.DATE_OF_BIRTH.getExpression(), exp1.getOperand(2));
 
 
         Expression exp2 = FunctionExpressionFactory.concatExp(Artist.ARTIST_NAME.getName(), Artist.DATE_OF_BIRTH.getName(), Artist.PAINTING_ARRAY.getName());
         assertTrue(exp2 instanceof ASTConcat);
         assertEquals(3, exp2.getOperandCount());
 
-        assertEquals(Artist.ARTIST_NAME.path(), exp2.getOperand(0));
-        assertEquals(Artist.DATE_OF_BIRTH.path(), exp2.getOperand(1));
-        assertEquals(Artist.PAINTING_ARRAY.path(), exp2.getOperand(2));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp2.getOperand(0));
+        assertEquals(Artist.DATE_OF_BIRTH.getExpression(), exp2.getOperand(1));
+        assertEquals(Artist.PAINTING_ARRAY.getExpression(), exp2.getOperand(2));
     }
 
     @Test
@@ -209,42 +209,42 @@ public class FunctionExpressionFactoryTest {
         assertEquals(1, exp1.getOperandCount());
         assertEquals(new ASTAsterisk(), exp1.getOperand(0));
 
-        Expression exp2 = FunctionExpressionFactory.countExp(Artist.ARTIST_NAME.path());
+        Expression exp2 = FunctionExpressionFactory.countExp(Artist.ARTIST_NAME.getExpression());
         assertTrue(exp2 instanceof ASTCount);
         assertEquals(1, exp2.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp2.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp2.getOperand(0));
     }
 
     @Test
     public void minTest() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.minExp(Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.minExp(Artist.ARTIST_NAME.getExpression());
         assertTrue(exp1 instanceof ASTMin);
         assertEquals(1, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
     }
 
     @Test
     public void maxTest() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.maxExp(Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.maxExp(Artist.ARTIST_NAME.getExpression());
         assertTrue(exp1 instanceof ASTMax);
         assertEquals(1, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
     }
 
     @Test
     public void avgTest() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.avgExp(Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.avgExp(Artist.ARTIST_NAME.getExpression());
         assertTrue(exp1 instanceof ASTAvg);
         assertEquals(1, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
     }
 
     @Test
     public void sumTest() throws Exception {
-        Expression exp1 = FunctionExpressionFactory.sumExp(Artist.ARTIST_NAME.path());
+        Expression exp1 = FunctionExpressionFactory.sumExp(Artist.ARTIST_NAME.getExpression());
         assertTrue(exp1 instanceof ASTSum);
         assertEquals(1, exp1.getOperandCount());
-        assertEquals(Artist.ARTIST_NAME.path(), exp1.getOperand(0));
+        assertEquals(Artist.ARTIST_NAME.getExpression(), exp1.getOperand(0));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
index 3630384..3850cb2 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
@@ -45,9 +45,11 @@ import org.apache.cayenne.exp.parser.ASTSum;
 import org.apache.cayenne.exp.parser.ASTTrim;
 import org.apache.cayenne.exp.parser.ASTUpper;
 import org.apache.cayenne.exp.parser.PatternMatchNode;
+import org.apache.cayenne.exp.property.NumericProperty;
 import org.apache.cayenne.reflect.TstJavaBean;
 import org.junit.Test;
 
+@Deprecated
 public class PropertyTest {
 
     @Test
@@ -344,7 +346,7 @@ public class PropertyTest {
     @Test
     public void testCount() {
         Property<String> p = Property.create("test", String.class);
-        Property<Long> newProp = p.count();
+        NumericProperty<Long> newProp = p.count();
         assertTrue(newProp.getExpression() instanceof ASTCount);
         assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
     }
@@ -352,7 +354,7 @@ public class PropertyTest {
     @Test
     public void testCountDistinct() {
         Property<String> p = Property.create("test", String.class);
-        Property<Long> newProp = p.countDistinct();
+        NumericProperty<Long> newProp = p.countDistinct();
         assertTrue(newProp.getExpression() instanceof ASTCount);
         assertTrue(newProp.getExpression().getOperand(0) instanceof ASTDistinct);
         assertEquals(p.getExpression(), ((ASTDistinct)newProp.getExpression().getOperand(0)).getOperand(0));

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/property/BasePropertyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/BasePropertyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/BasePropertyTest.java
new file mode 100644
index 0000000..745d867
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/BasePropertyTest.java
@@ -0,0 +1,268 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.exp.property;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.exp.parser.ASTLike;
+import org.apache.cayenne.exp.parser.ASTObjPath;
+import org.apache.cayenne.reflect.TstJavaBean;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.2
+ */
+public class BasePropertyTest {
+
+    private BaseProperty<Integer> property;
+
+    @Before
+    public void createProperty() {
+        property = new BaseProperty<>("path", null, Integer.class);
+    }
+
+
+    @Test
+    public void testPathExpConstructor() {
+        assertEquals(new ASTObjPath("path"), property.getExpression());
+    }
+
+    @Test
+    public void testCustomExpConstructor() {
+        property = new BaseProperty<>("path", new ASTLike(), Integer.class);
+        assertEquals(new ASTLike(), property.getExpression());
+    }
+
+    @Test
+    public void testEq() {
+        Expression exp = property.eq(1);
+        assertEquals(ExpressionFactory.exp("path = 1"), exp);
+    }
+
+    @Test
+    public void testNe() {
+        Expression exp = property.ne(1);
+        assertEquals(ExpressionFactory.exp("path != 1"), exp);
+    }
+
+    @Test
+    public void testIn() {
+        Expression exp = property.in(1, 2, 3);
+        assertEquals(ExpressionFactory.exp("path in (1, 2, 3)"), exp);
+    }
+
+    @Test
+    public void testInCollection() {
+        Expression exp = property.in(Arrays.asList(1,2,3));
+        assertEquals(ExpressionFactory.exp("path in (1, 2, 3)"), exp);
+    }
+
+    @Test
+    public void testNin() {
+        Expression exp = property.nin(1, 2, 3);
+        assertEquals(ExpressionFactory.exp("path not in (1, 2, 3)"), exp);
+    }
+
+    @Test
+    public void testNinCollection() {
+        Expression exp = property.nin(Arrays.asList(1,2,3));
+        assertEquals(ExpressionFactory.exp("path not in (1, 2, 3)"), exp);
+    }
+
+    @Test
+    public void testIsNull() {
+        BaseProperty<Integer> property = new BaseProperty<>("path", null, Integer.class);
+        Expression exp = property.isNull();
+        assertEquals(ExpressionFactory.exp("path = null"), exp);
+    }
+
+    @Test
+    public void testNotIsNull() {
+        Expression exp = property.isNotNull();
+        assertEquals(ExpressionFactory.exp("path != null"), exp);
+    }
+
+    @Test
+    public void testIsTrue() {
+        Expression exp = property.isTrue();
+        assertEquals(ExpressionFactory.exp("path = true"), exp);
+    }
+
+    @Test
+    public void testIsFalse() {
+        Expression exp = property.isFalse();
+        assertEquals(ExpressionFactory.exp("path = false"), exp);
+    }
+
+    @Test
+    public void testAlias() {
+        assertEquals("path", property.getName());
+        assertNull(property.getAlias());
+
+        property = property.alias("test");
+
+        assertEquals("test", property.getName());
+        assertEquals("test", property.getAlias());
+        assertEquals(new ASTObjPath("path"), property.getExpression());
+    }
+
+    @Test
+    public void testGetFrom() {
+        TstJavaBean bean = new TstJavaBean();
+        bean.setIntField(7);
+        BaseProperty<Integer> INT_FIELD = new BaseProperty<>("intField", null, Integer.class);
+        assertEquals(Integer.valueOf(7), INT_FIELD.getFrom(bean));
+    }
+
+    @Test
+    public void testGetFromNestedProperty() {
+        TstJavaBean bean = new TstJavaBean();
+        TstJavaBean nestedBean = new TstJavaBean();
+        nestedBean.setIntField(7);
+        bean.setObjectField(nestedBean);
+        BaseProperty<Integer> OBJECT_FIELD_INT_FIELD = new BaseProperty<>("objectField.intField", null, Integer.class);
+        assertEquals(Integer.valueOf(7), OBJECT_FIELD_INT_FIELD.getFrom(bean));
+    }
+
+    @Test
+    public void testGetFromNestedNull() {
+        TstJavaBean bean = new TstJavaBean();
+        bean.setObjectField(null);
+        BaseProperty<Integer> OBJECT_FIELD_INT_FIELD = new BaseProperty<>("objectField.intField", null, Integer.class);
+        assertNull(OBJECT_FIELD_INT_FIELD.getFrom(bean));
+    }
+
+    @Test
+    public void testGetFromAll() {
+        TstJavaBean bean = new TstJavaBean();
+        bean.setIntField(7);
+
+        TstJavaBean bean2 = new TstJavaBean();
+        bean2.setIntField(8);
+
+        List<TstJavaBean> beans = Arrays.asList(bean, bean2);
+
+        BaseProperty<Integer> INT_FIELD = new BaseProperty<>("intField", null, Integer.class);
+        assertEquals(Arrays.asList(7, 8), INT_FIELD.getFromAll(beans));
+    }
+
+    @Test
+    public void testSetIn() {
+        TstJavaBean bean = new TstJavaBean();
+        BaseProperty<Integer> INT_FIELD = new BaseProperty<>("intField", null, Integer.class);
+        INT_FIELD.setIn(bean, 7);
+        assertEquals(7, bean.getIntField());
+    }
+
+    @Test
+    public void testSetInNestedProperty() {
+        TstJavaBean bean = new TstJavaBean();
+        bean.setObjectField(new TstJavaBean());
+
+        BaseProperty<Integer> OBJECT_FIELD_INT_FIELD = new BaseProperty<>("objectField.intField", null, Integer.class);
+
+        OBJECT_FIELD_INT_FIELD.setIn(bean, 7);
+        assertEquals(7, ((TstJavaBean) bean.getObjectField()).getIntField());
+    }
+
+    @Test
+    public void testSetInNestedNull() {
+        TstJavaBean bean = new TstJavaBean();
+        bean.setObjectField(null);
+        BaseProperty<Integer> OBJECT_FIELD_INT_FIELD = new BaseProperty<>("objectField.intField", null, Integer.class);
+        OBJECT_FIELD_INT_FIELD.setIn(bean, 7);
+    }
+
+    @Test
+    public void testSetInAll() {
+        TstJavaBean bean = new TstJavaBean();
+        TstJavaBean bean2 = new TstJavaBean();
+        List<TstJavaBean> beans = Arrays.asList(bean, bean2);
+
+        BaseProperty<Integer> INT_FIELD = new BaseProperty<>("intField", null, Integer.class);
+        INT_FIELD.setInAll(beans, 7);
+        assertEquals(7, bean.getIntField());
+        assertEquals(7, bean2.getIntField());
+    }
+
+    @Test
+    public void testEqualsWithName() {
+        BaseProperty<Integer> INT_FIELD = new BaseProperty<>("intField", null, Integer.class);
+        BaseProperty<Integer> INT_FIELD2 = new BaseProperty<>("intField", null, Integer.class);
+
+        assertNotSame(INT_FIELD, INT_FIELD2);
+        assertEquals(INT_FIELD, INT_FIELD2);
+    }
+
+    @Test
+    public void testHashCodeWithName() {
+        BaseProperty<Integer> INT_FIELD = new BaseProperty<>("intField", null, Integer.class);
+        BaseProperty<Integer> INT_FIELD2 = new BaseProperty<>("intField", null, Integer.class);
+        BaseProperty<Long> LONG_FIELD = new BaseProperty<>("longField", null, Long.class);
+
+        assertEquals(INT_FIELD.hashCode(), INT_FIELD2.hashCode());
+        assertNotSame(INT_FIELD.hashCode(), LONG_FIELD.hashCode());
+    }
+
+    @Test
+    public void testEqualsWithNameAndType() {
+        BaseProperty<Integer> INT_FIELD = new BaseProperty<>("intField", null, Integer.class);
+        BaseProperty<Integer> INT_FIELD2 = new BaseProperty<>("intField", null, Integer.class);
+
+        assertNotSame(INT_FIELD, INT_FIELD2);
+        assertEquals(INT_FIELD, INT_FIELD2);
+    }
+
+    @Test
+    public void testHashCodeWithNameAndType() {
+        BaseProperty<Integer> INT_FIELD = new BaseProperty<>("intField", null, Integer.class);
+        BaseProperty<Integer> INT_FIELD2 = new BaseProperty<>("intField", null, Integer.class);
+        BaseProperty<Long> LONG_FIELD = new BaseProperty<>("longField", null, Long.class);
+
+        assertEquals(INT_FIELD.hashCode(), INT_FIELD2.hashCode());
+        assertNotEquals(INT_FIELD.hashCode(), LONG_FIELD.hashCode());
+    }
+
+    @Test
+    public void testEqualsWithExpAndType() {
+        BaseProperty<Integer> INT_FIELD = new BaseProperty<>(null, ExpressionFactory.exp("1"), Integer.class);
+        BaseProperty<Integer> INT_FIELD2 = new BaseProperty<>(null, ExpressionFactory.exp("1"), Integer.class);
+
+        assertNotSame(INT_FIELD, INT_FIELD2);
+        assertEquals(INT_FIELD, INT_FIELD2);
+    }
+
+    @Test
+    public void testHashCodeWithExpAndType() {
+        BaseProperty<Integer> INT_FIELD = new BaseProperty<>(null, ExpressionFactory.exp("1"), Integer.class);
+        BaseProperty<Integer> INT_FIELD2 = new BaseProperty<>(null, ExpressionFactory.exp("1"), Integer.class);
+        BaseProperty<Integer> INT_FIELD3 = new BaseProperty<>(null, ExpressionFactory.exp("2"), Integer.class);
+
+        assertEquals(INT_FIELD.hashCode(), INT_FIELD2.hashCode());
+        assertNotEquals(INT_FIELD.hashCode(), INT_FIELD3.hashCode());
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/property/DatePropertyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/DatePropertyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/DatePropertyTest.java
new file mode 100644
index 0000000..6463cdd
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/DatePropertyTest.java
@@ -0,0 +1,98 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.exp.property;
+
+import java.time.LocalDate;
+
+import org.apache.cayenne.exp.Expression;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.cayenne.exp.ExpressionFactory.exp;
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.2
+ */
+public class DatePropertyTest {
+
+    private DateProperty<LocalDate> property;
+
+    @Before
+    public void createProperty() {
+        property = new DateProperty<>("path", null, LocalDate.class);
+    }
+
+    @Test
+    public void year() {
+        Expression exp = property.year().getExpression();
+        assertEquals(exp("year(path)"), exp);
+    }
+
+    @Test
+    public void month() {
+        Expression exp = property.month().getExpression();
+        assertEquals(exp("month(path)"), exp);
+    }
+
+    @Test
+    public void dayOfMonth() {
+        Expression exp = property.dayOfMonth().getExpression();
+        assertEquals(exp("dayOfMonth(path)"), exp);
+    }
+
+    @Test
+    public void hour() {
+        Expression exp = property.hour().getExpression();
+        assertEquals(exp("hour(path)"), exp);
+    }
+
+    @Test
+    public void minute() {
+        Expression exp = property.minute().getExpression();
+        assertEquals(exp("minute(path)"), exp);
+    }
+
+    @Test
+    public void second() {
+        Expression exp = property.second().getExpression();
+        assertEquals(exp("second(path)"), exp);
+    }
+
+    @Test
+    public void max() {
+        Expression exp = property.max().getExpression();
+        assertEquals(exp("max(path)"), exp);
+    }
+
+    @Test
+    public void min() {
+        Expression exp = property.min().getExpression();
+        assertEquals(exp("min(path)"), exp);
+    }
+
+    @Test
+    public void alias() {
+        DateProperty<LocalDate> aliased = property.alias("test");
+        assertEquals("test", aliased.getAlias());
+        assertEquals("test", aliased.getName());
+        assertEquals(exp("path"), aliased.getExpression());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/property/EntityPropertyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/EntityPropertyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/EntityPropertyTest.java
new file mode 100644
index 0000000..8b9ba0e
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/EntityPropertyTest.java
@@ -0,0 +1,74 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.exp.property;
+
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.2
+ */
+public class EntityPropertyTest {
+
+    private EntityProperty<Artist> property;
+
+    @Before
+    public void createProperty() {
+        property = new EntityProperty<>("path", null, Artist.class);
+    }
+
+    @Test
+    public void alias() {
+        assertEquals("path", property.getName());
+        assertNull(property.getAlias());
+
+        property = property.alias("alias");
+
+        assertEquals("alias", property.getName());
+        assertEquals("alias", property.getAlias());
+    }
+
+    @Test
+    public void outer() {
+        assertEquals("path", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path"), property.getExpression());
+
+        property = property.outer();
+
+        assertEquals("path+", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path+"), property.getExpression());
+
+        property = property.outer();
+
+        assertEquals("path+", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path+"), property.getExpression());
+    }
+
+    @Test
+    public void dot() {
+        BaseProperty<?> other = property.dot("other");
+        assertEquals("path.other", other.getName());
+        assertEquals(ExpressionFactory.pathExp("path.other"), other.getExpression());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/property/ListPropertyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/ListPropertyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/ListPropertyTest.java
new file mode 100644
index 0000000..fb775af
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/ListPropertyTest.java
@@ -0,0 +1,101 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.exp.property;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.2
+ */
+public class ListPropertyTest {
+
+    private ListProperty<Artist> property;
+
+    @Before
+    public void createProperty() {
+        property = new ListProperty<>("path", null, Artist.class);
+    }
+
+
+    @Test
+    public void alias() {
+        assertEquals("path", property.getName());
+        assertNull(property.getAlias());
+
+        property = property.alias("alias");
+
+        assertEquals("alias", property.getName());
+        assertEquals("alias", property.getAlias());
+    }
+
+    @Test
+    public void outer() {
+        assertEquals("path", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path"), property.getExpression());
+
+        property = property.outer();
+
+        assertEquals("path+", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path+"), property.getExpression());
+
+        property = property.outer();
+
+        assertEquals("path+", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path+"), property.getExpression());
+    }
+
+    @Test
+    public void containsOne() {
+        Artist artist = new Artist();
+        Expression exp = property.contains(artist);
+        assertEquals(ExpressionFactory.matchExp("path", artist), exp);
+    }
+
+    @Test
+    public void containsMany() {
+        Collection<Artist> artists = Arrays.asList(new Artist(), new Artist());
+        Expression exp = property.contains(artists);
+        assertEquals(ExpressionFactory.inExp("path", artists), exp);
+    }
+
+    @Test
+    public void notContainsOne() {
+        Artist artist = new Artist();
+        Expression exp = property.notContains(artist);
+        assertEquals(ExpressionFactory.noMatchExp("path", artist), exp);
+    }
+
+    @Test
+    public void notContainsMany() {
+        Collection<Artist> artists = Arrays.asList(new Artist(), new Artist());
+        Expression exp = property.notContains(artists);
+        assertEquals(ExpressionFactory.notInExp("path", artists), exp);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/property/MapPropertyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/MapPropertyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/MapPropertyTest.java
new file mode 100644
index 0000000..bc4ee9e
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/MapPropertyTest.java
@@ -0,0 +1,158 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.exp.property;
+
+import java.util.Arrays;
+
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.2
+ */
+public class MapPropertyTest {
+
+    private MapProperty<Integer, Artist> property;
+
+    @Before
+    public void createProperty() {
+        property = new MapProperty<>("path", null, Integer.class, Artist.class);
+    }
+
+    @Test
+    public void flat() {
+        Expression exp = property.flat().getExpression();
+        assertEquals(ExpressionFactory.fullObjectExp(ExpressionFactory.pathExp("path")), exp);
+    }
+
+    @Test
+    public void containsOne() {
+        Artist artist = new Artist();
+        Expression exp = property.contains(artist);
+        assertEquals(ExpressionFactory.matchExp("path", artist), exp);
+    }
+
+    @Test
+    public void notContainsOne() {
+        Artist artist = new Artist();
+        Expression exp = property.notContains(artist);
+        assertEquals(ExpressionFactory.noMatchExp("path", artist), exp);
+    }
+
+    @Test
+    public void containsManyArray() {
+        Artist artist1 = new Artist();
+        Artist artist2 = new Artist();
+        Expression exp = property.contains(artist1, artist2);
+        assertEquals(ExpressionFactory.inExp("path", Arrays.asList(artist1, artist2)), exp);
+    }
+
+    @Test
+    public void containsManyCollection() {
+        Artist artist1 = new Artist();
+        Artist artist2 = new Artist();
+        Expression exp = property.contains(Arrays.asList(artist1, artist2));
+        assertEquals(ExpressionFactory.inExp("path", Arrays.asList(artist1, artist2)), exp);
+    }
+
+    @Test
+    public void notContainsManyArray() {
+        Artist artist1 = new Artist();
+        Artist artist2 = new Artist();
+        Expression exp = property.notContains(artist1, artist2);
+        assertEquals(ExpressionFactory.notInExp("path", Arrays.asList(artist1, artist2)), exp);
+    }
+
+    @Test
+    public void notContainsManyCollection() {
+        Artist artist1 = new Artist();
+        Artist artist2 = new Artist();
+        Expression exp = property.notContains(Arrays.asList(artist1, artist2));
+        assertEquals(ExpressionFactory.notInExp("path", Arrays.asList(artist1, artist2)), exp);
+    }
+
+    @Test
+    public void containsOneId() {
+        Expression exp = property.containsId(1);
+        assertEquals(ExpressionFactory.exp("path = 1"), exp);
+    }
+
+    @Test
+    public void containsManyIdArray() {
+        Expression exp = property.containsId(1, 2, 3);
+        assertEquals(ExpressionFactory.exp("path in (1,2,3)"), exp);
+    }
+
+    @Test
+    public void containsManyIdCollection() {
+        Expression exp = property.containsId(Arrays.asList(1, 2, 3));
+        assertEquals(ExpressionFactory.exp("path in (1,2,3)"), exp);
+    }
+
+    @Test
+    public void notContainsOneId() {
+        Expression exp = property.notContainsId(1);
+        assertEquals(ExpressionFactory.exp("path != 1"), exp);
+    }
+
+    @Test
+    public void notContainsManyIdArray() {
+        Expression exp = property.notContainsId(1, 2, 3);
+        assertEquals(ExpressionFactory.exp("path not in (1,2,3)"), exp);
+    }
+
+    @Test
+    public void notContainsManyIdCollection() {
+        Expression exp = property.notContainsId(Arrays.asList(1, 2, 3));
+        assertEquals(ExpressionFactory.exp("path not in (1,2,3)"), exp);
+    }
+
+    @Test
+    public void alias() {
+        assertEquals("path", property.getName());
+        assertNull(property.getAlias());
+
+        property = property.alias("alias");
+
+        assertEquals("alias", property.getName());
+        assertEquals("alias", property.getAlias());
+    }
+
+    @Test
+    public void outer() {
+        assertEquals("path", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path"), property.getExpression());
+
+        property = property.outer();
+
+        assertEquals("path+", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path+"), property.getExpression());
+
+        property = property.outer();
+
+        assertEquals("path+", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path+"), property.getExpression());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/property/NumericPropertyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/NumericPropertyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/NumericPropertyTest.java
new file mode 100644
index 0000000..0f78eaf
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/NumericPropertyTest.java
@@ -0,0 +1,247 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.exp.property;
+
+import java.util.Arrays;
+
+import org.apache.cayenne.exp.Expression;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.apache.cayenne.exp.ExpressionFactory.exp;
+
+/**
+ * @since 4.2
+ */
+public class NumericPropertyTest {
+
+    private NumericProperty<Integer> property;
+    private NumericProperty<Integer> other;
+
+    @Before
+    public void createProperty() {
+        property = new NumericProperty<>("path", null, Integer.class);
+        other = new NumericProperty<>("other", null, Integer.class);
+    }
+
+    @Test
+    public void avg() {
+        assertEquals(exp("avg(path)"), property.avg().getExpression());
+    }
+
+    @Test
+    public void min() {
+        assertEquals(exp("min(path)"), property.min().getExpression());
+    }
+
+    @Test
+    public void max() {
+        assertEquals(exp("max(path)"), property.max().getExpression());
+    }
+
+    @Test
+    public void sum() {
+        assertEquals(exp("sum(path)"), property.sum().getExpression());
+    }
+
+    @Test
+    public void count() {
+        assertEquals(exp("count(path)"), property.count().getExpression());
+    }
+
+    @Test
+    public void modNumber() {
+        assertEquals(exp("mod(path, 3)"), property.mod(3).getExpression());
+    }
+
+    @Test
+    public void modProp() {
+        assertEquals(exp("mod(path, other)"), property.mod(other).getExpression());
+    }
+
+    @Test
+    public void abs() {
+        assertEquals(exp("abs(path)"), property.abs().getExpression());
+    }
+
+    @Test
+    public void sqrt() {
+        assertEquals(exp("sqrt(path)"), property.sqrt().getExpression());
+    }
+
+    @Test
+    public void add() {
+        assertEquals(exp("path + 42"), property.add(42).getExpression());
+    }
+
+    @Test
+    public void addProp() {
+        assertEquals(exp("path + other"), property.add(other).getExpression());
+    }
+
+    @Test
+    public void sub() {
+        assertEquals(exp("path - 42"), property.sub(42).getExpression());
+    }
+
+    @Test
+    public void subProp() {
+        assertEquals(exp("path - other"), property.sub(other).getExpression());
+    }
+
+    @Test
+    public void div() {
+        assertEquals(exp("path / 42"), property.div(42).getExpression());
+    }
+
+    @Test
+    public void divProp() {
+        assertEquals(exp("path / other"), property.div(other).getExpression());
+    }
+
+    @Test
+    public void mul() {
+        assertEquals(exp("path * 42"), property.mul(42).getExpression());
+    }
+
+    @Test
+    public void mulProp() {
+        assertEquals(exp("path * other"), property.mul(other).getExpression());
+    }
+
+    @Test
+    public void neg() {
+        assertEquals(exp("- path"), property.neg().getExpression());
+    }
+
+    @Test
+    public void between() {
+        Expression exp1 = exp("path between 42 and 123");
+        Expression exp2 = property.between(42, 123);
+        assertEquals(exp1, exp2);
+    }
+
+    @Test
+    public void betweenProp() {
+        assertEquals(exp("path between -other and other"), property.between(other.neg(), other));
+    }
+
+    @Test
+    public void eq() {
+        assertEquals(exp("path = 123"), property.eq(123));
+    }
+
+    @Test
+    public void eqProp() {
+        assertEquals(exp("path = other"), property.eq(other));
+    }
+
+    @Test
+    public void ne() {
+        assertEquals(exp("path != 123"), property.ne(123));
+    }
+
+    @Test
+    public void neProp() {
+        assertEquals(exp("path != other"), property.ne(other));
+    }
+
+    @Test
+    public void inArray() {
+        assertEquals(exp("path in (1, 2, 3)"), property.in(1, 2, 3));
+    }
+
+    @Test
+    public void inCollection() {
+        assertEquals(exp("path in (1, 2, 3)"), property.in(Arrays.asList(1, 2, 3)));
+    }
+
+    @Test
+    public void ninArray() {
+        assertEquals(exp("path not in (1, 2, 3)"), property.nin(1, 2, 3));
+    }
+
+    @Test
+    public void ninCollection() {
+        assertEquals(exp("path not in (1, 2, 3)"), property.nin(Arrays.asList(1, 2, 3)));
+    }
+
+    @Test
+    public void gt() {
+        assertEquals(exp("path > 123"), property.gt(123));
+    }
+
+    @Test
+    public void gtProp() {
+        assertEquals(exp("path > other"), property.gt(other));
+    }
+
+    @Test
+    public void gte() {
+        assertEquals(exp("path >= 123"), property.gte(123));
+    }
+
+    @Test
+    public void gteProp() {
+        assertEquals(exp("path >= other"), property.gte(other));
+    }
+
+    @Test
+    public void lt() {
+        assertEquals(exp("path < 42"), property.lt(42));
+    }
+
+    @Test
+    public void ltProp() {
+        assertEquals(exp("path < other"), property.lt(other));
+    }
+
+    @Test
+    public void lte() {
+        assertEquals(exp("path <= 42"), property.lte(42));
+    }
+
+    @Test
+    public void lteProp() {
+        assertEquals(exp("path <= other"), property.lte(other));
+    }
+
+    @Test
+    public void isTrue() {
+        assertEquals(exp("path = true"), property.isTrue());
+    }
+
+    @Test
+    public void isFalse() {
+        assertEquals(exp("path = false"), property.isFalse());
+    }
+
+    @Test
+    public void alias() {
+        assertEquals("path", property.getName());
+        assertNull(property.getAlias());
+
+        property = property.alias("alias");
+
+        assertEquals("alias", property.getName());
+        assertEquals("alias", property.getAlias());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyFactoryTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyFactoryTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyFactoryTest.java
new file mode 100644
index 0000000..89a3553
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/PropertyFactoryTest.java
@@ -0,0 +1,275 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.exp.property;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.junit.Test;
+
+import static org.apache.cayenne.exp.ExpressionFactory.*;
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.2
+ */
+public class PropertyFactoryTest {
+
+    @Test
+    public void createBase() {
+        BaseProperty<Integer> property = PropertyFactory
+                .createBase("path", Integer.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path"), property.getExpression());
+        assertEquals(Integer.class, property.getType());
+    }
+
+    @Test
+    public void createBase1() {
+        BaseProperty<Boolean> property = PropertyFactory
+                .createBase("path", exp("path = 1"), Boolean.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path = 1"), property.getExpression());
+        assertEquals(Boolean.class, property.getType());
+    }
+
+    @Test
+    public void createBase2() {
+        BaseProperty<Boolean> property = PropertyFactory
+                .createBase(exp("path = 1"), Boolean.class);
+
+        assertNull(property.getName());
+        assertEquals(exp("path = 1"), property.getExpression());
+        assertEquals(Boolean.class, property.getType());
+    }
+
+    @Test
+    public void createString() {
+        StringProperty<String> property = PropertyFactory
+                .createString("path", String.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path"), property.getExpression());
+        assertEquals(String.class, property.getType());
+    }
+
+    @Test
+    public void createString1() {
+        StringProperty<String> property = PropertyFactory
+                .createString(exp("path"), String.class);
+
+        assertNull(property.getName());
+        assertEquals(exp("path"), property.getExpression());
+        assertEquals(String.class, property.getType());
+    }
+
+    @Test
+    public void createString2() {
+        StringProperty<StringBuilder> property = PropertyFactory
+                .createString("path", exp("concat(path, 'abc')"), StringBuilder.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("concat(path, 'abc')"), property.getExpression());
+        assertEquals(StringBuilder.class, property.getType());
+    }
+
+    @Test
+    public void createNumeric() {
+        NumericProperty<Integer> property = PropertyFactory
+                .createNumeric("path", Integer.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path"), property.getExpression());
+        assertEquals(Integer.class, property.getType());
+    }
+
+    @Test
+    public void createNumeric1() {
+        NumericProperty<Integer> property = PropertyFactory
+                .createNumeric(exp("path + 1"), Integer.class);
+
+        assertNull(property.getName());
+        assertEquals(exp("path + 1"), property.getExpression());
+        assertEquals(Integer.class, property.getType());
+    }
+
+    @Test
+    public void createNumeric2() {
+        NumericProperty<Double> property = PropertyFactory
+                .createNumeric("path", exp("path / 2"), Double.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path / 2"), property.getExpression());
+        assertEquals(Double.class, property.getType());
+    }
+
+    @Test
+    public void createDate() {
+        DateProperty<LocalDate> property = PropertyFactory
+                .createDate("path", LocalDate.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path"), property.getExpression());
+        assertEquals(LocalDate.class, property.getType());
+    }
+
+    @Test
+    public void createDate1() {
+        DateProperty<LocalDate> property = PropertyFactory
+                .createDate(exp("year(path)"), LocalDate.class);
+
+        assertNull(property.getName());
+        assertEquals(exp("year(path)"), property.getExpression());
+        assertEquals(LocalDate.class, property.getType());
+    }
+
+    @Test
+    public void createDate2() {
+        DateProperty<LocalDate> property = PropertyFactory
+                .createDate("path", exp("year(path)"), LocalDate.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("year(path)"), property.getExpression());
+        assertEquals(LocalDate.class, property.getType());
+    }
+
+    @Test
+    public void createEntity() {
+        EntityProperty<Artist> property = PropertyFactory
+                .createEntity("path", Artist.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path"), property.getExpression());
+        assertEquals(Artist.class, property.getType());
+    }
+
+    @Test
+    public void createEntity1() {
+        EntityProperty<Artist> property = PropertyFactory
+                .createEntity(exp("path+.subpath"), Artist.class);
+
+        assertNull(property.getName());
+        assertEquals(exp("path+.subpath"), property.getExpression());
+        assertEquals(Artist.class, property.getType());
+    }
+
+    @Test
+    public void createEntity2() {
+        EntityProperty<Artist> property = PropertyFactory
+                .createEntity("path", exp("path+.subpath"), Artist.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path+.subpath"), property.getExpression());
+        assertEquals(Artist.class, property.getType());
+    }
+
+    @Test
+    public void createSelf() {
+        EntityProperty<Artist> property = PropertyFactory
+                .createSelf(Artist.class);
+
+        assertNull(property.getName());
+        assertEquals(fullObjectExp(), property.getExpression());
+        assertEquals(Artist.class, property.getType());
+    }
+
+    @Test
+    public void createSelf1() {
+        EntityProperty<Artist> property = PropertyFactory
+                .createSelf(exp("path"), Artist.class);
+
+        assertNull(property.getName());
+        assertEquals(fullObjectExp(exp("path")), property.getExpression());
+        assertEquals(Artist.class, property.getType());
+    }
+
+    @Test
+    public void createList() {
+        ListProperty<Artist> property = PropertyFactory
+                .createList("path", Artist.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path"), property.getExpression());
+        assertEquals(List.class, property.getType());
+        assertEquals(Artist.class, property.getEntityType());
+    }
+
+    @Test
+    public void createList1() {
+        ListProperty<Artist> property = PropertyFactory
+                .createList("path", exp("path+.sub"), Artist.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path+.sub"), property.getExpression());
+        assertEquals(List.class, property.getType());
+        assertEquals(Artist.class, property.getEntityType());
+    }
+
+    @Test
+    public void createSet() {
+        SetProperty<Artist> property = PropertyFactory
+                .createSet("path", Artist.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path"), property.getExpression());
+        assertEquals(Set.class, property.getType());
+        assertEquals(Artist.class, property.getEntityType());
+    }
+
+    @Test
+    public void createSet1() {
+        SetProperty<Artist> property = PropertyFactory
+                .createSet("path", exp("path+.sub"), Artist.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path+.sub"), property.getExpression());
+        assertEquals(Set.class, property.getType());
+        assertEquals(Artist.class, property.getEntityType());
+    }
+
+    @Test
+    public void createMap() {
+        MapProperty<Integer, Artist> property = PropertyFactory
+                .createMap("path", Integer.class, Artist.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path"), property.getExpression());
+        assertEquals(Map.class, property.getType());
+        assertEquals(Integer.class, property.getKeyType());
+        assertEquals(Artist.class, property.getEntityType());
+    }
+
+    @Test
+    public void createMap1() {
+        MapProperty<Integer, Artist> property = PropertyFactory
+                .createMap("path", exp("path+.sub"), Integer.class, Artist.class);
+
+        assertEquals("path", property.getName());
+        assertEquals(exp("path+.sub"), property.getExpression());
+        assertEquals(Map.class, property.getType());
+        assertEquals(Integer.class, property.getKeyType());
+        assertEquals(Artist.class, property.getEntityType());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/property/SetPropertyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/SetPropertyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/SetPropertyTest.java
new file mode 100644
index 0000000..2cd258f
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/SetPropertyTest.java
@@ -0,0 +1,75 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.exp.property;
+
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.2
+ */
+public class SetPropertyTest {
+
+    private SetProperty<Artist> property;
+
+    @Before
+    public void createProperty() {
+        property = new SetProperty<>("path", null, Artist.class);
+    }
+
+    @Test
+    public void alias() {
+        assertEquals("path", property.getName());
+        assertNull(property.getAlias());
+
+        property = property.alias("alias");
+
+        assertEquals("alias", property.getName());
+        assertEquals("alias", property.getAlias());
+    }
+
+    @Test
+    public void outer() {
+        assertEquals("path", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path"), property.getExpression());
+
+        property = property.outer();
+
+        assertEquals("path+", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path+"), property.getExpression());
+
+        property = property.outer();
+
+        assertEquals("path+", property.getName());
+        assertEquals(ExpressionFactory.pathExp("path+"), property.getExpression());
+    }
+
+    @Test
+    public void containsOne() {
+        Artist artist = new Artist();
+        Expression exp = property.contains(artist);
+        assertEquals(ExpressionFactory.matchExp("path", artist), exp);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/2050c2e1/cayenne-server/src/test/java/org/apache/cayenne/exp/property/StringPropertyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/property/StringPropertyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/StringPropertyTest.java
new file mode 100644
index 0000000..a2b7388
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/property/StringPropertyTest.java
@@ -0,0 +1,176 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.exp.property;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.cayenne.exp.ExpressionFactory.exp;
+import static org.junit.Assert.*;
+
+/**
+ * @since 4.2
+ */
+public class StringPropertyTest {
+
+    private StringProperty<String> property;
+    private StringProperty<String> other;
+
+    @Before
+    public void createProperty() {
+        property = new StringProperty<>("path", null, String.class);
+        other = new StringProperty<>("other", null, String.class);
+    }
+
+    @Test
+    public void like() {
+        assertEquals(exp("path like 'abc'"), property.like("abc"));
+    }
+
+    @Test
+    public void likeProp() {
+        assertEquals(exp("path like other"), property.like(other));
+    }
+
+    @Test
+    public void likeWithEscape() {
+        assertEquals(exp("path like 'abc'"), property.like("abc", '|'));
+    }
+
+    @Test
+    public void likeIgnoreCase() {
+        assertEquals(exp("path likeIgnoreCase 'abc'"), property.likeIgnoreCase("abc"));
+    }
+
+    @Test
+    public void likeIgnoreCaseProp() {
+        assertEquals(exp("path likeIgnoreCase other"), property.likeIgnoreCase(other));
+    }
+
+    @Test
+    public void nlike() {
+        assertEquals(exp("path not like 'abc'"), property.nlike("abc"));
+    }
+
+    @Test
+    public void nlikeProp() {
+        assertEquals(exp("path not like other"), property.nlike(other));
+    }
+
+    @Test
+    public void nlikeIgnoreCase() {
+        assertEquals(exp("path not likeIgnoreCase 'abc'"), property.nlikeIgnoreCase("abc"));
+    }
+
+    @Test
+    public void nlikeIgnoreCaseProp() {
+        assertEquals(exp("path not likeIgnoreCase other"), property.nlikeIgnoreCase(other));
+    }
+
+    @Test
+    public void contains() {
+        assertEquals(exp("path like '%abc%'"), property.contains("abc"));
+    }
+
+    @Test
+    public void startsWith() {
+        assertEquals(exp("path like 'abc%'"), property.startsWith("abc"));
+    }
+
+    @Test
+    public void endsWith() {
+        assertEquals(exp("path like '%abc'"), property.endsWith("abc"));
+    }
+
+    @Test
+    public void containsIgnoreCase() {
+        assertEquals(exp("path likeIgnoreCase '%abc%'"), property.containsIgnoreCase("abc"));
+    }
+
+    @Test
+    public void startsWithIgnoreCase() {
+        assertEquals(exp("path likeIgnoreCase 'abc%'"), property.startsWithIgnoreCase("abc"));
+    }
+
+    @Test
+    public void endsWithIgnoreCase() {
+        assertEquals(exp("path likeIgnoreCase '%abc'"), property.endsWithIgnoreCase("abc"));
+    }
+
+    @Test
+    public void length() {
+        assertEquals(exp("length(path)"), property.length().getExpression());
+    }
+
+    @Test
+    public void locate() {
+        assertEquals(exp("locate('abc', path)"), property.locate("abc").getExpression());
+    }
+
+    @Test
+    public void locateProp() {
+        assertEquals(exp("locate(other, path)"), property.locate(other).getExpression());
+    }
+
+    @Test
+    public void trim() {
+        assertEquals(exp("trim(path)"), property.trim().getExpression());
+    }
+
+    @Test
+    public void upper() {
+        assertEquals(exp("upper(path)"), property.upper().getExpression());
+    }
+
+    @Test
+    public void lower() {
+        assertEquals(exp("lower(path)"), property.lower().getExpression());
+    }
+
+    @Test
+    public void concat() {
+        assertEquals(exp("concat(path, 'abc', ' ', 'def', other)"),
+                property.concat("abc", ' ', exp("'def'"), other).getExpression());
+    }
+
+    @Test
+    public void substring() {
+        assertEquals(exp("substring(path, 10, 30)"), property.substring(10, 30).getExpression());
+    }
+
+    @Test
+    public void substringProp() {
+        NumericProperty<Integer> offset = PropertyFactory.createNumeric("offset", Integer.class);
+        // length is a function name, so use len here
+        NumericProperty<Integer> length = PropertyFactory.createNumeric("len", Integer.class);
+        assertEquals(exp("substring(path, offset, len)"), property.substring(offset, length).getExpression());
+    }
+
+    @Test
+    public void alias() {
+        assertEquals("path", property.getName());
+        assertNull(property.getAlias());
+
+        property = property.alias("alias");
+
+        assertEquals("alias", property.getName());
+        assertEquals("alias", property.getAlias());
+    }
+}
\ No newline at end of file


Mime
View raw message