class CacheStorageReader {

  @VisibleForTesting
  static void verifyImageMetadata(ImageMetadataTemplate metadata, Path metadataCacheDirectory)
      throws CacheCorruptedException {
    List<ManifestAndConfigTemplate> manifestsAndConfigs = metadata.getManifestsAndConfigs();
    if (manifestsAndConfigs.isEmpty()) {
      throw new CacheCorruptedException(metadataCacheDirectory, "Manifest cache empty");
    }
    if (manifestsAndConfigs.stream().anyMatch(entry -> entry.getManifest() == null)) {
      throw new CacheCorruptedException(metadataCacheDirectory, "Manifest(s) missing");
    }
    if (metadata.getManifestList() == null && manifestsAndConfigs.size() != 1) {
      throw new CacheCorruptedException(metadataCacheDirectory, "Manifest list missing");
    }

    ManifestTemplate firstManifest = manifestsAndConfigs.get(0).getManifest();
    if (firstManifest instanceof V21ManifestTemplate) {
      if (metadata.getManifestList() != null
          || manifestsAndConfigs.stream().anyMatch(entry -> entry.getConfig() != null)) {
        throw new CacheCorruptedException(metadataCacheDirectory, "Schema 1 manifests corrupted");
      }
    } else if (firstManifest instanceof BuildableManifestTemplate) {
      if (manifestsAndConfigs.stream().anyMatch(entry -> entry.getConfig() == null)) {
        throw new CacheCorruptedException(metadataCacheDirectory, "Schema 2 manifests corrupted");
      }
      if (metadata.getManifestList() != null
          && manifestsAndConfigs.stream().anyMatch(entry -> entry.getManifestDigest() == null)) {
        throw new CacheCorruptedException(metadataCacheDirectory, "Schema 2 manifests corrupted");
      }
    } else {
      throw new CacheCorruptedException(
          metadataCacheDirectory, "Unknown manifest type: " + firstManifest);
    }
  }

    CacheStorageReader(CacheStorageFiles cacheStorageFiles);

}