All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.helger.commons.compare.AbstractComparator Maven / Gradle / Ivy

/**
 * Copyright (C) 2014-2015 Philip Helger (www.helger.com)
 * philip[at]helger[dot]com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.helger.commons.compare;

import java.util.Comparator;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;

import com.helger.commons.ValueEnforcer;
import com.helger.commons.string.ToStringGenerator;

/**
 * Abstract comparator class that supports a sort order and a nested comparator.
 *
 * @author Philip Helger
 * @param 
 *        The data type to be compared
 */
@NotThreadSafe
public abstract class AbstractComparator  implements ISerializableComparator 
{
  private ESortOrder m_eSortOrder = ESortOrder.DEFAULT;
  private boolean m_bNullValuesComeFirst = CompareHelper.DEFAULT_NULL_VALUES_COME_FIRST;
  private Comparator  m_aNestedComparator;

  /**
   * Comparator with default sort order and no nested comparator.
   */
  public AbstractComparator ()
  {}

  /**
   * @return The currently assigned sort order. Never null.
   */
  @Nonnull
  public final ESortOrder getSortOrder ()
  {
    return m_eSortOrder;
  }

  /**
   * Call this to enable sorting after the constructor was invoked.
   *
   * @param eSortOrder
   *        The sort order to use. May not be null.
   * @return this
   */
  @Nonnull
  public final AbstractComparator  setSortOrder (@Nonnull final ESortOrder eSortOrder)
  {
    m_eSortOrder = ValueEnforcer.notNull (eSortOrder, "SortOrder");
    return this;
  }

  /**
   * @return true if null values are to be ordered
   *         before non-null values, false if
   *         null are to be sorted after non-null
   *         values.
   */
  public final boolean isNullValuesComeFirst ()
  {
    return m_bNullValuesComeFirst;
  }

  /**
   * Change the sort position of null values.
   *
   * @param bNullValuesComeFirst
   *        true if null values should come first,
   *        false if null values should go last.
   * @return this
   */
  @Nonnull
  public final AbstractComparator  setNullValuesComeFirst (final boolean bNullValuesComeFirst)
  {
    m_bNullValuesComeFirst = bNullValuesComeFirst;
    return this;
  }

  /**
   * @return The nested comparator. May be null.
   */
  @Nonnull
  public final Comparator  getNestedComparator ()
  {
    return m_aNestedComparator;
  }

  /**
   * Set a nested comparator to be invoked if the comparison result of this
   * comparator is 0.
   *
   * @param aNestedComparator
   *        The nested comparator to be invoked, when the main comparison
   *        resulted in 0. May be null.
   * @return this
   */
  @Nonnull
  public final AbstractComparator  setNestedComparator (@Nullable final Comparator  aNestedComparator)
  {
    m_aNestedComparator = aNestedComparator;
    return this;
  }

  /**
   * @param aElement1
   *        First element to compare. Never null.
   * @param aElement2
   *        Second element to compare. Never null.
   * @return a negative integer, zero, or a positive integer as the first
   *         argument is less than, equal to, or greater than the second.
   */
  protected abstract int mainCompare (@Nonnull final DATATYPE aElement1, @Nonnull final DATATYPE aElement2);

  public final int compare (final DATATYPE aElement1, final DATATYPE aElement2)
  {
    int nCompare;
    if (aElement1 == aElement2)
    {
      // The same object
      nCompare = 0;
    }
    else
      if (aElement1 == null)
      {
        // First element is null
        nCompare = m_bNullValuesComeFirst ? -1 : +1;
      }
      else
        if (aElement2 == null)
        {
          // Second element is null
          nCompare = m_bNullValuesComeFirst ? +1 : -1;
        }
        else
        {
          // Both are not null - compare
          nCompare = mainCompare (aElement1, aElement2);
        }

    // Invoke the nested comparator for 2nd level comparison (if any)
    // The nested comparator may have another nested comparator etc.
    if (nCompare == 0 && m_aNestedComparator != null)
    {
      nCompare = m_aNestedComparator.compare (aElement1, aElement2);
    }

    // Apply sort order by switching the sign of the return value
    return m_eSortOrder.isAscending () ? nCompare : -nCompare;
  }

  @Override
  public String toString ()
  {
    return new ToStringGenerator (this).append ("sortOrder", m_eSortOrder)
                                       .append ("nullValuesComeFirst", m_bNullValuesComeFirst)
                                       .appendIfNotNull ("nestedComparator", m_aNestedComparator)
                                       .toString ();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy