public boolean endRecord(final long currentRecordIndex) {
        // Get the current stream number.
        final long currentStreamIndex = metaHolder.getPartIndex();
        progressLocation = new StepLocation(
                metaHolder.getMeta().getId(),
                currentStreamIndex,
                currentRecordIndex);

        if (taskContext.isTerminated()) {
            return true;
        }

        // Update the progress monitor.
        taskContext.info(() ->
                "Stepping {" +
                streamInfo +
                "} [" +
                (currentStreamIndex + 1) +
                ":" +
                (currentRecordIndex + 1) +
                "]");

        LOGGER.debug("endRecord() stream index {} record index {}", currentStreamIndex, currentRecordIndex);

        // Figure out what the highlighted portion of the input stream should be.
        TextRange highlight = DEFAULT_TEXT_RANGE;
        if (locationHolder != null && locationHolder.getCurrentLocation() != null) {
            highlight = NullSafe.get(locationHolder.getCurrentLocation().getFirstHighlight(),
                    DataRange::getAsTextRange,
                    opt -> opt.orElse(null));
        }

        // First we need to check that the record is ok WRT the location of the
        // record, i.e. is it after the last record found if stepping forward
        // etc.
        if (isRecordPositionOk(currentRecordIndex)) {
            // Now that we have found an appropriate record to return lets check
            // to see if it matches any filters.
            boolean allMatch = true;
            boolean filterMatch = false;

            // We only want to filter records if we are stepping forward or
            // backward.
            if (!StepType.REFRESH.equals(request.getStepType())) {
                for (final ElementMonitor monitor : monitors) {
                    if (monitor.isFilterApplied()) {
                        if (monitor.filterMatches(currentRecordIndex)) {
                            filterMatch = true;
                        } else {
                            allMatch = false;
                        }
                    }
                }
            }

            // We are going to make an early exit from the current parse if we
            // have found the record we are interested in and any filter matches
            // if one has been specified.
            if (allMatch || filterMatch) {
                // Create a location for each monitoring filter to store data
                // against.
                foundLocation = progressLocation;

                // Create step data for the current step.
                final StepData stepData = createStepData(highlight);

                steppingResponseCache.setStepData(foundLocation, stepData);

                // We want to exit early if we have found a record and are
                // stepping first, forward or refreshing.
                if (!StepType.BACKWARD.equals(request.getStepType())
                    && !StepType.LAST.equals(request.getStepType())) {
                    return true;
                }
            }
        }

        // Reset all filters.
        clearAllFilters(highlight);

        // We want to exit early from backward stepping if we have got to the
        // previous record number.
        return StepType.BACKWARD.equals(request.getStepType())
               && stepLocation != null
               && currentStreamIndex == stepLocation.getPartIndex()
               && currentRecordIndex >= stepLocation.getRecordIndex() - 1;
    }
Called by the step detector to tell us that we have reached the end of a
record.

@return True if the step detector should terminate stepping.
stroom-pipeline/src/main/java/stroom/pipeline/stepping/SteppingController.java