/***************************************************************** * 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.apache.cayenne.exp.ExpressionFactory.exp; import static org.apache.cayenne.exp.ExpressionFactory.greaterExp; import static org.apache.cayenne.exp.FunctionExpressionFactory.lengthExp; import static org.apache.cayenne.exp.FunctionExpressionFactory.substringExp; import static org.apache.cayenne.exp.FunctionExpressionFactory.trimExp; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.List; import org.apache.cayenne.ObjectContext; import org.apache.cayenne.di.Inject; import org.apache.cayenne.query.ObjectSelect; import org.apache.cayenne.query.SelectQuery; import org.apache.cayenne.testdo.testmap.Artist; import org.apache.cayenne.testdo.testmap.Painting; import org.apache.cayenne.unit.UnitDbAdapter; import org.apache.cayenne.unit.di.server.CayenneProjects; import org.apache.cayenne.unit.di.server.ServerCase; import org.apache.cayenne.unit.di.server.UseServerRuntime; import org.junit.Test; @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT) public class ExpressionFactoryIT extends ServerCase { @Inject private ObjectContext context; @Inject private UnitDbAdapter accessStackAdapter; // CAY-416 @Test public void testCollectionMatch() { Artist artist = context.newObject(Artist.class); artist.setArtistName("artist"); Painting p1 = context.newObject(Painting.class), p2 = context.newObject(Painting.class), p3 = context.newObject(Painting.class); p1.setPaintingTitle("p1"); p2.setPaintingTitle("p2"); p3.setPaintingTitle("p3"); artist.addToPaintingArray(p1); artist.addToPaintingArray(p2); context.commitChanges(); assertTrue(ExpressionFactory.matchExp("paintingArray", p1).match(artist)); assertFalse(ExpressionFactory.matchExp("paintingArray", p3).match(artist)); assertTrue(ExpressionFactory.noMatchExp("paintingArray", p1).match(artist)); // changed to align with SQL assertTrue(ExpressionFactory.noMatchExp("paintingArray", p3).match(artist)); assertTrue(ExpressionFactory.matchExp("paintingArray.paintingTitle", "p1").match(artist)); assertFalse(ExpressionFactory.matchExp("paintingArray.paintingTitle", "p3").match(artist)); assertTrue(ExpressionFactory.noMatchExp("paintingArray.paintingTitle", "p1").match(artist)); // changed to align with SQL assertTrue(ExpressionFactory.noMatchExp("paintingArray.paintingTitle", "p3").match(artist)); assertTrue(ExpressionFactory.inExp("paintingTitle", "p1").match(p1)); assertFalse(ExpressionFactory.notInExp("paintingTitle", "p3").match(p3)); } @Test public void testIn() { Artist a1 = context.newObject(Artist.class); a1.setArtistName("a1"); Painting p1 = context.newObject(Painting.class); p1.setPaintingTitle("p1"); Painting p2 = context.newObject(Painting.class); p2.setPaintingTitle("p2"); a1.addToPaintingArray(p1); a1.addToPaintingArray(p2); Expression in = ExpressionFactory.inExp("paintingArray", p1); assertTrue(in.match(a1)); } @Test public void testEscapeCharacter() { if(!accessStackAdapter.supportsEscapeInLike()) { return; } Artist a1 = context.newObject(Artist.class); a1.setArtistName("A_1"); Artist a2 = context.newObject(Artist.class); a2.setArtistName("A_2"); context.commitChanges(); Expression ex1 = ExpressionFactory.likeIgnoreCaseDbExp("ARTIST_NAME", "A*_1", '*'); SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class, ex1); List<Artist> artists = context.select(q1); assertEquals(1, artists.size()); Expression ex2 = ExpressionFactory.likeExp("artistName", "A*_2", '*'); SelectQuery<Artist> q2 = new SelectQuery<Artist>(Artist.class, ex2); artists = context.select(q2); assertEquals(1, artists.size()); } @Test public void testContains_Escape() { if(!accessStackAdapter.supportsEscapeInLike()) { return; } Artist a1 = context.newObject(Artist.class); a1.setArtistName("MA_1X"); Artist a2 = context.newObject(Artist.class); a2.setArtistName("CA%2Y"); context.commitChanges(); Expression ex1 = ExpressionFactory.containsExp(Artist.ARTIST_NAME.getName(), "A_1"); SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class, ex1); List<Artist> artists = context.select(q1); assertEquals(1, artists.size()); Expression ex2 = ExpressionFactory.containsExp(Artist.ARTIST_NAME.getName(), "A%2"); SelectQuery<Artist> q2 = new SelectQuery<Artist>(Artist.class, ex2); artists = context.select(q2); assertEquals(1, artists.size()); } @Test public void testDifferentExpressionAPI() throws Exception { List<Artist> res; // First version via expression string Expression exp1 = exp( "length(substring(artistName, 1, 3)) > length(trim(artistName))" ); res = ObjectSelect.query(Artist.class, exp1).select(context); assertEquals(0, res.size()); // Second version via FunctionExpressionFactory API Expression exp2 = greaterExp( lengthExp(substringExp(Artist.ARTIST_NAME.path(), 1, 3)), lengthExp(trimExp(Artist.ARTIST_NAME.path())) ); res = ObjectSelect.query(Artist.class, exp2).select(context); assertEquals(0, res.size()); // Third version via Property API Property<Integer> lengthSub = Property.create(lengthExp(substringExp(Artist.ARTIST_NAME.path(), 1, 3)), Integer.class); Property<Integer> length = Property.create(lengthExp(trimExp(Artist.ARTIST_NAME.path())), Integer.class); Expression exp3 = lengthSub.gt(length); res = ObjectSelect.query(Artist.class, exp3).select(context); assertEquals(0, res.size()); // Check that all expressions are equal assertEquals(exp1, exp2); assertEquals(exp3, exp3); } }