class DatawaveFieldIndexRangeIteratorJexl extends DatawaveFieldIndexCachingIteratorJexl {

    @Override
    protected List<Range> buildBoundingFiRanges(Text rowId, Text fiName, Text fieldValue) {
        if (ANY_FINAME.equals(fiName)) {
            Key startKey = new Key(rowId, FI_START);
            Key endKey = new Key(rowId, FI_END);
            return new RangeSplitter(new Range(startKey, true, endKey, false), getMaxRangeSplit());
        } else if (subRanges != null && !subRanges.isEmpty()) {
            List<Range> ranges = new ArrayList<>();
            
            // Note: The IndexRangeIteratorBuilder hard codes 'negated' to false, so unless that changes, this logic will never be executed.
            if (isNegated()) {
                Key startFi = new Key(rowId, fiName);
                Key endFi = new Key(rowId, new Text(fiName.toString() + '\0'));
                
                Key startKey = startFi;
                for (Range subRange : subRanges) {
                    Range range = new Range(startKey, true,
                                    createUpperBoundKey(rowId, fiName, subRange.getStartKey().getRow(), !subRange.isStartKeyInclusive()), true);
                    startKey = createLowerBoundKey(rowId, fiName, subRange.getEndKey().getRow(), !subRange.isEndKeyInclusive());
                    ranges.add(range);
                }
                
                // add the final range
                ranges.add(new Range(startKey, true, endFi, true));
            } else {
                for (Range subRange : subRanges) {
                    Key startKey = createLowerBoundKey(rowId, fiName, subRange.getStartKey().getRow(), subRange.isStartKeyInclusive());
                    Key endKey = createUpperBoundKey(rowId, fiName, subRange.getEndKey().getRow(), subRange.isEndKeyInclusive());
                    ranges.add(new Range(startKey, true, endKey, true));
                }
            }
            
            return ranges;
        } else {
            Key startKey = createLowerBoundKey(rowId, fiName, fieldValue, lowerInclusive);
            Key endKey = createUpperBoundKey(rowId, fiName, upperBound, upperInclusive);
            
            // Note: The IndexRangeIteratorBuilder hard codes 'negated' to false, so unless that changes, this logic will never be executed.
            if (isNegated()) {
                Key startFi = new Key(rowId, fiName);
                Key endFi = new Key(rowId, new Text(fiName.toString() + '\0'));
                List<Range> rangeList = new ArrayList<>(new RangeSplitter(new Range(startFi, true, startKey, true), getMaxRangeSplit() / 2));
                rangeList.addAll(new RangeSplitter(new Range(endKey, true, endFi, true), getMaxRangeSplit() / 2));
                return rangeList;
            } else {
                return new RangeSplitter(new Range(startKey, true, endKey, true), getMaxRangeSplit());
            }
        }
    }

    protected  DatawaveFieldIndexRangeIteratorJexl(Builder builder);
    public  DatawaveFieldIndexRangeIteratorJexl();
    public  DatawaveFieldIndexRangeIteratorJexl(DatawaveFieldIndexRangeIteratorJexl other, IteratorEnvironment env);

}