package org.apache.lucene.facet.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import org.apache.lucene.util.PriorityQueue;
import org.apache.lucene.facet.search.Heap;
import org.apache.lucene.facet.search.params.FacetRequest;
import org.apache.lucene.facet.search.params.FacetRequest.SortOrder;
import org.apache.lucene.facet.search.results.FacetResultNode;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
/**
* Utilities for generating facet results sorted as required
*
* @lucene.experimental
*/
public class ResultSortUtils {
/**
* Create a suitable heap according to facet request being served.
* @return heap for maintaining results for specified request.
* @throws IllegalArgumentException is provided facet request is not supported
*/
public static Heap<FacetResultNode> createSuitableHeap(FacetRequest facetRequest) {
int nresults = facetRequest.getNumResults();
boolean accending = (facetRequest.getSortOrder() == SortOrder.ASCENDING);
if (nresults == Integer.MAX_VALUE) {
return new AllValueHeap(accending);
}
if (accending) {
switch (facetRequest.getSortBy()) {
case VALUE:
return new MaxValueHeap(nresults);
case ORDINAL:
return new MaxOrdinalHeap(nresults);
}
} else {
switch (facetRequest.getSortBy()) {
case VALUE:
return new MinValueHeap(nresults);
case ORDINAL:
return new MinOrdinalHeap(nresults);
}
}
throw new IllegalArgumentException("none supported facet request: "+facetRequest);
}
private static class MinValueHeap extends PriorityQueue<FacetResultNode> implements Heap<FacetResultNode> {
public MinValueHeap(int size) {
super(size);
}
@Override
protected boolean lessThan(FacetResultNode arg0, FacetResultNode arg1) {
double value0 = arg0.getValue();
double value1 = arg1.getValue();
int valueCompare = Double.compare(value0, value1);
if (valueCompare == 0) {
return arg0.getOrdinal() < arg1.getOrdinal();
}
return valueCompare < 0;
}
}
private static class MaxValueHeap extends PriorityQueue<FacetResultNode> implements Heap<FacetResultNode> {
public MaxValueHeap(int size) {
super(size);
}
@Override
protected boolean lessThan(FacetResultNode arg0, FacetResultNode arg1) {
double value0 = arg0.getValue();
double value1 = arg1.getValue();
int valueCompare = Double.compare(value0, value1);
if (valueCompare == 0) {
return arg0.getOrdinal() > arg1.getOrdinal();
}
return valueCompare > 0;
}
}
private static class MinOrdinalHeap extends
PriorityQueue<FacetResultNode> implements Heap<FacetResultNode> {
public MinOrdinalHeap(int size) {
super(size);
}
@Override
protected boolean lessThan(FacetResultNode arg0, FacetResultNode arg1) {
return arg0.getOrdinal() < arg1.getOrdinal();
}
}
private static class MaxOrdinalHeap extends
PriorityQueue<FacetResultNode> implements Heap<FacetResultNode> {
public MaxOrdinalHeap(int size) {
super(size);
}
@Override
protected boolean lessThan(FacetResultNode arg0, FacetResultNode arg1) {
return arg0.getOrdinal() > arg1.getOrdinal();
}
}
/**
* Create a Heap-Look-Alike, which implements {@link Heap}, but uses a
* regular <code>ArrayList</code> for holding <b>ALL</b> the objects given,
* only sorting upon the first call to {@link #pop()}.
*/
private static class AllValueHeap implements Heap<FacetResultNode> {
private ArrayList<FacetResultNode> resultNodes = new ArrayList<FacetResultNode>();
final boolean accending;
private boolean isReady = false;
public AllValueHeap(boolean accending) {
this.accending = accending;
}
public FacetResultNode insertWithOverflow(FacetResultNode node) {
resultNodes.add(node);
return null;
}
public FacetResultNode pop() {
if (!isReady) {
Collections.sort(resultNodes, new Comparator<FacetResultNode>() {
public int compare(FacetResultNode o1, FacetResultNode o2) {
int value = Double.compare(o1.getValue(), o2
.getValue());
if (value == 0) {
value = o1.getOrdinal() - o2.getOrdinal();
}
if (accending) {
value = -value;
}
return value;
}
});
isReady = true;
}
return resultNodes.remove(0);
}
public int size() {
return resultNodes.size();
}
public FacetResultNode top() {
if (resultNodes.size() > 0) {
return resultNodes.get(0);
}
return null;
}
public FacetResultNode add(FacetResultNode frn) {
resultNodes.add(frn);
return null;
}
public void clear() {
resultNodes.clear();
}
}
}