/***************************************************************** * 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.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.cayenne.CayenneDataObject; import org.apache.cayenne.DataObject; import org.apache.cayenne.exp.parser.ASTList; import org.junit.Test; public class Expression_ParamsTest { @Test public void testParams_Positional1() { Expression e = ExpressionFactory.exp("a = $a or x = $x"); Expression ep = e.paramsArray("A", 5); assertNotSame(e, ep); assertEquals("(a = \"A\") or (x = 5)", ep.toString()); } @Test public void testParams_Positional_Repeating() { Expression e = ExpressionFactory.exp("a = $a or x = $x and y = $x"); Expression ep = e.paramsArray("A", 5); assertNotSame(e, ep); assertEquals("(a = \"A\") or ((x = 5) and (y = 5))", ep.toString()); } @Test public void testParams_Positional_InAsValues() throws Exception { Expression inExp = ExpressionFactory.exp("k1 in ($ap, $bp)"); Expression transformed = inExp.paramsArray("a", "b"); assertEquals("k1 in (\"a\", \"b\")", transformed.toString()); } @Test(expected = ExpressionException.class) public void testParams_Positional_MoreParams() { Expression e = ExpressionFactory.exp("a = $a or x = $x"); e.paramsArray("A", 5, "B"); } @Test(expected = ExpressionException.class) public void testParams_Positional_LessParams() { Expression e = ExpressionFactory.exp("a = $a or x = $x"); e.paramsArray("B"); } @Test(expected = ExpressionException.class) public void testParams_Positional_NoParams() { Expression e = ExpressionFactory.exp("a = $a or x = $x"); e.paramsArray(); } @Test public void testParams_NullHandling_CAY847() { Expression e = ExpressionFactory.exp("X = $x"); e = e.params(Collections.singletonMap("x", null)); assertEquals("X = null", e.toString()); } @Test public void testParams_Map_Full() { Expression e = ExpressionFactory.exp("a = $a or x = $x"); @SuppressWarnings("serial") Expression ep = e.params(new HashMap<String, Object>() { { put("a", "A"); put("x", "X"); } }); assertNotSame(e, ep); assertEquals("(a = \"A\") or (x = \"X\")", ep.toString()); } @Test public void testParams_Map_Partial_Prune() { Expression e = ExpressionFactory.exp("a = $a or x = $x"); @SuppressWarnings("serial") Expression ep = e.params(new HashMap<String, Object>() { { put("a", "A"); } }); assertNotSame(e, ep); assertEquals("(a = \"A\")", ep.toString()); } @SuppressWarnings("serial") @Test(expected = ExpressionException.class) public void testParams_Map_Partial_NoPrune() { Expression e = ExpressionFactory.exp("a = $a or x = $x"); e.params(new HashMap<String, Object>() { { put("a", "A"); } }, false); } /** * Tests how parameter substitution algorithm works on an expression with no * parameters. */ @Test public void testCopy1() throws Exception { Expression e1 = ExpressionFactory.matchExp("k1", "v1"); e1 = e1.orExp(ExpressionFactory.matchExp("k2", "v2")); e1 = e1.orExp(ExpressionFactory.matchExp("k3", "v3")); Expression e2 = e1.params(new HashMap()); TstTraversalHandler.compareExps(e1, e2); } /** * Tests how parameter substitution algorithm works on an expression with no * parameters. */ @Test public void testCopy2() throws Exception { Expression andExp = ExpressionFactory.matchExp("k1", "v1"); andExp = andExp.andExp(ExpressionFactory.matchExp("k2", "v2")); andExp = andExp.andExp(ExpressionFactory.matchExp("k3", "v3")); List exprs = new ArrayList(); exprs.add(andExp); exprs.add(ExpressionFactory.matchExp("k1", "v1")); Expression e1 = ExpressionFactory.joinExp(Expression.OR, exprs); Expression e2 = e1.params(new HashMap()); TstTraversalHandler.compareExps(e1, e2); } /** * Tests how parameter substitution algorithm works on an expression with no * parameters. */ @Test public void testInParameter() throws Exception { Expression inExp = ExpressionFactory.exp("k1 in $test"); Expression e1 = ExpressionFactory.exp("k1 in ('a', 'b')"); Expression transformed = inExp.params(Collections.singletonMap("test", new Object[] { "a", "b" })); TstTraversalHandler.compareExps(e1, transformed); // just in case manually check params DataObject o1 = new CayenneDataObject(); o1.writePropertyDirectly("k1", "a"); assertTrue(transformed.match(o1)); DataObject o2 = new CayenneDataObject(); o2.writePropertyDirectly("k1", "x"); assertFalse(transformed.match(o2)); } @Test public void testInParameter_AsValues() throws Exception { Expression inExp = ExpressionFactory.exp("k1 in ($ap, $bp)"); String e1String = "k1 in (\"a\", \"b\")"; Expression e1 = ExpressionFactory.exp(e1String); Map<String, Object> params = new HashMap<String, Object>(); params.put("ap", "a"); params.put("bp", "b"); Expression transformed = inExp.params(params); TstTraversalHandler.compareExps(e1, transformed); assertEquals(e1String, transformed.toString()); // just in case manually check params DataObject o1 = new CayenneDataObject(); o1.writePropertyDirectly("k1", "a"); assertTrue(transformed.match(o1)); DataObject o2 = new CayenneDataObject(); o2.writePropertyDirectly("k1", "x"); assertFalse(transformed.match(o2)); } @Test(expected = ExpressionException.class) public void testFailOnMissingParams() throws Exception { Expression e1 = ExpressionFactory.matchExp("k1", new ExpressionParameter("test")); e1 = e1.orExp(ExpressionFactory.matchExp("k2", "v2")); e1 = e1.orExp(ExpressionFactory.matchExp("k3", "v3")); e1.params(new HashMap(), false); } @Test public void testParams1() throws Exception { Expression e1 = ExpressionFactory.matchExp("k1", new ExpressionParameter("test")); Map map = new HashMap(); map.put("test", "xyz"); Expression e2 = e1.params(map, false); assertNotNull(e2); assertEquals(2, e2.getOperandCount()); assertEquals(Expression.EQUAL_TO, e2.getType()); assertEquals("xyz", e2.getOperand(1)); } @Test public void testParams2() throws Exception { Expression e1 = ExpressionFactory.likeExp("k1", new ExpressionParameter("test")); Map map = new HashMap(); map.put("test", "xyz"); Expression e2 = e1.params(map, false); assertNotNull(e2); assertEquals(2, e2.getOperandCount()); assertEquals(Expression.LIKE, e2.getType()); assertEquals("xyz", e2.getOperand(1)); } @Test public void testNoParams1() throws Exception { Expression e1 = ExpressionFactory.matchExp("k1", new ExpressionParameter("test")); Expression e2 = e1.params(Collections.<String, Object> emptyMap()); // all expression nodes must be pruned assertNull(e2); } @Test public void testNoParams2() throws Exception { List list = new ArrayList(); list.add(ExpressionFactory.matchExp("k1", new ExpressionParameter( "test1"))); list.add(ExpressionFactory.matchExp("k2", new ExpressionParameter( "test2"))); list.add(ExpressionFactory.matchExp("k3", new ExpressionParameter( "test3"))); list.add(ExpressionFactory.matchExp("k4", new ExpressionParameter( "test4"))); Expression e1 = ExpressionFactory.or(list); Map params = new HashMap(); params.put("test2", "abc"); params.put("test3", "xyz"); Expression e2 = e1.params(params); // some expression nodes must be pruned assertNotNull(e2); assertEquals(2, e2.getOperandCount()); Expression k2 = (Expression) e2.getOperand(0); assertEquals("abc", k2.getOperand(1)); Expression k3 = (Expression) e2.getOperand(1); assertEquals("xyz", k3.getOperand(1)); } @Test public void testNoParams3() throws Exception { List list = new ArrayList(); list.add(ExpressionFactory.matchExp("k1", new ExpressionParameter( "test1"))); list.add(ExpressionFactory.matchExp("k2", new ExpressionParameter( "test2"))); list.add(ExpressionFactory.matchExp("k3", new ExpressionParameter( "test3"))); list.add(ExpressionFactory.matchExp("k4", new ExpressionParameter( "test4"))); Expression e1 = ExpressionFactory.joinExp(Expression.OR, list); Map params = new HashMap(); params.put("test4", "123"); Expression e2 = e1.params(params, true); // some expression nodes must be pruned assertNotNull(e2); assertTrue("List expression: " + e2, !(e2 instanceof ASTList)); assertEquals(2, e2.getOperandCount()); assertEquals("123", e2.getOperand(1)); assertEquals("k4", ((Expression) e2.getOperand(0)).getOperand(0)); } @Test public void testNullOptionalParameter() throws Exception { Expression e = ExpressionFactory.exp("abc = 3 and x = $a"); Expression e1 = e.params(Collections.EMPTY_MAP, true); // $a must be pruned assertEquals(ExpressionFactory.exp("abc = 3"), e1); Map params = new HashMap(); params.put("a", null); Expression e2 = e.params(params, true); // null must be preserved assertEquals(ExpressionFactory.exp("abc = 3 and x = null"), e2); } @Test(expected = ExpressionException.class) public void testNullRequiredParameter1() throws Exception { Expression e1 = ExpressionFactory.exp("abc = 3 and x = $a"); e1.params(Collections.EMPTY_MAP, false); } @Test public void testNullRequiredParameter2() throws Exception { Expression e1 = ExpressionFactory.exp("abc = 3 and x = $a"); Map params = new HashMap(); params.put("a", null); Expression e2 = e1.params(params, false); // null must be preserved assertEquals(ExpressionFactory.exp("abc = 3 and x = null"), e2); } @Test public void testNulls() { Expression e1 = ExpressionFactory.exp("x = null"); Expression e2 = e1.params(Collections.EMPTY_MAP, true); assertNotNull(e2); TstTraversalHandler.compareExps(e1, e2); } @Test public void testCopy1_FromString() { Expression e1 = ExpressionFactory .exp("k1 = 'v1' or k2 = 'v2' or k3 = 'v3'"); Expression e2 = e1.params(Collections.EMPTY_MAP); TstTraversalHandler.compareExps(e1, e2); } /** * Tests how parameter substitution algorithm works on an expression with no * parameters. */ @Test public void testCopy2_FromString() { Expression e1 = ExpressionFactory .exp("(k1 = 'v1' and k2 = 'v2' and k3 = 'v3') or (k1 = 'v1')"); Expression e2 = e1.params(Collections.EMPTY_MAP); TstTraversalHandler.compareExps(e1, e2); } @Test public void testCopy3_FromString() { Expression e1 = ExpressionFactory.exp("(k1 / 2) = (k2 * 2)"); Expression e2 = e1.params(Collections.EMPTY_MAP); TstTraversalHandler.compareExps(e1, e2); } /** * Tests how parameter substitution algorithm works on an expression with no * parameters. */ @Test(expected = ExpressionException.class) public void testFailOnMissingParams_FromString() { Expression e1 = ExpressionFactory .exp("k1 = $test or k2 = 'v2' or k3 = 'v3'"); e1.params(Collections.EMPTY_MAP, false); } @Test public void testParams1_FromString() { Expression e1 = ExpressionFactory.exp("k1 = $test"); Map<String, Object> map = new HashMap<String, Object>(); map.put("test", "xyz"); Expression e2 = e1.params(map, false); assertNotNull(e2); assertEquals(2, e2.getOperandCount()); assertEquals(Expression.EQUAL_TO, e2.getType()); assertEquals("xyz", e2.getOperand(1)); } @Test public void testParams2_FromString() { Expression e1 = ExpressionFactory.exp("k1 like $test"); Map<String, Object> map = new HashMap<String, Object>(); map.put("test", "xyz"); Expression e2 = e1.params(map, false); assertNotNull(e2); assertEquals(2, e2.getOperandCount()); assertEquals(Expression.LIKE, e2.getType()); assertEquals("xyz", e2.getOperand(1)); } @Test public void testNoParams1_FromString() { Expression e1 = ExpressionFactory.exp("k1 = $test"); Expression e2 = e1.params(Collections.EMPTY_MAP); // all expression nodes must be pruned assertNull(e2); } @Test public void testNoParams2_FromString() { Expression e1 = ExpressionFactory .exp("k1 = $test1 or k2 = $test2 or k3 = $test3 or k4 = $test4"); Map<String, Object> params = new HashMap<String, Object>(); params.put("test2", "abc"); params.put("test3", "xyz"); Expression e2 = e1.params(params); // some expression nodes must be pruned assertNotNull(e2); assertEquals(2, e2.getOperandCount()); Expression k2 = (Expression) e2.getOperand(0); assertEquals("abc", k2.getOperand(1)); Expression k3 = (Expression) e2.getOperand(1); assertEquals("xyz", k3.getOperand(1)); } @Test public void testNoParams3_FromString() { Expression e1 = ExpressionFactory .exp("k1 = $test1 or k2 = $test2 or k3 = $test3 or k4 = $test4"); Map<String, Object> params = new HashMap<String, Object>(); params.put("test4", "123"); Expression e2 = e1.params(params); // some expression nodes must be pruned assertNotNull(e2); assertEquals(2, e2.getOperandCount()); assertEquals("123", e2.getOperand(1)); assertEquals("k4", ((Expression) e2.getOperand(0)).getOperand(0)); } }