/**
* Copyright 2008 the original author or authors.
*
* 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 net.sf.katta.lib.lucene;
import java.util.Comparator;
import net.sf.katta.util.WritableType;
import org.apache.lucene.search.SortField;
/**
* Implementation of an {@link Comparator} that compares two {@link Hit} objects
* based on a given {@link Sort} specification. This comparator helps sorting a
* result list by field terms rather then by sore.
*
* This code leans on the lucene code from {@link FieldSortedHitQueue}
*
*/
@SuppressWarnings("unchecked")
class FieldSortComparator implements Comparator<Hit> {
private static Comparator<Comparable> COMPARABLE_COMPARATOR = new ComparableComparator();
private static Comparator<Comparable> REVERSED_COMPARABLE_COMPARATOR = new ComparableComparator(true);
private final SortField[] _sortFields;
private final WritableType[] _fieldTypes;
private final Comparator<Comparable>[] _fieldComparators;
public FieldSortComparator(SortField[] sortFields, WritableType[] fieldTypes) {
_sortFields = sortFields;
_fieldTypes = fieldTypes;
_fieldComparators = new Comparator[sortFields.length];
// prepare a array of comparators, for each field one. For type-information
// we use the user provided SortField[] and the WritableType[] which are
// auto-detected on the node side.
for (int i = 0; i < sortFields.length; i++) {
if (_fieldTypes[i] == WritableType.TEXT && sortFields[i].getLocale() != null) {
throw new UnsupportedOperationException("locale-sensitive field sort currently not supported");
// jz: therefore we could use java.text.Collator class (see lucenes
// FieldSortedHitQueue)
} else if (sortFields[i].getType() == SortField.CUSTOM) {
throw new UnsupportedOperationException("custom field sort currently not supported");
}
if (_sortFields[i].getType() == SortField.SCORE) {
_fieldComparators[i] = REVERSED_COMPARABLE_COMPARATOR;
} else {
_fieldComparators[i] = COMPARABLE_COMPARATOR;
}
}
}
public SortField[] getSortFields() {
return _sortFields;
}
public WritableType[] getFieldTypes() {
return _fieldTypes;
}
@Override
public int compare(Hit hit1, Hit hit2) {
int c = compare(hit1.getSortFields(), hit2.getSortFields());
if (c == 0) {
c = hit1.compareTo(hit2);
}
return c;
}
public int compare(Object[] fields1, Object[] fields2) {
int n = _sortFields.length;
int c = 0;
for (int i = 0; i < n && c == 0; ++i) {
Comparable fieldTerm1 = (Comparable) fields1[i];
Comparable fieldTerm2 = (Comparable) fields2[i];
c = (_sortFields[i].getReverse()) ? _fieldComparators[i].compare(fieldTerm2, fieldTerm1) : _fieldComparators[i]
.compare(fieldTerm1, fieldTerm2);
}
return c;
}
static class ComparableComparator implements Comparator<Comparable> {
private final boolean _reverse;
public ComparableComparator() {
this(false);
}
public ComparableComparator(boolean reverse) {
_reverse = reverse;
}
@Override
public int compare(Comparable o1, Comparable o2) {
if (_reverse) {
return o2.compareTo(o1);
}
return o1.compareTo(o2);
}
}
}