/** default maxResults is 1000 */
  @Override
  public ListenableFuture<PageSet<? extends StorageMetadata>> list(
      final String container, ListContainerOptions options) {

    // Check if the container exists
    if (!containerExistsSyncImpl(container)) {
      return immediateFailedFuture(cnfe(container));
    }

    // Loading blobs from container
    Iterable<String> blobBelongingToContainer = null;
    try {
      blobBelongingToContainer = storageStrategy.getBlobKeysInsideContainer(container);
    } catch (IOException e) {
      logger.error(e, "An error occurred loading blobs contained into container %s", container);
      Throwables.propagate(e);
    }

    SortedSet<StorageMetadata> contents =
        newTreeSet(
            transform(
                blobBelongingToContainer,
                new Function<String, StorageMetadata>() {
                  public StorageMetadata apply(String key) {
                    Blob oldBlob = loadFileBlob(container, key);

                    checkState(
                        oldBlob != null,
                        "blob "
                            + key
                            + " is not present although it was in the list of "
                            + container);
                    checkState(
                        oldBlob.getMetadata() != null,
                        "blob " + container + "/" + key + " has no metadata");
                    MutableBlobMetadata md = copy(oldBlob.getMetadata());
                    String directoryName = ifDirectoryReturnName.execute(md);
                    if (directoryName != null) {
                      md.setName(directoryName);
                      md.setType(StorageType.RELATIVE_PATH);
                    }
                    return md;
                  }
                }));

    String marker = null;
    if (options != null) {
      if (options.getMarker() != null) {
        final String finalMarker = options.getMarker();
        StorageMetadata lastMarkerMetadata =
            find(
                contents,
                new Predicate<StorageMetadata>() {
                  public boolean apply(StorageMetadata metadata) {
                    return metadata.getName().equals(finalMarker);
                  }
                });
        contents = contents.tailSet(lastMarkerMetadata);
        contents.remove(lastMarkerMetadata);
      }

      final String prefix = options.getDir();
      if (prefix != null) {
        contents =
            newTreeSet(
                filter(
                    contents,
                    new Predicate<StorageMetadata>() {
                      public boolean apply(StorageMetadata o) {
                        return (o != null
                            && o.getName().startsWith(prefix)
                            && !o.getName().equals(prefix));
                      }
                    }));
      }

      Integer maxResults = options.getMaxResults() != null ? options.getMaxResults() : 1000;
      if (contents.size() > 0) {
        SortedSet<StorageMetadata> contentsSlice = firstSliceOfSize(contents, maxResults);
        if (!contentsSlice.contains(contents.last())) {
          // Partial listing
          marker = contentsSlice.last().getName();
        } else {
          marker = null;
        }
        contents = contentsSlice;
      }

      final String delimiter = options.isRecursive() ? null : File.separator;
      if (delimiter != null) {
        SortedSet<String> commonPrefixes = null;
        Iterable<String> iterable =
            transform(contents, new CommonPrefixes(prefix != null ? prefix : null, delimiter));
        commonPrefixes = iterable != null ? newTreeSet(iterable) : new TreeSet<String>();
        commonPrefixes.remove(CommonPrefixes.NO_PREFIX);

        contents =
            newTreeSet(
                filter(contents, new DelimiterFilter(prefix != null ? prefix : null, delimiter)));

        Iterables.<StorageMetadata>addAll(
            contents,
            transform(
                commonPrefixes,
                new Function<String, StorageMetadata>() {
                  public StorageMetadata apply(String o) {
                    MutableStorageMetadata md = new MutableStorageMetadataImpl();
                    md.setType(StorageType.RELATIVE_PATH);
                    md.setName(o);
                    return md;
                  }
                }));
      }

      // trim metadata, if the response isn't supposed to be detailed.
      if (!options.isDetailed()) {
        for (StorageMetadata md : contents) {
          md.getUserMetadata().clear();
        }
      }
    }

    return Futures.<PageSet<? extends StorageMetadata>>immediateFuture(
        new PageSetImpl<StorageMetadata>(contents, marker));
  }