public static RangeEndpointCalculator<? extends Comparable<?>> create(RangeFacetRequest request) { final SchemaField sf = request.getField(); final FieldType ft = sf.getType(); final RangeEndpointCalculator<?> calc; if (ft instanceof TrieField) { final TrieField trie = (TrieField) ft; switch (trie.getType()) { case FLOAT: calc = new FloatRangeEndpointCalculator(request); break; case DOUBLE: calc = new DoubleRangeEndpointCalculator(request); break; case INTEGER: calc = new IntegerRangeEndpointCalculator(request); break; case LONG: calc = new LongRangeEndpointCalculator(request); break; default: throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Unable to range facet on tried field of unexpected type:" + sf.getName()); } } else if (ft instanceof DateField) { calc = new DateRangeEndpointCalculator(request, null); } else { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "Unable to range facet on field:" + sf); } return calc; }
public RangeEndpointCalculator(final RangeFacetRequest request) { this.field = request.getField(); this.request = request; }
public List<FacetRange> getRanges() { final T start = getValue(request.getStart()); T end = getValue(request.getEnd()); // not final, hardend may change this if (end.compareTo(start) < 0) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "range facet 'end' comes before 'start': " + end + " < " + start); } // explicitly return the gap. compute this early so we are more // likely to catch parse errors before attempting math final String[] gaps = request.getGaps(); String gap = gaps[0]; final EnumSet<FacetRangeInclude> include = request.getInclude(); T low = start; List<FacetRange> ranges = new ArrayList<FacetRange>(); int gapCounter = 0; while (low.compareTo(end) < 0) { if (gapCounter < gaps.length) { gap = gaps[gapCounter++]; } T high = addGap(low, gap); if (end.compareTo(high) < 0) { if (request.isHardEnd()) { high = end; } else { end = high; } } if (high.compareTo(low) < 0) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "range facet infinite loop (is gap negative? did the math overflow?)"); } if (high.compareTo(low) == 0) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "range facet infinite loop: gap is either zero, or too small relative start/end and caused underflow: " + low + " + " + gap + " = " + high); } final boolean includeLower = (include.contains(FacetRangeInclude.ALL) || include.contains(FacetRangeInclude.LOWER) || (include.contains(FacetRangeInclude.EDGE) && 0 == low.compareTo(start))); final boolean includeUpper = (include.contains(FacetRangeInclude.ALL) || include.contains(FacetRangeInclude.UPPER) || (include.contains(FacetRangeInclude.EDGE) && 0 == high.compareTo(end))); final String lowS = formatValue(low); final String highS = formatValue(high); ranges.add(new FacetRange(lowS, lowS, highS, includeLower, includeUpper)); low = high; } final Set<FacetRangeOther> others = request.getOthers(); if (null != others && 0 < others.size()) { // no matter what other values are listed, we don't do // anything if "none" is specified. if (!others.contains(FacetRangeOther.NONE)) { boolean all = others.contains(FacetRangeOther.ALL); if (all || others.contains(FacetRangeOther.BEFORE)) { // include upper bound if "outer" or if first gap doesn't already include it ranges.add( new FacetRange( FacetRangeOther.BEFORE.toString(), null, formatValue(start), false, include.contains(FacetRangeInclude.OUTER) || include.contains(FacetRangeInclude.ALL) || !(include.contains(FacetRangeInclude.LOWER) || include.contains(FacetRangeInclude.EDGE)))); } if (all || others.contains(FacetRangeOther.AFTER)) { // include lower bound if "outer" or if last gap doesn't already include it ranges.add( new FacetRange( FacetRangeOther.AFTER.toString(), formatValue(end), null, include.contains(FacetRangeInclude.OUTER) || include.contains(FacetRangeInclude.ALL) || !(include.contains(FacetRangeInclude.UPPER) || include.contains(FacetRangeInclude.EDGE)), false)); } if (all || others.contains(FacetRangeOther.BETWEEN)) { ranges.add( new FacetRange( FacetRangeOther.BETWEEN.toString(), formatValue(start), formatValue(end), include.contains(FacetRangeInclude.LOWER) || include.contains(FacetRangeInclude.EDGE) || include.contains(FacetRangeInclude.ALL), include.contains(FacetRangeInclude.UPPER) || include.contains(FacetRangeInclude.EDGE) || include.contains(FacetRangeInclude.ALL))); } } } return ranges; }