/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.search.query.hibernate.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity;
import org.hibernate.search.engine.spi.SearchFactoryImplementor;
import org.hibernate.search.util.logging.impl.Log;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Restrictions;
import org.hibernate.search.query.engine.spi.EntityInfo;
import org.hibernate.search.query.engine.spi.TimeoutManager;
import org.hibernate.search.util.logging.impl.LoggerFactory;
/**
* Initialize object using one or several criteria queries.
*
* @author Emmanuel Bernard <emmanuel@hibernate.org>
*/
public class CriteriaObjectsInitializer implements ObjectsInitializer {
private static final Log log = LoggerFactory.make();
private static final int MAX_IN_CLAUSE = 500;
public static final CriteriaObjectsInitializer INSTANCE = new CriteriaObjectsInitializer();
private CriteriaObjectsInitializer() {
// use INSTANCE instead of constructor
}
public void initializeObjects(EntityInfo[] entityInfos,
Criteria criteria, Class<?> entityType,
SearchFactoryImplementor searchFactoryImplementor,
TimeoutManager timeoutManager,
Session session) {
//Do not call isTimeOut here as the caller might be the last biggie on the list.
final int maxResults = entityInfos.length;
if ( log.isTraceEnabled() ) log.tracef( "Load %d objects using criteria queries", maxResults );
if ( maxResults == 0 ) {
return;
}
//criteria query not overridden, define one
if ( criteria == null ) {
criteria = session.createCriteria( entityType );
}
Set<Class<?>> indexedEntities = searchFactoryImplementor.getIndexedTypesPolymorphic( new Class<?>[] { entityType } );
DocumentBuilderIndexedEntity<?> builder = searchFactoryImplementor.getIndexBindingForEntity(
indexedEntities.iterator().next()
).getDocumentBuilder();
String idName = builder.getIdentifierName();
Disjunction disjunction = Restrictions.disjunction();
int loop = maxResults / MAX_IN_CLAUSE;
boolean exact = maxResults % MAX_IN_CLAUSE == 0;
if ( !exact ) {
loop++;
}
for ( int index = 0; index < loop; index++ ) {
int max = index * MAX_IN_CLAUSE + MAX_IN_CLAUSE <= maxResults ?
index * MAX_IN_CLAUSE + MAX_IN_CLAUSE :
maxResults;
List<Serializable> ids = new ArrayList<Serializable>( max - index * MAX_IN_CLAUSE );
for ( int entityInfoIndex = index * MAX_IN_CLAUSE; entityInfoIndex < max; entityInfoIndex++ ) {
ids.add( entityInfos[entityInfoIndex].getId() );
}
disjunction.add( Restrictions.in( idName, ids ) );
}
criteria.add( disjunction );
//not best effort so fail fast
if ( timeoutManager.getType() != TimeoutManager.Type.LIMIT ) {
Long timeLeftInSecond = timeoutManager.getTimeoutLeftInSeconds();
if ( timeLeftInSecond != null ) {
if (timeLeftInSecond == 0) {
timeoutManager.reactOnQueryTimeoutExceptionWhileExtracting(null);
}
criteria.setTimeout( timeLeftInSecond.intValue() );
}
}
criteria.list(); //load all objects
}
}