/*
* Copyright 2005 Joe Walker
*
* 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 org.directwebremoting.datasync;
import java.util.Comparator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.directwebremoting.io.SortCriterion;
import org.directwebremoting.util.LocalUtil;
/**
* A {@link Comparator} that uses a list of {@link SortCriterion} to decide
* how to sort the beans. Values to sort by are extracted using an implementation
* of {@link AttributeValueExtractor},.
* @author Joe Walker [joe at getahead dot ltd dot uk]
*/
public class SortCriteriaComparator<T> implements Comparator<T>
{
/**
* All SortCriteriaComparators need a set of things to sort on and a way to
* get the values to sort
*/
public SortCriteriaComparator(List<SortCriterion> sort, ComparatorFactory<T> comparatorFactory)
{
this.sort = sort;
this.comparatorFactory = comparatorFactory;
}
/* (non-Javadoc)
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(T object1, T object2)
{
if (object1 == null)
{
if (object2 == null)
{
return 0;
}
else
{
return -1;
}
}
else
{
if (object2 == null)
{
return 1;
}
}
if (object1.getClass() != object2.getClass())
{
log.warn("Classes don't match. Results could be unpredictable: " + object1.getClass() + " / " + object2.getClass());
}
try
{
for (SortCriterion criterion : sort)
{
Comparator<? super T> comparator = comparatorFactory.getComparator(criterion.getAttribute(), criterion.isAscending());
int comparison = comparator.compare(object1, object2);
if (comparison != 0)
{
return comparison;
}
}
}
catch (Exception ex)
{
log.warn("Failure while sorting objects", ex);
}
// So we can't tell them apart by comparing them - we can't return 0
// unless they are equal, so we need to do something determinate
if (object1.equals(object2))
{
return 0;
}
int hash1 = object1.hashCode();
int hash2 = object2.hashCode();
return LocalUtil.shrink(hash1 - hash2);
}
/**
* The way to extract values to sort on
*/
private final ComparatorFactory<T> comparatorFactory;
/**
* The sort criteria
*/
private final List<SortCriterion> sort;
/**
* The log stream
*/
private static final Log log = LogFactory.getLog(SortCriteriaComparator.class);
}