class PerformanceCachingGoogleCloudStorage extends ForwardingGoogleCloudStorage {

  @Override
  public GoogleCloudStorageItemInfo getItemInfo(StorageResourceId resourceId) throws IOException {
    // Get the item from cache.
    GoogleCloudStorageItemInfo item = cache.getItem(resourceId);

    // If it wasn't in the cache, list all the objects in the parent directory and cache them
    // and then retrieve it from the cache.
    if (item == null && resourceId.isStorageObject()) {
      String bucketName = resourceId.getBucketName();
      String objectName = resourceId.getObjectName();
      int lastSlashIndex = objectName.lastIndexOf(PATH_DELIMITER);
      String directoryName =
          lastSlashIndex >= 0 ? objectName.substring(0, lastSlashIndex + 1) : null;
      // make just 1 request to prefetch only 1 page of directory items
      listObjectInfoPage(
          bucketName, directoryName, ListObjectOptions.DEFAULT, /* pageToken= */ null);
      item = cache.getItem(resourceId);
    }

    // If it wasn't in the cache and wasn't cached in directory list request
    // then request and cache it directly.
    if (item == null) {
      item = super.getItemInfo(resourceId);
      cache.putItem(item);
    }

    return item;
  }

  public  PerformanceCachingGoogleCloudStorage(
      GoogleCloudStorage delegate, PerformanceCachingGoogleCloudStorageOptions options);
  @VisibleForTesting  PerformanceCachingGoogleCloudStorage(
      GoogleCloudStorage delegate,
      PrefixMappedItemCache cache);

}