ExternalUserComparator.java
/*
* Copyright (c) 2002-2024, City of Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.plugins.workflow.modules.ticketing.business.externaluser;
import java.io.Serializable;
import java.util.Comparator;
import org.apache.commons.lang.StringUtils;
/**
* Comparator for ExternalUser
*/
public class ExternalUserComparator implements Comparator<ExternalUser>, Serializable
{
/**
*
*/
private static final long serialVersionUID = -4877792520955232251L;
/**
* {@inheritDoc}
*/
@Override
public int compare( ExternalUser o1, ExternalUser o2 )
{
int nCompare = 0;
nCompare = compareAlphaNumeric( o1.getAdditionalAttribute( ), o2.getAdditionalAttribute( ), nCompare );
nCompare = compareAlphaNumeric( o1.getLastname( ), o2.getLastname( ), nCompare );
nCompare = compareAlphaNumeric( o1.getFirstname( ), o2.getFirstname( ), nCompare );
nCompare = compareAlphaNumeric( o1.getEmail( ), o2.getEmail( ), nCompare );
return nCompare;
}
/**
* return true if the character is numeric
*
* @param cDigit
* a character
* @return true if the character is numeric
*/
private boolean isDigit( char cDigit )
{
return ( cDigit >= 48 ) && ( cDigit <= 57 );
}
/**
* Length of string is passed in for improved efficiency (only need to calculate it once)
*
* @param strCompare
* original string
* @param nStrLength
* size of the given string
* @param nCurrentMarker
* current position in the given String
* @return substring to compare
*/
private String getChunk( String strCompare, int nStrLength, int nCurrentMarker )
{
StringBuilder strChunk = new StringBuilder( );
int nMarker = nCurrentMarker;
char c = strCompare.charAt( nMarker );
strChunk.append( c );
nMarker++;
if ( isDigit( c ) )
{
while ( nMarker < nStrLength )
{
c = strCompare.charAt( nMarker );
if ( !isDigit( c ) )
{
break;
}
strChunk.append( c );
nMarker++;
}
}
else
{
while ( nMarker < nStrLength )
{
c = strCompare.charAt( nMarker );
if ( isDigit( c ) )
{
break;
}
strChunk.append( c );
nMarker++;
}
}
return strChunk.toString( );
}
/**
* compare with natural order two string if nCurrentCompare is equal to 0 null/empty string have to be at 'the bottom' of the list
*
* @param str1
* , first string to compare
* @param str2
* , second string to compare
* @param nCurrentCompare
* , current compare value
* @return comparison value
*/
private int compareAlphaNumeric( String str1, String str2, int nCurrentCompare )
{
if ( nCurrentCompare != 0 )
{
return nCurrentCompare;
}
int nCompare = 0;
if ( StringUtils.isEmpty( str1 ) )
{
if ( StringUtils.isEmpty( str2 ) )
{
return 0;
}
else
{
nCompare = 1;
}
}
else
if ( StringUtils.isEmpty( str2 ) )
{
nCompare = -1;
}
if ( nCompare != 0 )
{
return nCompare;
}
int nMarker1 = 0;
int nMarker2 = 0;
int nLength1 = str1.length( );
int nLength2 = str2.length( );
while ( ( nMarker1 < nLength1 ) && ( nMarker2 < nLength2 ) )
{
String strChunk1 = getChunk( str1, nLength1, nMarker1 );
nMarker1 += strChunk1.length( );
String strChunk2 = getChunk( str2, nLength2, nMarker2 );
nMarker2 += strChunk2.length( );
// If both chunks contain numeric characters, sort them numerically
if ( isDigit( strChunk1.charAt( 0 ) ) && isDigit( strChunk2.charAt( 0 ) ) )
{
// Simple chunk comparison by length.
int thisChunkLength = strChunk1.length( );
nCompare = thisChunkLength - strChunk2.length( );
// If equal, the first different number counts
if ( nCompare == 0 )
{
for ( int i = 0; i < thisChunkLength; i++ )
{
nCompare = strChunk1.charAt( i ) - strChunk2.charAt( i );
if ( nCompare != 0 )
{
break;
}
}
}
}
else
if ( isDigit( strChunk1.charAt( 0 ) ) )
{
// in this case strChunk2 is not numeric
nCompare = 1;
}
else
{
// in this case both are string
nCompare = strChunk1.compareTo( strChunk2 );
}
if ( nCompare != 0 )
{
return nCompare;
}
}
return nLength1 - nLength2;
}
}