From 679c3c8de8d933fb5edb551af93bceb53a456a53 Mon Sep 17 00:00:00 2001 From: Robert Muir Date: Wed, 15 Jan 2014 19:44:06 +0000 Subject: [PATCH] LUCENE-5399: remove code duplication git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene539399@1558552 13f79535-47bb-0310-9956-ffa450edef68 --- .../MissingStringLastComparatorSource.java | 301 ------------------ .../java/org/apache/solr/search/Sorting.java | 29 +- 2 files changed, 18 insertions(+), 312 deletions(-) delete mode 100644 solr/core/src/java/org/apache/solr/search/MissingStringLastComparatorSource.java diff --git a/solr/core/src/java/org/apache/solr/search/MissingStringLastComparatorSource.java b/solr/core/src/java/org/apache/solr/search/MissingStringLastComparatorSource.java deleted file mode 100644 index 977adc511c6..00000000000 --- a/solr/core/src/java/org/apache/solr/search/MissingStringLastComparatorSource.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * 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. - */ - -package org.apache.solr.search; - -import java.io.IOException; - -import org.apache.lucene.index.AtomicReader; -import org.apache.lucene.index.AtomicReaderContext; -import org.apache.lucene.index.SortedDocValues; -import org.apache.lucene.search.FieldCache; -import org.apache.lucene.search.FieldComparator; -import org.apache.lucene.search.FieldComparatorSource; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.UnicodeUtil; -import org.apache.lucene.util.packed.PackedInts; - - -public class MissingStringLastComparatorSource extends FieldComparatorSource { - private final BytesRef missingValueProxy; - - public MissingStringLastComparatorSource() { - this(UnicodeUtil.BIG_TERM); - } - - /** Creates a {@link FieldComparatorSource} that sorts null last in a normal ascending sort. - * missingValueProxy as the value to return from FieldComparator.value() - * - * @param missingValueProxy The value returned when sortValue() is called for a document missing the sort field. - * This value is *not* normally used for sorting. - */ - public MissingStringLastComparatorSource(BytesRef missingValueProxy) { - this.missingValueProxy=missingValueProxy; - } - - @Override - public FieldComparator newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException { - return new TermOrdValComparator_SML(numHits, fieldname, sortPos, reversed, missingValueProxy); - } - -} - -// Copied from Lucene's TermOrdValComparator and modified since the Lucene version couldn't -// be extended. -class TermOrdValComparator_SML extends FieldComparator { - private static final int NULL_ORD = Integer.MAX_VALUE-1; - - private final int[] ords; - private final BytesRef[] values; - private final int[] readerGen; - - private SortedDocValues termsIndex; - private final String field; - - private final BytesRef NULL_VAL; - private PerSegmentComparator current; - - public TermOrdValComparator_SML(int numHits, String field, int sortPos, boolean reversed, BytesRef nullVal) { - ords = new int[numHits]; - values = new BytesRef[numHits]; - readerGen = new int[numHits]; - this.field = field; - this.NULL_VAL = nullVal; - } - - @Override - public int compare(int slot1, int slot2) { - throw new UnsupportedOperationException(); - } - - @Override - public void setBottom(int slot) { - throw new UnsupportedOperationException(); - } - - @Override - public void setTopValue(Comparable value) { - throw new UnsupportedOperationException(); - } - - @Override - public int compareBottom(int doc) { - throw new UnsupportedOperationException(); - } - - @Override - public void copy(int slot, int doc) { - throw new UnsupportedOperationException(); - } - - @Override - public BytesRef value(int slot) { - throw new UnsupportedOperationException(); - } - - @Override - public int compareValues(Comparable first, Comparable second) { - if (first == null) { - if (second == null) { - return 0; - } else { - return 1; - } - } else if (second == null) { - return -1; - } else { - return first.compareTo(second); - } - } - - @Override - public FieldComparator setNextReader(AtomicReaderContext context) throws IOException { - return TermOrdValComparator_SML.createComparator(context.reader(), this); - } - - @Override - public int compareTop(int doc) { - throw new UnsupportedOperationException(); - } - - // Base class for specialized (per bit width of the - // ords) per-segment comparator. NOTE: this is messy; - // we do this only because hotspot can't reliably inline - // the underlying array access when looking up doc->ord - private static abstract class PerSegmentComparator extends FieldComparator { - protected TermOrdValComparator_SML parent; - protected final int[] ords; - protected final BytesRef[] values; - protected final int[] readerGen; - - protected int currentReaderGen = -1; - protected SortedDocValues termsIndex; - - protected int bottomSlot = -1; - protected int bottomOrd; - protected boolean bottomSameReader = false; - protected BytesRef bottomValue; - protected final BytesRef tempBR = new BytesRef(); - - - public PerSegmentComparator(TermOrdValComparator_SML parent) { - this.parent = parent; - PerSegmentComparator previous = parent.current; - if (previous != null) { - currentReaderGen = previous.currentReaderGen; - bottomSlot = previous.bottomSlot; - bottomOrd = previous.bottomOrd; - bottomValue = previous.bottomValue; - } - ords = parent.ords; - values = parent.values; - readerGen = parent.readerGen; - termsIndex = parent.termsIndex; - currentReaderGen++; - } - - @Override - public FieldComparator setNextReader(AtomicReaderContext context) throws IOException { - return TermOrdValComparator_SML.createComparator(context.reader(), parent); - } - - @Override - public void setTopValue(BytesRef value) { - throw new UnsupportedOperationException(); - } - - @Override - public int compare(int slot1, int slot2) { - if (readerGen[slot1] == readerGen[slot2]) { - return ords[slot1] - ords[slot2]; - } - - final BytesRef val1 = values[slot1]; - final BytesRef val2 = values[slot2]; - if (val1 == null) { - if (val2 == null) { - return 0; - } - return 1; - } else if (val2 == null) { - return -1; - } - return val1.compareTo(val2); - } - - @Override - public void setBottom(final int bottom) { - bottomSlot = bottom; - - bottomValue = values[bottomSlot]; - if (currentReaderGen == readerGen[bottomSlot]) { - bottomOrd = ords[bottomSlot]; - bottomSameReader = true; - } else { - if (bottomValue == null) { - // -1 ord is null for all segments - assert ords[bottomSlot] == NULL_ORD; - bottomOrd = NULL_ORD; - bottomSameReader = true; - readerGen[bottomSlot] = currentReaderGen; - } else { - final int index = termsIndex.lookupTerm(bottomValue); - if (index < 0) { - bottomOrd = -index - 2; - bottomSameReader = false; - } else { - bottomOrd = index; - // exact value match - bottomSameReader = true; - readerGen[bottomSlot] = currentReaderGen; - ords[bottomSlot] = bottomOrd; - } - } - } - } - - @Override - public BytesRef value(int slot) { - return values==null ? parent.NULL_VAL : values[slot]; - } - - // this stuff caches the ordinal of the last 'value' from compareDocToValue - BytesRef lastValue = new BytesRef(); // sentinel - int lastOrd; - int lastReaderGen = -1; - boolean lastSameReader = false; - - // nocommit, broken: nuke all of this - @Override - public int compareTop(int doc) { - throw new UnsupportedOperationException(); - } - } - - private static final class AnyOrdComparator extends PerSegmentComparator { - public AnyOrdComparator(TermOrdValComparator_SML parent) { - super(parent); - } - - @Override - public int compareBottom(int doc) { - assert bottomSlot != -1; - int docOrd = termsIndex.getOrd(doc); - if (docOrd == -1) docOrd = NULL_ORD; - if (bottomSameReader) { - // ord is precisely comparable, even in the equal case - return bottomOrd - docOrd; - } else if (bottomOrd >= docOrd) { - // the equals case always means bottom is > doc - // (because we set bottomOrd to the lower bound in - // setBottom): - return 1; - } else { - return -1; - } - } - - @Override - public void copy(int slot, int doc) { - int ord = termsIndex.getOrd(doc); - if (ord == -1) { - ords[slot] = NULL_ORD; - values[slot] = null; - } else { - ords[slot] = ord; - assert ord >= 0; - if (values[slot] == null) { - values[slot] = new BytesRef(); - } - termsIndex.lookupOrd(ord, values[slot]); - } - readerGen[slot] = currentReaderGen; - } - } - - public static FieldComparator createComparator(AtomicReader reader, TermOrdValComparator_SML parent) throws IOException { - parent.termsIndex = FieldCache.DEFAULT.getTermsIndex(reader, parent.field); - PerSegmentComparator perSegComp = new AnyOrdComparator(parent); - - if (perSegComp.bottomSlot != -1) { - perSegComp.setBottom(perSegComp.bottomSlot); - } - - parent.current = perSegComp; - return perSegComp; - } -} diff --git a/solr/core/src/java/org/apache/solr/search/Sorting.java b/solr/core/src/java/org/apache/solr/search/Sorting.java index 535309b7493..bacf1c7c235 100644 --- a/solr/core/src/java/org/apache/solr/search/Sorting.java +++ b/solr/core/src/java/org/apache/solr/search/Sorting.java @@ -40,18 +40,25 @@ public class Sorting { * @return SortField */ public static SortField getStringSortField(String fieldName, boolean reverse, boolean nullLast, boolean nullFirst) { - if (nullLast) { - if (!reverse) return new SortField(fieldName, nullStringLastComparatorSource); - else return new SortField(fieldName, SortField.Type.STRING, true); - } else if (nullFirst) { - if (reverse) return new SortField(fieldName, nullStringLastComparatorSource, true); - else return new SortField(fieldName, SortField.Type.STRING, false); - } else { - return new SortField(fieldName, SortField.Type.STRING, reverse); + if (nullFirst && nullLast) { + throw new IllegalArgumentException("Cannot specify missing values as both first and last"); } + + SortField sortField = new SortField(fieldName, SortField.Type.STRING, reverse); + + // 4 cases: + // missingFirst / forward: default lucene behavior + // missingFirst / reverse: set sortMissingLast + // missingLast / forward: set sortMissingLast + // missingLast / reverse: default lucene behavior + + if (nullFirst && reverse) { + sortField.setMissingValue(SortField.STRING_LAST); + } else if (nullLast && !reverse) { + sortField.setMissingValue(SortField.STRING_LAST); + } + + return sortField; } - - - static final FieldComparatorSource nullStringLastComparatorSource = new MissingStringLastComparatorSource(null); }