blob: 41ec9615f53462cc4b79731795336c438b631a8c [file] [log] [blame]
/*
* Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
*
* 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.apache.zest.runtime.query;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.zest.api.composite.Composite;
import org.apache.zest.api.property.Property;
import org.apache.zest.api.query.grammar.OrderBy;
import org.apache.zest.api.util.Classes;
import org.apache.zest.functional.Iterables;
import org.apache.zest.functional.Specification;
import org.apache.zest.functional.Specifications;
import org.apache.zest.spi.query.QuerySource;
/**
* JAVADOC
*/
public class IterableQuerySource
implements QuerySource
{
private final Iterable iterable;
/**
* Constructor.
*
* @param iterable iterable
*/
@SuppressWarnings( "raw" )
IterableQuerySource( final Iterable iterable )
{
this.iterable = iterable;
}
@Override
public <T> T find( Class<T> resultType,
Specification<Composite> whereClause,
Iterable<OrderBy> orderBySegments,
Integer firstResult,
Integer maxResults,
Map<String, Object> variables
)
{
final Iterator<T> iterator = iterator( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
if( iterator.hasNext() )
{
return iterator.next();
}
return null;
}
@Override
public <T> long count( Class<T> resultType,
Specification<Composite> whereClause,
Iterable<OrderBy> orderBySegments,
Integer firstResult,
Integer maxResults,
Map<String, Object> variables
)
{
return list( resultType, whereClause, orderBySegments, firstResult, maxResults, variables ).size();
}
@Override
public <T> Iterator<T> iterator( Class<T> resultType,
Specification<Composite> whereClause,
Iterable<OrderBy> orderBySegments,
Integer firstResult,
Integer maxResults,
Map<String, Object> variables
)
{
return list( resultType, whereClause, orderBySegments, firstResult, maxResults, variables ).iterator();
}
@SuppressWarnings( {"raw", "unchecked"} )
private <T> List<T> list( Class<T> resultType,
Specification<Composite> whereClause,
Iterable<OrderBy> orderBySegments,
Integer firstResult,
Integer maxResults,
Map<String, Object> variables
)
{
// Ensure it's a list first
List<T> list = filter( resultType, whereClause );
// Order list
if( orderBySegments != null )
{
// Sort it
Collections.sort( list, new OrderByComparator( orderBySegments ) );
}
// Cut results
if( firstResult != null )
{
if( firstResult > list.size() )
{
return Collections.emptyList();
}
int toIdx;
if( maxResults != null )
{
toIdx = Math.min( firstResult + maxResults, list.size() );
}
else
{
toIdx = list.size();
}
list = list.subList( firstResult, toIdx );
}
else
{
int toIdx;
if( maxResults != null )
{
toIdx = Math.min( maxResults, list.size() );
}
else
{
toIdx = list.size();
}
list = list.subList( 0, toIdx );
}
return list;
}
@SuppressWarnings( {"raw", "unchecked"} )
private <T> List<T> filter( Class<T> resultType, Specification whereClause )
{
if( whereClause == null )
{
return Iterables.toList( Iterables.filter( Classes.instanceOf( resultType ), iterable ) );
}
else
{
return Iterables.toList( Iterables.filter( Specifications.and( Classes.instanceOf( resultType ), whereClause ), iterable ) );
}
}
@Override
public String toString()
{
return "IterableQuerySource{" + iterable + '}';
}
private static class OrderByComparator<T extends Composite>
implements Comparator<T>
{
private final Iterable<OrderBy> orderBySegments;
private OrderByComparator( Iterable<OrderBy> orderBySegments )
{
this.orderBySegments = orderBySegments;
}
@Override
@SuppressWarnings( {"raw", "unchecked"} )
public int compare( T o1, T o2 )
{
for( OrderBy orderBySegment : orderBySegments )
{
try
{
final Property prop1 = orderBySegment.property().map( o1 );
final Property prop2 = orderBySegment.property().map( o2 );
if( prop1 == null || prop2 == null )
{
if( prop1 == null && prop2 == null )
{
return 0;
}
else if( prop1 != null )
{
return 1;
}
return -1;
}
final Object value1 = prop1.get();
final Object value2 = prop2.get();
if( value1 == null || value2 == null )
{
if( value1 == null && value2 == null )
{
return 0;
}
else if( value1 != null )
{
return 1;
}
return -1;
}
if( value1 instanceof Comparable )
{
int result = ( (Comparable) value1 ).compareTo( value2 );
if( result != 0 )
{
if( orderBySegment.order() == OrderBy.Order.ASCENDING )
{
return result;
}
else
{
return -result;
}
}
}
}
catch( Exception e )
{
return 0;
}
}
return 0;
}
}
}