/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.store.dao;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Query;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.google.common.collect.Lists;
import com.enonic.cms.framework.cache.CacheFacade;
import com.enonic.cms.framework.hibernate.support.InClauseBuilder;
import com.enonic.cms.framework.hibernate.support.SelectBuilder;
import com.enonic.cms.core.content.ContentEntity;
import com.enonic.cms.core.content.ContentKey;
import com.enonic.cms.core.content.ContentMap;
import com.enonic.cms.core.content.ContentStatus;
import com.enonic.cms.core.content.ContentVersionEntity;
import com.enonic.cms.core.content.ContentVersionKey;
import com.enonic.cms.core.content.RelatedContentEntity;
import com.enonic.cms.core.content.access.ContentAccessEntity;
import com.enonic.cms.core.content.resultset.RelatedChildContent;
import com.enonic.cms.core.security.group.GroupKey;
class FindRelatedChildrenCommand
{
private CacheFacade entityCache;
private HibernateTemplate hibernateTemplate;
FindRelatedChildrenCommand( CacheFacade entityCache, HibernateTemplate hibernateTemplate )
{
this.entityCache = entityCache;
this.hibernateTemplate = hibernateTemplate;
}
Collection<RelatedChildContent> execute( RelatedChildContentQuery relatedChildContentQuery )
{
if ( relatedChildContentQuery.getContentVersions() == null || relatedChildContentQuery.getContentVersions().size() == 0 )
{
throw new IllegalArgumentException( "Given contentVersionKeys must contain values" );
}
String hql = getRelatedChildrenByKeyHQL( relatedChildContentQuery );
Query compiled = hibernateTemplate.getSessionFactory().getCurrentSession().createQuery( hql );
compiled.setCacheable( false );
compiled.setReadOnly( true );
compiled.setParameter( "deleted", 0 );
if ( !relatedChildContentQuery.isIncludeOfflineContent() )
{
compiled.setParameter( "status", ContentStatus.APPROVED.getKey() );
compiled.setParameter( "timeNow", relatedChildContentQuery.getNow().minuteOfHour().roundFloorCopy().toDate() );
}
final List<ContentVersionKey> contentVersionKeys = relatedChildContentQuery.getContentVersions();
for ( int i = 0; i < contentVersionKeys.size(); i++ )
{
compiled.setParameter( "cv" + i, contentVersionKeys.get( i ) );
}
if ( relatedChildContentQuery.hasSecurityFilter() )
{
compiled.setParameter( "one", 1 );
List<GroupKey> securityFilter = Lists.newArrayList( relatedChildContentQuery.getSecurityFilter() );
for ( int i = 0; i < securityFilter.size(); i++ )
{
compiled.setParameter( "g" + i, securityFilter.get( i ) );
}
}
@SuppressWarnings({"unchecked"}) List<Object[]> list = compiled.list();
final Set<ContentKey> contentKeys = new LinkedHashSet<ContentKey>( list.size() );
for ( Object[] row : list )
{
contentKeys.add( (ContentKey) row[1] );
}
final ContentMap contentMap = retrieveContent( contentKeys );
final List<RelatedChildContent> relatedChildContrents = new ArrayList<RelatedChildContent>();
for ( Object[] row : list )
{
ContentVersionKey versionKey = (ContentVersionKey) row[0];
ContentKey contentKey = (ContentKey) row[1];
ContentEntity content = contentMap.get( contentKey );
RelatedChildContent relatedChildContent = new RelatedChildContent( versionKey, content );
relatedChildContrents.add( relatedChildContent );
}
return relatedChildContrents;
}
private String getRelatedChildrenByKeyHQL( final RelatedChildContentQuery relatedChildContentQuery )
{
final SelectBuilder hqlQuery = new SelectBuilder( 0 );
hqlQuery.addSelect( "rc.key.parentContentVersionKey" );
hqlQuery.addSelectColumn( "c.key" );
hqlQuery.addFromTable( RelatedContentEntity.class.getName(), "rc", SelectBuilder.NO_JOIN, null );
hqlQuery.addFromTable( ContentEntity.class.getName(), "c", SelectBuilder.NO_JOIN, null );
hqlQuery.addFromTable( ContentVersionEntity.class.getName(), "mainVersion", SelectBuilder.NO_JOIN, null );
hqlQuery.addFilter( "AND", "rc.key.childContentKey = c.key" );
hqlQuery.addFilter( "AND", "mainVersion.key = c.mainVersion.key" );
hqlQuery.addFilter( "AND", new InClauseBuilder<ContentVersionKey>( "rc.key.parentContentVersionKey",
relatedChildContentQuery.getContentVersions() )
{
public void appendValue( final StringBuffer sql, final ContentVersionKey value )
{
sql.append( ":cv" ).append( getIndex() );
}
}.toString() );
if ( !relatedChildContentQuery.isIncludeOfflineContent() )
{
hqlQuery.addFilter( "AND", "mainVersion.status = :status" );
hqlQuery.addFilter( "AND", "c.availableFrom <= :timeNow" );
hqlQuery.addFilter( "AND", "(c.availableTo is null OR c.availableTo > :timeNow)" );
}
hqlQuery.addFilter( "AND", "c.deleted = :deleted" );
if ( relatedChildContentQuery.hasSecurityFilter() )
{
final SelectBuilder securitySubQuery = new SelectBuilder( 0 );
securitySubQuery.addSelect( "ca.content.key" );
securitySubQuery.addFromTable( ContentAccessEntity.class.getName(), "ca", SelectBuilder.NO_JOIN, null );
securitySubQuery.addFilter( "AND", "ca.readAccess = :one" );
securitySubQuery.addFilter( "AND", new InClauseBuilder<GroupKey>( "ca.group.key", relatedChildContentQuery.getSecurityFilter() )
{
public void appendValue( final StringBuffer sql, final GroupKey value )
{
sql.append( ":g" ).append( getIndex() );
}
}.toString() );
hqlQuery.append( "AND c.key IN ( " + securitySubQuery + " )" );
}
hqlQuery.addOrderBy( "c.createdAt" );
return hqlQuery.toString();
}
private ContentMap retrieveContent( final Set<ContentKey> contentKeys )
{
final FindContentByKeysQuerier findContentByKeysQuerier =
new FindContentByKeysQuerier( hibernateTemplate.getSessionFactory().getCurrentSession(), ContentEagerFetches.PRESET_FOR_PORTAL,
true );
final FindContentByKeysCommandExecutor commandExecutor =
new FindContentByKeysCommandExecutor( entityCache, hibernateTemplate, findContentByKeysQuerier );
return commandExecutor.execute( new ArrayList<ContentKey>( contentKeys ), false );
}
}