/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.store.dao;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.hibernate.transform.ResultTransformer;
import org.springframework.stereotype.Repository;
import com.enonic.cms.framework.hibernate.support.SelectBuilder;
import com.enonic.cms.core.content.ContentEntity;
import com.enonic.cms.core.log.ContentLogEntrySpecification;
import com.enonic.cms.core.log.LogEntryEntity;
import com.enonic.cms.core.log.LogEntryKey;
import com.enonic.cms.core.log.LogEntrySpecification;
import com.enonic.cms.core.log.LogType;
import com.enonic.cms.core.log.Table;
@Repository("logEntryDao")
final class LogEntryEntityDao
extends AbstractBaseEntityDao<LogEntryEntity>
implements LogEntryDao
{
@SuppressWarnings({"unchecked"})
public List<LogEntryKey> findBySpecification( LogEntrySpecification specification, final String orderBy )
{
final String logEntryKeysHQL = getLogEntryKeysHQL( specification, orderBy );
Query compiled =
getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery( logEntryKeysHQL );
if ( specification.getDateFilter() != null )
{
compiled.setDate( "dateFilter", specification.getDateFilter() );
}
if ( specification.isDateSpanSet() )
{
specification.setDateSpanParameters( compiled );
}
compiled.setCacheable( true );
@SuppressWarnings({"unchecked"}) LogEntryResultTransformer transformer =
new LogEntryResultTransformer( specification.isAllowDuplicateEntries() );
return transformer.transformList( compiled.list() );
}
public LogEntryEntity findByKey( LogEntryKey key )
{
return get( LogEntryEntity.class, key );
}
private String getLogEntryKeysHQL( LogEntrySpecification specification, String orderBy )
{
final SelectBuilder hqlQuery = new SelectBuilder( 0 );
hqlQuery.addSelect( "le.key" );
hqlQuery.addSelectColumn( "le.keyValue" );
hqlQuery.addSelectColumn( "le.timestamp" );
hqlQuery.addFromTable( LogEntryEntity.class.getName(), "le", SelectBuilder.NO_JOIN, null );
if ( specification instanceof ContentLogEntrySpecification )
{
ContentLogEntrySpecification conSpecification = (ContentLogEntrySpecification) specification;
if ( !conSpecification.isAllowDeletedContent() )
{
applyNonDeletedContentOnlyFilter( specification, hqlQuery );
}
}
applyTableTypeFilter( specification, hqlQuery );
applyTypeFilter( specification, hqlQuery );
applyUserFilter( specification, hqlQuery );
applyDateFilter( specification, hqlQuery );
applyDateSpan( specification, hqlQuery );
String hql = hqlQuery.toString();
if ( StringUtils.isNotBlank( orderBy ) )
{
hqlQuery.addOrderBy( "le." + orderBy );
hql = hqlQuery.toString();
hql = hql + " GROUP BY ce.key";
}
return hql;
}
private void applyTableTypeFilter( LogEntrySpecification specification, SelectBuilder hqlQuery )
{
if ( specification.getTableTypes() != null && specification.getTableTypes().length > 0 )
{
hqlQuery.addFilter( "AND", "le.tableKey IN ( " + createLogTableTypeString( specification.getTableTypes() ) + " )" );
}
}
private void applyDateFilter( LogEntrySpecification specification, SelectBuilder hqlQuery )
{
if ( specification.getDateFilter() != null )
{
hqlQuery.addFilter( "AND", "le.timestamp > :dateFilter" );
}
}
private void applyDateSpan( LogEntrySpecification specification, SelectBuilder hqlQuery )
{
if ( specification.isDateSpanSet() )
{
specification.appendDateSpan( "le", hqlQuery );
}
}
private void applyNonDeletedContentOnlyFilter( LogEntrySpecification specification, SelectBuilder hqlQuery )
{
hqlQuery.addFromTable( ContentEntity.class.getName(), "ce", SelectBuilder.NO_JOIN, null );
hqlQuery.addFilter( "AND", "ce.key = le.keyValue" );
hqlQuery.addFilter( "AND", "ce.deleted = 0" );
}
private void applyUserFilter( LogEntrySpecification specification, SelectBuilder hqlQuery )
{
if ( specification.getUser() != null )
{
hqlQuery.addFilter( "AND", "le.user.key = '" + specification.getUser().getKey() + "'" );
}
}
private void applyTypeFilter( LogEntrySpecification specification, SelectBuilder hqlQuery )
{
if ( specification.getTypes() != null && specification.getTypes().length > 0 )
{
hqlQuery.addFilter( "AND", "le.type IN ( " + createLogTypesString( specification.getTypes() ) + " )" );
}
}
private String createLogTypesString( LogType[] types )
{
String typesString = "";
for ( int i = 0; i < types.length; i++ )
{
typesString += types[i].asInteger();
if ( ( i + 1 ) != types.length )
{
typesString += ",";
}
}
return typesString;
}
private String createLogTableTypeString( Table[] tableTypes )
{
String typesString = "";
for ( int i = 0; i < tableTypes.length; i++ )
{
typesString += tableTypes[i].asInteger();
if ( ( i + 1 ) != tableTypes.length )
{
typesString += ",";
}
}
return typesString;
}
}
final class LogEntryResultTransformer
implements ResultTransformer
{
private boolean allowDuplicates;
public LogEntryResultTransformer( boolean duplicates )
{
allowDuplicates = duplicates;
}
@SuppressWarnings("unchecked")
public List<LogEntryKey> transformList( List list )
{
if ( !allowDuplicates )
{
return nonDuplicateEntries( list );
}
return duplicateEntries( list );
}
private List<LogEntryKey> duplicateEntries( List list )
{
List<LogEntryKey> keysList = new ArrayList<LogEntryKey>();
for ( Object object : list )
{
Object[] row = (Object[]) object;
LogEntryKey key = (LogEntryKey) row[0];
keysList.add( key );
}
return keysList;
}
private List<LogEntryKey> nonDuplicateEntries( List list )
{
List<LogEntryKey> distinctList = new ArrayList<LogEntryKey>();
Set<Integer> added = new HashSet<Integer>();
for ( Object object : list )
{
Object[] row = (Object[]) object;
LogEntryKey key = (LogEntryKey) row[0];
Integer contentKey = (Integer) row[1];
if ( !isAlreadyAdded( contentKey, added ) )
{
distinctList.add( key );
added.add( contentKey );
}
}
return distinctList;
}
public Object transformTuple( Object[] arg0, String[] arg1 )
{
throw new IllegalStateException( "Not implemented" );
}
private boolean isAlreadyAdded( Integer key, Set<Integer> added )
{
return added.contains( key );
}
}