/**
   * Returns a result segment of an enumerable collection of files and directories for this
   * directory, using the specified listing details options, request options, and operation context.
   *
   * @param maxResults The maximum number of results to retrieve.
   * @param continuationToken A {@link ResultContinuation} object that represents a continuation
   *     token returned by a previous listing operation.
   * @param options A {@link FileRequestOptions} object that specifies any additional options for
   *     the request. Specifying <code>null</code> will use the default request options from the
   *     associated service client ( {@link CloudFileClient}).
   * @param opContext An {@link OperationContext} object that represents the context for the current
   *     operation. This object is used to track requests to the storage service, and to provide
   *     additional runtime information about the operation.
   * @return A {@link ResultSegment} object that contains a segment of the enumerable collection of
   *     {@link ListFileItem} objects that represent the files and directories in this directory.
   * @throws StorageException If a storage service error occurred.
   */
  public ResultSegment<ListFileItem> listFilesAndDirectoriesSegmented(
      final int maxResults,
      final ResultContinuation continuationToken,
      FileRequestOptions options,
      OperationContext opContext)
      throws StorageException {
    if (opContext == null) {
      opContext = new OperationContext();
    }

    opContext.initialize();
    options = FileRequestOptions.applyDefaults(options, this.fileServiceClient);

    Utility.assertContinuationType(continuationToken, ResultContinuationType.FILE);

    SegmentedStorageRequest segmentedRequest = new SegmentedStorageRequest();
    segmentedRequest.setToken(continuationToken);

    return ExecutionEngine.executeWithRetry(
        this.fileServiceClient,
        this,
        this.listFilesAndDirectoriesSegmentedImpl(maxResults, options, segmentedRequest),
        options.getRetryPolicyFactory(),
        opContext);
  }
  private StorageRequest<CloudFileClient, CloudFileDirectory, ResultSegment<ListFileItem>>
      listFilesAndDirectoriesSegmentedImpl(
          final int maxResults,
          final FileRequestOptions options,
          final SegmentedStorageRequest segmentedRequest) {

    Utility.assertContinuationType(segmentedRequest.getToken(), ResultContinuationType.FILE);

    final ListingContext listingContext = new ListingContext(null, maxResults);

    final StorageRequest<CloudFileClient, CloudFileDirectory, ResultSegment<ListFileItem>>
        getRequest =
            new StorageRequest<CloudFileClient, CloudFileDirectory, ResultSegment<ListFileItem>>(
                options, this.getStorageUri()) {

              @Override
              public void setRequestLocationMode() {
                this.setRequestLocationMode(
                    Utility.getListingLocationMode(segmentedRequest.getToken()));
              }

              @Override
              public HttpURLConnection buildRequest(
                  CloudFileClient client, CloudFileDirectory directory, OperationContext context)
                  throws Exception {
                listingContext.setMarker(
                    segmentedRequest.getToken() != null
                        ? segmentedRequest.getToken().getNextMarker()
                        : null);
                return FileRequest.listFilesAndDirectories(
                    directory.getUri(), options, context, listingContext);
              }

              @Override
              public void signRequest(
                  HttpURLConnection connection, CloudFileClient client, OperationContext context)
                  throws Exception {
                StorageRequest.signBlobQueueAndFileRequest(connection, client, -1L, null);
              }

              @Override
              public ResultSegment<ListFileItem> preProcessResponse(
                  CloudFileDirectory directory, CloudFileClient client, OperationContext context)
                  throws Exception {
                if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) {
                  this.setNonExceptionedRetryableFailure(true);
                }

                return null;
              }

              @Override
              public ResultSegment<ListFileItem> postProcessResponse(
                  HttpURLConnection connection,
                  CloudFileDirectory directory,
                  CloudFileClient client,
                  OperationContext context,
                  ResultSegment<ListFileItem> storageObject)
                  throws Exception {
                final ListResponse<ListFileItem> response =
                    FileListHandler.getFileAndDirectoryList(
                        this.getConnection().getInputStream(), directory);
                ResultContinuation newToken = null;

                if (response.getNextMarker() != null) {
                  newToken = new ResultContinuation();
                  newToken.setNextMarker(response.getNextMarker());
                  newToken.setContinuationType(ResultContinuationType.FILE);
                  newToken.setTargetLocation(this.getResult().getTargetLocation());
                }

                final ResultSegment<ListFileItem> resSegment =
                    new ResultSegment<ListFileItem>(response.getResults(), maxResults, newToken);

                // Important for listFilesAndDirectories because this is required by the lazy
                // iterator between executions.
                segmentedRequest.setToken(resSegment.getContinuationToken());
                return resSegment;
              }
            };

    return getRequest;
  }