class Order {

    public int compare( Object lside, Object rside )
    {
        Object o1 = ReflectionUtils.invokeMethod( lside, property.getGetterMethod() );
        Object o2 = ReflectionUtils.invokeMethod( rside, property.getGetterMethod() );

        if ( o1 == o2 )
        {
            return 0;
        }

        // for null values use the same order like PostgreSQL in order to have same effect like DB ordering
        // (NULLs are greater than other values)
        if ( o1 == null || o2 == null )
        {
            if ( o1 == null )
            {
                return isAscending() ? 1 : -1;
            }
            return isAscending() ? -1 : 1;
        }

        if ( String.class.isInstance( o1 ) && String.class.isInstance( o2 ) )
        {
            String value1 = ignoreCase ? ((String) o1).toLowerCase() : (String) o1;
            String value2 = ignoreCase ? ((String) o2).toLowerCase() : (String) o2;

            return isAscending() ? value1.compareTo( value2 ) : value2.compareTo( value1 );
        }
        if ( Boolean.class.isInstance( o1 ) && Boolean.class.isInstance( o2 ) )
        {
            return isAscending() ? ((Boolean) o1).compareTo( (Boolean) o2 ) : ((Boolean) o2).compareTo( (Boolean) o1 );
        }
        else if ( Integer.class.isInstance( o1 ) && Integer.class.isInstance( o2 ) )
        {
            return isAscending() ? ((Integer) o1).compareTo( (Integer) o2 ) : ((Integer) o2).compareTo( (Integer) o1 );
        }
        else if ( Float.class.isInstance( o1 ) && Float.class.isInstance( o2 ) )
        {
            return isAscending() ? ((Float) o1).compareTo( (Float) o2 ) : ((Float) o2).compareTo( (Float) o1 );
        }
        else if ( Double.class.isInstance( o1 ) && Double.class.isInstance( o2 ) )
        {
            return isAscending() ? ((Double) o1).compareTo( (Double) o2 ) : ((Double) o2).compareTo( (Double) o1 );
        }
        else if ( Date.class.isInstance( o1 ) && Date.class.isInstance( o2 ) )
        {
            return isAscending() ? ((Date) o1).compareTo( (Date) o2 ) : ((Date) o2).compareTo( (Date) o1 );
        }
        else if ( Enum.class.isInstance( o1 ) && Enum.class.isInstance( o2 ) )
        {
            return isAscending() ? String.valueOf( o1 ).compareTo( String.valueOf( o2 ) ) : String.valueOf( o2 ).compareTo( String.valueOf( o1 ) );
        }

        return 0;
    }

    public  Order( Property property, Direction direction );

}