/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.upgrade.task;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import com.enonic.cms.upgrade.UpgradeContext;
final class UpgradeModel0208
extends AbstractUpgradeTask
{
@Override
protected boolean canModelUpgrade( UpgradeContext context )
{
context.logInfo( "Looking for duplicate users in database..." );
context.logInfo( "Duplicates user are found if more than one user resides in a user-store with same sync value" );
List<Pair> duplicates;
SyncValueColumn syncValueColumn;
try
{
boolean isSyncValue2 = context.columnExist( "tUser", "usr_sSyncValue2" );
syncValueColumn = isSyncValue2 ? SyncValueColumn.SYNCVALUE2 : SyncValueColumn.SYNCVALUE;
duplicates =
(List<Pair>) context.getJdbcTemplate().query( syncValueColumn.getQuery(), new UserPropertyExtractor( syncValueColumn ) );
}
catch ( Exception ex )
{
context.logError( ex.getMessage(), ex );
return false;
}
if ( duplicates.isEmpty() )
{
context.logInfo( "Upgrade check ok." );
return true;
}
context.logInfo( "Duplicate users found:" );
for ( Pair duplicate : duplicates )
{
final String message =
"\nusr_dom_lKey = " + duplicate.getDomKey() + ", " + syncValueColumn.getName() + " = '" + duplicate.getSyncValue() + "', " +
"SELECT SQL: SELECT * FROM tuser WHERE usr_dom_lKey = " + duplicate.getDomKey() + " AND " + syncValueColumn.getName() +
" = '" +
duplicate.getSyncValue() + "'";
context.logInfo( message );
}
context.logInfo( "Please use the generated SELECT SQL to identify each duplicated user." );
context.logInfo( "Then set the " + syncValueColumn.getName() + " of the user that is no longer needed to something unique." );
return false;
}
public UpgradeModel0208()
{
super( 208 );
}
public void upgrade( final UpgradeContext context )
throws Exception
{
if ( context.columnExist( "tUser", "usr_sSyncValue2" ) )
{
context.logInfo( "'tUser.usr_sSyncValue2' is already exists. Skipping." );
return;
}
context.logInfo( "Adding new column 'usr_sSyncValue2' to table 'tUser'" );
context.getJdbcTemplate().execute( "ALTER TABLE tUser ADD usr_sSyncValue2 @varchar(255)@ DEFAULT '-' NOT NULL" );
context.reorganizeTablesForDb2( "tUser" );
}
private enum SyncValueColumn
{
SYNCVALUE
{
String getQuery()
{
StringBuilder sb = new StringBuilder();
sb.append( "select usr_dom_lKey, usr_sSyncValue " );
sb.append( "from tUser " );
// to exclude 1) Admin user, 2) Anonymous user, 3) users in Local User Store
sb.append(
"WHERE NOT ( (usr_dom_lkey IN (SELECT dom_lkey FROM tDomain WHERE dom_sconfigname is null OR dom_sconfigname = '')) OR (USR_UT_LKEY IN ( 1, 2 )) ) " );
sb.append( "group by usr_dom_lKey, usr_sSyncValue HAVING (COUNT(usr_sSyncValue) > 1) " );
return sb.toString();
}
String getName()
{
return "usr_sSyncValue";
}
},
SYNCVALUE2
{
String getQuery()
{
StringBuilder sb = new StringBuilder();
sb.append( "select usr_dom_lKey, usr_sSyncValue2 " );
sb.append( "from tUser " );
// to exclude 1) Admin user, 2) Anonymous user, 3) users in Local User Store
sb.append(
"WHERE NOT ( (usr_dom_lkey IN (SELECT dom_lkey FROM tDomain WHERE dom_sconfigname is null OR dom_sconfigname = '')) OR (USR_UT_LKEY IN ( 1, 2 )) ) " );
sb.append( "group by usr_dom_lKey, usr_sSyncValue2 HAVING (COUNT(usr_sSyncValue2) > 1) " );
return sb.toString();
}
String getName()
{
return "usr_sSyncValue2";
}
};
abstract String getQuery();
abstract String getName();
}
private class UserPropertyExtractor
implements ResultSetExtractor
{
private SyncValueColumn syncValueColumn;
private UserPropertyExtractor( final SyncValueColumn syncValueColumn )
{
this.syncValueColumn = syncValueColumn;
}
public Object extractData( ResultSet rs )
throws SQLException, DataAccessException
{
List<Pair> duplicates = new ArrayList<Pair>();
while ( rs.next() )
{
String domKey = rs.getString( "usr_dom_lKey" );
String syncValue = rs.getString( syncValueColumn.getName() );
duplicates.add( new Pair( domKey, syncValue ) );
}
return duplicates;
}
}
private class Pair
{
private String domKey;
private String syncValue;
private Pair( String domKey, String syncValue )
{
this.domKey = domKey;
this.syncValue = syncValue;
}
public String getDomKey()
{
return domKey;
}
public String getSyncValue()
{
return syncValue;
}
}
}