/*****************************************************************
* 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;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.List;
import org.apache.cayenne.exp.parser.ASTAbs;
import org.apache.cayenne.exp.parser.ASTAvg;
import org.apache.cayenne.exp.parser.ASTConcat;
import org.apache.cayenne.exp.parser.ASTCount;
import org.apache.cayenne.exp.parser.ASTLength;
import org.apache.cayenne.exp.parser.ASTLocate;
import org.apache.cayenne.exp.parser.ASTLower;
import org.apache.cayenne.exp.parser.ASTMax;
import org.apache.cayenne.exp.parser.ASTMin;
import org.apache.cayenne.exp.parser.ASTMod;
import org.apache.cayenne.exp.parser.ASTObjPath;
import org.apache.cayenne.exp.parser.ASTScalar;
import org.apache.cayenne.exp.parser.ASTSqrt;
import org.apache.cayenne.exp.parser.ASTSubstring;
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.reflect.TstJavaBean;
import org.junit.Test;
public class PropertyTest {
@Test
public void testPath() {
Property<String> p = Property.create("x.y", String.class);
Expression pp = p.path();
assertEquals(ExpressionFactory.exp("x.y"), pp);
}
@Test
public void testIn() {
Property<String> p = Property.create("x.y", String.class);
Expression e1 = p.in("a");
assertEquals("x.y in (\"a\")", e1.toString());
Expression e2 = p.in("a", "b");
assertEquals("x.y in (\"a\", \"b\")", e2.toString());
Expression e3 = p.in(Arrays.asList("a", "b"));
assertEquals("x.y in (\"a\", \"b\")", e3.toString());
}
@Test
public void testGetFrom() {
TstJavaBean bean = new TstJavaBean();
bean.setIntField(7);
Property<Integer> INT_FIELD = Property.create("intField", 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);
Property<Integer> OBJECT_FIELD_INT_FIELD = Property.create("objectField.intField", Integer.class);
assertEquals(Integer.valueOf(7), OBJECT_FIELD_INT_FIELD.getFrom(bean));
}
@Test
public void testGetFromNestedNull() {
TstJavaBean bean = new TstJavaBean();
bean.setObjectField(null);
Property<Integer> OBJECT_FIELD_INT_FIELD = Property.create("objectField.intField", 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);
Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
assertEquals(Arrays.asList(7, 8), INT_FIELD.getFromAll(beans));
}
@Test
public void testSetIn() {
TstJavaBean bean = new TstJavaBean();
Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
INT_FIELD.setIn(bean, 7);
assertEquals(7, bean.getIntField());
}
@Test
public void testSetInNestedProperty() {
TstJavaBean bean = new TstJavaBean();
bean.setObjectField(new TstJavaBean());
Property<Integer> OBJECT_FIELD_INT_FIELD = Property.create("objectField.intField", 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);
Property<Integer> OBJECT_FIELD_INT_FIELD = Property.create("objectField.intField", 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);
Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
INT_FIELD.setInAll(beans, 7);
assertEquals(7, bean.getIntField());
assertEquals(7, bean2.getIntField());
}
@Test
public void testEqualsWithName() {
Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
Property<Integer> INT_FIELD2 = Property.create("intField", Integer.class);
assertTrue(INT_FIELD != INT_FIELD2);
assertTrue(INT_FIELD.equals(INT_FIELD2));
}
@Test
public void testHashCodeWithName() {
Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
Property<Integer> INT_FIELD2 = Property.create("intField", Integer.class);
Property<Long> LONG_FIELD = Property.create("longField", Long.class);
assertTrue(INT_FIELD.hashCode() == INT_FIELD2.hashCode());
assertTrue(INT_FIELD.hashCode() != LONG_FIELD.hashCode());
}
@Test
public void testEqualsWithNameAndType() {
Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
Property<Integer> INT_FIELD2 = Property.create("intField", Integer.class);
assertTrue(INT_FIELD != INT_FIELD2);
assertTrue(INT_FIELD.equals(INT_FIELD2));
}
@Test
public void testHashCodeWithNameAndType() {
Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
Property<Integer> INT_FIELD2 = Property.create("intField", Integer.class);
Property<Long> LONG_FIELD = Property.create("longField", Long.class);
assertTrue(INT_FIELD.hashCode() == INT_FIELD2.hashCode());
assertTrue(INT_FIELD.hashCode() != LONG_FIELD.hashCode());
}
@Test
public void testEqualsWithExpAndType() {
Property<Integer> INT_FIELD = new Property<>(null, ExpressionFactory.exp("1"), Integer.class);
Property<Integer> INT_FIELD2 = new Property<>(null, ExpressionFactory.exp("1"), Integer.class);
assertTrue(INT_FIELD != INT_FIELD2);
assertTrue(INT_FIELD.equals(INT_FIELD2));
}
@Test
public void testHashCodeWithExpAndType() {
Property<Integer> INT_FIELD = new Property<>(null, ExpressionFactory.exp("1"), Integer.class);
Property<Integer> INT_FIELD2 = new Property<>(null, ExpressionFactory.exp("1"), Integer.class);
Property<Integer> INT_FIELD3 = new Property<>(null, ExpressionFactory.exp("2"), Integer.class);
assertEquals(INT_FIELD.hashCode(), INT_FIELD2.hashCode());
assertNotEquals(INT_FIELD.hashCode(), INT_FIELD3.hashCode());
}
@Test
public void testOuter() {
Property<String> inner = Property.create("xyz", String.class);
assertEquals("xyz+", inner.outer().getName());
Property<String> inner1 = Property.create("xyz.xxx", String.class);
assertEquals("xyz.xxx+", inner1.outer().getName());
Property<String> outer = Property.create("xyz+", String.class);
assertEquals("xyz+", outer.outer().getName());
}
@Test
public void testLike() {
Property<String> p = Property.create("prop", String.class);
Expression e = p.like("abc");
assertEquals("prop like \"abc\"", e.toString());
}
@Test
public void testLikeIgnoreCase() {
Property<String> p = Property.create("prop", String.class);
Expression e = p.likeIgnoreCase("abc");
assertEquals("prop likeIgnoreCase \"abc\"", e.toString());
}
@Test
public void testLike_NoEscape() {
Property<String> p = Property.create("prop", String.class);
Expression e = p.like("ab%c");
assertEquals("prop like \"ab%c\"", e.toString());
assertEquals(0, ((PatternMatchNode) e).getEscapeChar());
}
@Test
public void testContains() {
Property<String> p = Property.create("prop", String.class);
Expression e = p.contains("abc");
assertEquals("prop like \"%abc%\"", e.toString());
assertEquals(0, ((PatternMatchNode) e).getEscapeChar());
}
@Test
public void testStartsWith() {
Property<String> p = Property.create("prop", String.class);
Expression e = p.startsWith("abc");
assertEquals("prop like \"abc%\"", e.toString());
assertEquals(0, ((PatternMatchNode) e).getEscapeChar());
}
@Test
public void testEndsWith() {
Property<String> p = Property.create("prop", String.class);
Expression e = p.endsWith("abc");
assertEquals("prop like \"%abc\"", e.toString());
assertEquals(0, ((PatternMatchNode) e).getEscapeChar());
}
@Test
public void testContains_Escape1() {
Property<String> p = Property.create("prop", String.class);
Expression e = p.contains("a%bc");
assertEquals("prop like \"%a!%bc%\"", e.toString());
assertEquals('!', ((PatternMatchNode) e).getEscapeChar());
}
@Test
public void testContains_Escape2() {
Property<String> p = Property.create("prop", String.class);
Expression e = p.contains("a_!bc");
assertEquals("prop like \"%a#_!bc%\"", e.toString());
assertEquals('#', ((PatternMatchNode) e).getEscapeChar());
}
@Test
public void testExpressionConstructor() {
Property<Integer> p = Property.create("testPath", new ASTObjPath("test.path"), Integer.class);
assertEquals("testPath", p.getName());
Expression ex = p.getExpression();
assertEquals("test.path", ex.toString());
}
@SuppressWarnings("deprecation")
@Test
public void testDeprecatedConstruct() {
Property<String> p = new Property<>("p");
assertNull(p.getType());
assertEquals("p", p.getName());
assertEquals(new ASTObjPath("p"), p.getExpression());
}
@Test
public void testCreationWithName() {
Property<String> p1 = new Property<>("p1", String.class);
assertEquals(String.class, p1.getType());
assertEquals("p1", p1.getName());
assertEquals(new ASTObjPath("p1"), p1.getExpression());
Property<String> p2 = Property.create("p1", String.class);
assertEquals(p1, p2);
}
@Test
public void testCreationWithExp() {
Expression exp = FunctionExpressionFactory.currentTime();
Property<String> p1 = new Property<>(null, exp, String.class);
assertEquals(String.class, p1.getType());
assertEquals(null, p1.getName());
assertEquals(exp, p1.getExpression());
Property<String> p2 = Property.create(exp, String.class);
assertEquals(p1, p2);
}
@Test
public void testCreationWithNameAndExp() {
Expression exp = FunctionExpressionFactory.currentTime();
Property<String> p1 = new Property<>("p1", exp, String.class);
assertEquals(String.class, p1.getType());
assertEquals("p1", p1.getName());
assertEquals(exp, p1.getExpression());
Property<String> p2 = Property.create("p1", exp, String.class);
assertEquals(p1, p2);
}
@Test
public void testAlias() {
Expression exp = FunctionExpressionFactory.currentTime();
Property<String> p1 = new Property<>("p1", exp, String.class);
assertEquals(String.class, p1.getType());
assertEquals("p1", p1.getName());
assertEquals(exp, p1.getExpression());
Property<String> p2 = p1.alias("p2");
assertEquals(String.class, p2.getType());
assertEquals("p2", p2.getName());
assertEquals(exp, p2.getExpression());
}
@Test
public void testCount() {
Property<String> p = Property.create("test", String.class);
Property<Long> newProp = p.count();
assertTrue(newProp.getExpression() instanceof ASTCount);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testMin() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.min();
assertTrue(newProp.getExpression() instanceof ASTMin);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testMax() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.max();
assertTrue(newProp.getExpression() instanceof ASTMax);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testSum() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.sum();
assertTrue(newProp.getExpression() instanceof ASTSum);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testAvg() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.avg();
assertTrue(newProp.getExpression() instanceof ASTAvg);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testAbs() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.abs();
assertTrue(newProp.getExpression() instanceof ASTAbs);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testMod() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.mod(3.0);
assertTrue(newProp.getExpression() instanceof ASTMod);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
assertEquals(3.0, newProp.getExpression().getOperand(1));
}
@Test
public void testSqrt() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.sqrt();
assertTrue(newProp.getExpression() instanceof ASTSqrt);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testLength() {
Property<String> p = Property.create("test", String.class);
Property<Integer> newProp = p.length();
assertTrue(newProp.getExpression() instanceof ASTLength);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testLocateString() {
Property<String> p = Property.create("test", String.class);
Property<Integer> newProp = p.locate("test");
assertTrue(newProp.getExpression() instanceof ASTLocate);
assertEquals("test", newProp.getExpression().getOperand(0));
assertEquals(p.getExpression(), newProp.getExpression().getOperand(1));
}
@Test
public void testLocateProperty() {
Property<String> p = Property.create("test", String.class);
Property<String> p2 = Property.create("test2", String.class);
Property<Integer> newProp = p.locate(p2);
assertTrue(newProp.getExpression() instanceof ASTLocate);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(1));
assertEquals(p2.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testSustring() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.substring(1, 2);
assertTrue(newProp.getExpression() instanceof ASTSubstring);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
assertEquals(1, newProp.getExpression().getOperand(1));
assertEquals(2, newProp.getExpression().getOperand(2));
}
@Test
public void testTrim() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.trim();
assertTrue(newProp.getExpression() instanceof ASTTrim);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testLower() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.lower();
assertTrue(newProp.getExpression() instanceof ASTLower);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testUpper() {
Property<String> p = Property.create("test", String.class);
Property<String> newProp = p.upper();
assertTrue(newProp.getExpression() instanceof ASTUpper);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
}
@Test
public void testConcat() {
Property<String> p = Property.create("test", String.class);
Property<String> p2 = Property.create("concat", String.class);
Expression exp = new ASTScalar(3);
Property<String> newProp = p.concat("string", exp, p2);
assertTrue(newProp.getExpression() instanceof ASTConcat);
assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
assertEquals("string", newProp.getExpression().getOperand(1));
assertEquals(3, newProp.getExpression().getOperand(2)); // getOperand unwrapping ASTScalar
assertEquals(p2.getExpression(), newProp.getExpression().getOperand(3));
}
}