/*
* Copyright 2008 Alin Dreghiciu.
* Copyright 2009 Niclas Hedhman.
*
* Licensed 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.qi4j.test.indexing;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
import org.qi4j.api.query.NotQueryableException;
import org.qi4j.api.query.Query;
import org.qi4j.api.query.QueryBuilder;
import org.qi4j.api.query.grammar.OrderBy;
import org.qi4j.spi.query.EntityFinderException;
import org.qi4j.spi.query.IndexExporter;
import org.qi4j.test.indexing.model.City;
import org.qi4j.test.indexing.model.Domain;
import org.qi4j.test.indexing.model.Female;
import org.qi4j.test.indexing.model.File;
import org.qi4j.test.indexing.model.Male;
import org.qi4j.test.indexing.model.Nameable;
import org.qi4j.test.indexing.model.Person;
import org.qi4j.test.indexing.model.QueryParam;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.qi4j.api.query.QueryExpressions.and;
import static org.qi4j.api.query.QueryExpressions.contains;
import static org.qi4j.api.query.QueryExpressions.eq;
import static org.qi4j.api.query.QueryExpressions.ge;
import static org.qi4j.api.query.QueryExpressions.gt;
import static org.qi4j.api.query.QueryExpressions.isNotNull;
import static org.qi4j.api.query.QueryExpressions.isNull;
import static org.qi4j.api.query.QueryExpressions.matches;
import static org.qi4j.api.query.QueryExpressions.not;
import static org.qi4j.api.query.QueryExpressions.oneOf;
import static org.qi4j.api.query.QueryExpressions.or;
import static org.qi4j.api.query.QueryExpressions.orderBy;
import static org.qi4j.api.query.QueryExpressions.templateFor;
public abstract class AbstractQueryTest
extends AbstractAnyQueryTest
{
@Test
public void showNetwork()
throws IOException
{
IndexExporter indexerExporter = module.findService( IndexExporter.class ).get();
indexerExporter.exportReadableToStream( System.out );
}
private static void verifyUnorderedResults( final Iterable<? extends Nameable> results, final String... names )
{
final List<String> expected = new ArrayList<String>( Arrays.asList( names ) );
for( Nameable entity : results )
{
String name = entity.name().get();
assertTrue( name + " returned but not expected", expected.remove( name ) );
}
for( String notReturned : expected )
{
fail( notReturned + " was expected but not returned" );
}
}
private static void verifyOrderedResults( final Iterable<? extends Nameable> results, final String... names )
{
final List<String> expected = new ArrayList<String>( Arrays.asList( names ) );
final List<String> actual = new ArrayList<String>();
for( Nameable result : results )
{
actual.add( result.name().get() );
}
assertThat( "Result is incorrect", actual, equalTo( expected ) );
}
@Test
public void script01()
throws EntityFinderException
{
final QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
final Query<Person> query = unitOfWork.newQuery( qb );
System.out.println( "*** script01: " + query );
verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Jack Doe" );
}
@Test
public void script02()
throws EntityFinderException
{
final QueryBuilder<Domain> qb = this.module.newQueryBuilder( Domain.class );
final Nameable nameable = templateFor( Nameable.class );
final Query<Domain> query = unitOfWork.newQuery( qb.where( eq( nameable.name(), "Gaming" ) ) );
System.out.println( "*** script02: " + query );
verifyUnorderedResults( query, "Gaming" );
}
@Test
public void script03()
throws EntityFinderException
{
QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
Query<Nameable> query = unitOfWork.newQuery( qb );
verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Jack Doe", "Penang", "Kuala Lumpur", "Cooking", "Gaming",
"Programming", "Cars" );
System.out.println( "*** script03: " + query );
}
@Test
public void script04()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person personTemplate = templateFor( Person.class );
City placeOfBirth = personTemplate.placeOfBirth().get();
Query<Person> query = unitOfWork.newQuery( qb.where( eq( placeOfBirth.name(), "Kuala Lumpur" ) ) );
System.out.println( "*** script04: " + query );
verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
}
@Test
public void script05()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.mother()
.get()
.placeOfBirth()
.get()
.name(), "Kuala Lumpur" ) )
);
System.out.println( "*** script05: " + query );
verifyUnorderedResults( query, "Joe Doe" );
}
@Test
public void script06()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Query<Person> query = unitOfWork.newQuery( qb.where( ge( person.yearOfBirth(), 1973 ) ) );
System.out.println( "*** script06: " + query );
verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
}
@Test
public void script07()
throws EntityFinderException
{
QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
Person person = templateFor( Person.class );
Query<Nameable> query = unitOfWork.newQuery( qb.where(
and( ge( person.yearOfBirth(), 1900 ), eq( person.placeOfBirth().get().name(), "Penang" ) ) ) );
System.out.println( "*** script07: " + query );
verifyUnorderedResults( query, "Jack Doe" );
}
@Test
public void script08()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Query<Person> query = unitOfWork.newQuery( qb.where( or( eq( person.yearOfBirth(), 1970 ), eq( person.yearOfBirth(), 1975 ) ) )
);
System.out.println( "*** script08: " + query );
verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
}
@Test
public void script09()
throws EntityFinderException
{
QueryBuilder<Female> qb = this.module.newQueryBuilder( Female.class );
Person person = templateFor( Person.class );
Query<Female> query = unitOfWork.newQuery( qb.where( or( eq( person.yearOfBirth(), 1970 ), eq( person.yearOfBirth(), 1975 ) ) )
);
System.out.println( "*** script09: " + query );
verifyUnorderedResults( query, "Ann Doe" );
}
@Test
public void script10()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Query<Person> query = unitOfWork.newQuery( qb.where( not( eq( person.yearOfBirth(), 1975 ) ) ) );
System.out.println( "*** script10: " + query );
verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
}
@Test
public void script11()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Query<Person> query = unitOfWork.newQuery( qb.where( isNotNull( person.email() ) ) );
System.out.println( "*** script11: " + query );
verifyUnorderedResults( query, "Joe Doe" );
}
@Test
public void script12()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Query<Person> query = unitOfWork.newQuery( qb.where( isNull( person.email() ) ) );
System.out.println( "*** script12: " + query );
verifyUnorderedResults( query, "Ann Doe", "Jack Doe" );
}
@Test
public void script13()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Male person = templateFor( Male.class );
Query<Person> query = unitOfWork.newQuery( qb.where( isNotNull( person.wife() ) ) );
System.out.println( "*** script13: " + query );
verifyUnorderedResults( query, "Jack Doe" );
}
@Test
public void script14()
throws EntityFinderException
{
QueryBuilder<Male> qb = this.module.newQueryBuilder( Male.class );
Male person = templateFor( Male.class );
Query<Male> query = unitOfWork.newQuery( qb.where( isNull( person.wife() ) ) );
System.out.println( "*** script14: " + query );
verifyUnorderedResults( query, "Joe Doe" );
}
@Test
public void script15()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Male person = templateFor( Male.class );
Query<Person> query = unitOfWork.newQuery( qb.where( isNull( person.wife() ) ) );
System.out.println( "*** script15: " + query );
verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
}
@Test
public void script16()
throws EntityFinderException
{
QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
// should return only 2 entities
Nameable nameable = templateFor( Nameable.class );
Query<Nameable> query = unitOfWork.newQuery( qb );
query.orderBy( orderBy( nameable.name() ) );
query.maxResults( 2 );
System.out.println( "*** script16: " + query );
verifyOrderedResults( query, "Ann Doe", "Cars" );
}
@Test
public void script17()
throws EntityFinderException
{
QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
// should return only 3 entities starting with forth one
Nameable nameable = templateFor( Nameable.class );
Query<Nameable> query = unitOfWork.newQuery( qb );
query.orderBy( orderBy( nameable.name() ) );
query.firstResult( 3 );
query.maxResults( 2 );
System.out.println( "*** script17: " + query );
verifyOrderedResults( query, "Gaming", "Jack Doe" );
}
@Test
public void script18()
throws EntityFinderException
{
QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
// should return all Nameable entities sorted by name
Nameable nameable = templateFor( Nameable.class );
Query<Nameable> query = unitOfWork.newQuery( qb );
query.orderBy( orderBy( nameable.name() ) );
System.out.println( "*** script18: " + query );
verifyOrderedResults( query, "Ann Doe", "Cars", "Cooking", "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur",
"Penang", "Programming" );
}
@Test
public void script19()
throws EntityFinderException
{
QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
// should return all Nameable entities with a name > "D" sorted by name
Nameable nameable = templateFor( Nameable.class );
Query<Nameable> query = unitOfWork.newQuery( qb.where( gt( nameable.name(), "D" ) ) );
query.orderBy( orderBy( nameable.name() ) );
System.out.println( "*** script19: " + query );
verifyOrderedResults( query, "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur", "Penang", "Programming" );
}
@Test
public void script20()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
// should return all Persons born after 1973 (Ann and Joe Doe) sorted descending by name
Person person = templateFor( Person.class );
Query<Person> query = unitOfWork.newQuery( qb.where( gt( person.yearOfBirth(), 1973 ) ) );
query.orderBy( orderBy( person.name(), OrderBy.Order.DESCENDING ) );
System.out.println( "*** script20: " + query );
verifyOrderedResults( query, "Joe Doe", "Ann Doe" );
}
@Test
public void script21()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
// should return all Persons sorted by name of the city they were born, and then by year they were born
Person person = templateFor( Person.class );
Query<Person> query = unitOfWork.newQuery( qb );
query.orderBy( orderBy( person.placeOfBirth().get().name() ), orderBy( person.yearOfBirth() ) );
System.out.println( "*** script21: " + query );
verifyOrderedResults( query, "Ann Doe", "Joe Doe", "Jack Doe" );
}
@Test
public void script22()
throws EntityFinderException
{
QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
Nameable nameable = templateFor( Nameable.class );
// should return Jack and Joe Doe
Query<Nameable> query = unitOfWork.newQuery( qb.where( matches( nameable.name(), "J.*Doe" ) ) );
System.out.println( "*** script22: " + query );
verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
}
@Ignore( "Skip this one for now. It sporadically fails sometimes." )
@Test
public void script23()
throws EntityFinderException
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Domain interests = oneOf( person.interests() );
Query<Person> query = unitOfWork.newQuery( qb.where( eq( interests.name(), "Cars" ) ) );
System.out.println( "*** script23: " + query );
verifyOrderedResults( query, "Jack Doe" );
}
@Test
public void script24()
throws EntityFinderException
{
final QueryBuilder<Domain> qb = this.module.newQueryBuilder( Domain.class );
final Nameable nameable = templateFor( Nameable.class );
final Query<Domain> query = unitOfWork.newQuery( qb.where( eq( nameable.name(), "Gaming" ) ) );
System.out.println( "*** script24: " + query );
assertThat( query.find().name().get(), is( equalTo( "Gaming" ) ) );
}
@Test( expected = NotQueryableException.class )
public void script25()
{
this.module.newQueryBuilder( File.class );
}
@Test( expected = NotQueryableException.class )
public void script26()
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
qb.where( eq( person.personalWebsite().get().file().get().value(), "some/path" ) );
}
@Test( expected = NotQueryableException.class )
public void script27()
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
qb.where( eq( person.personalWebsite().get().host().get().value(), "www.qi4j.org" ) );
}
@Test( expected = NotQueryableException.class )
public void script28()
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
qb.where( eq( person.personalWebsite().get().port().get().value(), 8080 ) );
}
@Test
@Ignore( "Wait until indexing of complex values is implemented" )
public void script29()
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.personalWebsite()
.get()
.protocol()
.get()
.value(), "http" ) )
);
System.out.println( "*** script29: " + query );
verifyUnorderedResults( query, "Jack Doe" );
}
@Test
@Ignore( "Wait till 1.1?" )
public void script30()
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
QueryParam queryParam = null; // oneOf( person.personalWebsite().get().queryParams() );
Query<Person> query = unitOfWork.newQuery( qb.where( and( eq( queryParam.name(), "foo" ), eq( queryParam.value(), "bar" ) ) )
);
System.out.println( "*** script30: " + query );
verifyUnorderedResults( query, "Jack Doe" );
}
@Test
@Ignore( "Wait till 1.1?" )
public void script31()
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Map<String, String> info = new HashMap<String, String>();
Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.additionalInfo(), info ) ) );
System.out.println( "*** script31: " + query );
verifyUnorderedResults( query, "Jack Doe" );
}
@Test
public void script32()
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Map<String, String> info = new HashMap<String, String>();
Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.address().get().line1(), "Qi Alley 4j" ) ) );
System.out.println( "*** script32: " + query );
verifyUnorderedResults( query, "Joe Doe" );
}
@Test
public void script33()
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Domain gaming = unitOfWork.get( Domain.class, "Gaming" );
Query<Person> query = unitOfWork.newQuery( qb.where( contains( person.interests(), gaming ) ) );
System.out.println( "*** script33: " + query );
verifyUnorderedResults( query, "Joe Doe" );
}
@Test
public void script34()
{
QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
Person person = templateFor( Person.class );
Female annDoe = unitOfWork.get( Female.class, "anndoe" );
Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.mother(), annDoe ) ) );
verifyUnorderedResults( query, "Joe Doe" );
}
}