Machine Coding Problem

Image Gallery

macoAllmediametadatafolder-structure
Commonly Asked By:PinterestSnapInstagram

Functional Scope (In-Scope)

  • Hierarchical Parent-Child Folder Tree: Represents multi-level directories uniformly using child and parent relationship matrices.
  • O(1) Tag-Based Index Intersect: O(1) query index enabling efficient multi-tag "AND" search querying without full repository scans.
  • Rich EXIF Media Metadata Store: Safely parses and indexes file size, layout constraints, spatial coordinates, and hardware camera specifications.
  • HMAC Cryptographic Shared Links: Encodes token payload parameters with expirations directly, validated statelessly via signature checking.

Explicit Boundaries (Out-of-Scope)

  • Concrete Blob Transcoding Engines: Omits real-time video/image compression algorithms, dynamic resolution resizing, and chunk loaders.
  • Network-level CDN and S3 integrations: Simulates local file path identifiers instead of implementing actual S3 API adapters or cloud bucket uploaders.

Production reference implementations demonstrating nested folders, O(1) multi-tag queries, and stateless HMAC links in Java and Python:

// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

class ExifMetadata {
    private final long fileSizeBytes;
    private final int widthPixels;
    private final int heightPixels;
    private final String cameraModel;
    private final double gpsLatitude;
    private final double gpsLongitude;

    public ExifMetadata(long fileSizeBytes, int widthPixels, int heightPixels, String cameraModel, double gpsLatitude, double gpsLongitude) {
        this.fileSizeBytes = fileSizeBytes;
        this.widthPixels = widthPixels;
        this.heightPixels = heightPixels;
        this.cameraModel = cameraModel;
        this.gpsLatitude = gpsLatitude;
        this.gpsLongitude = gpsLongitude;
    }

    public long getFileSizeBytes() { return fileSizeBytes; }
    public int getWidthPixels() { return widthPixels; }
    public int getHeightPixels() { return heightPixels; }
    public String getCameraModel() { return cameraModel; }
    public double getGpsLatitude() { return gpsLatitude; }
    public double getGpsLongitude() { return gpsLongitude; }
}

class Image {
    private final String id;
    private final String filename;
    private final String filePath;
    private final long uploadTimeMs;
    private final Set<String> tags;
    private final ExifMetadata exifMetadata;
    private final String folderId;

    public Image(String id, String filename, String filePath, long uploadTimeMs, Set<String> tags, ExifMetadata exifMetadata, String folderId) {
        this.id = id;
        this.filename = filename;
        this.filePath = filePath;
        this.uploadTimeMs = uploadTimeMs;
        this.tags = new HashSet<>(tags);
        this.exifMetadata = exifMetadata;
        this.folderId = folderId;
    }

    public String getId() { return id; }
    public String getFilename() { return filename; }
    public String getFilePath() { return filePath; }
    public long getUploadTimeMs() { return uploadTimeMs; }
    public Set<String> getTags() { return Collections.unmodifiableSet(tags); }
    public ExifMetadata getExifMetadata() { return exifMetadata; }
    public String getFolderId() { return folderId; }
}

class Folder {
    private final String id;
    private final String name;
    private final String parentId; // null if Root
    private final List<String> subfolderIds;
    private final List<String> imageIds;

    public Folder(String id, String name, String parentId) {
        this.id = id;
        this.name = name;
        this.parentId = parentId;
        this.subfolderIds = new CopyOnWriteArrayList<>();
        this.imageIds = new CopyOnWriteArrayList<>();
    }

    public String getId() { return id; }
    public String getName() { return name; }
    public String getParentId() { return parentId; }
    public List<String> getSubfolderIds() { return subfolderIds; }
    public List<String> getImageIds() { return imageIds; }

    public void addSubfolder(String folderId) {
        subfolderIds.add(folderId);
    }

    public void addImage(String imageId) {
        imageIds.add(imageId);
    }

    public void removeImage(String imageId) {
        imageIds.remove(imageId);
    }
}

class GalleryService {
    private final Map<String, Folder> folders = new HashMap<>();
    private final Map<String, Image> images = new HashMap<>();
    private final Map<String, Set<String>> tagIndex = new HashMap<>();
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final String secretKey = "SuperSecretHMACGalleryKey";
    private static final String ROOT_FOLDER_ID = "ROOT";

    public GalleryService() {
        folders.put(ROOT_FOLDER_ID, new Folder(ROOT_FOLDER_ID, "Root", null));
    }

    public Folder createFolder(String name, String parentId) {
        String actualParent = (parentId == null) ? ROOT_FOLDER_ID : parentId;
        
        rwLock.writeLock().lock();
        try {
            Folder parent = folders.get(actualParent);
            if (parent == null) {
                throw new IllegalArgumentException("Parent folder does not exist.");
            }

            String folderId = UUID.randomUUID().toString();
            Folder newFolder = new Folder(folderId, name, actualParent);
            folders.put(folderId, newFolder);
            parent.addSubfolder(folderId);

            return newFolder;
        } finally {
            rwLock.writeLock().unlock();
        }
    }

    public Image uploadImage(String filename, String filePath, Set<String> tags, ExifMetadata exif, String folderId) {
        String actualFolder = (folderId == null) ? ROOT_FOLDER_ID : folderId;
        
        rwLock.writeLock().lock();
        try {
            Folder target = folders.get(actualFolder);
            if (target == null) {
                throw new IllegalArgumentException("Target folder does not exist.");
            }

            String imageId = UUID.randomUUID().toString();
            Image newImage = new Image(imageId, filename, filePath, System.currentTimeMillis(), tags, exif, actualFolder);
            images.put(imageId, newImage);
            target.addImage(imageId);

            // Populate Tag Index O(1)
            for (String tag : tags) {
                tagIndex.computeIfAbsent(tag.toLowerCase(), k -> new HashSet<>()).add(imageId);
            }

            return newImage;
        } finally {
            rwLock.writeLock().unlock();
        }
    }

    public List<Image> searchImagesByTags(Set<String> queryTags) {
        if (queryTags == null || queryTags.isEmpty()) {
            return Collections.emptyList();
        }

        rwLock.readLock().lock();
        try {
            Set<String> intersectedIds = null;

            for (String tag : queryTags) {
                Set<String> matches = tagIndex.get(tag.toLowerCase());
                if (matches == null || matches.isEmpty()) {
                    return Collections.emptyList(); // AND constraint fails
                }
                if (intersectedIds == null) {
                    intersectedIds = new HashSet<>(matches);
                } else {
                    intersectedIds.retainAll(matches);
                }
            }

            if (intersectedIds == null || intersectedIds.isEmpty()) {
                return Collections.emptyList();
            }

            return intersectedIds.stream()
                .map(images::get)
                .sorted(Comparator.comparingLong(Image::getUploadTimeMs).reversed())
                .collect(Collectors.toList());
        } finally {
            rwLock.readLock().unlock();
        }
    }

    public String generateShareLink(String albumId, long ttlSeconds) {
        rwLock.readLock().lock();
        try {
            if (!folders.containsKey(albumId)) {
                throw new IllegalArgumentException("Target album/folder does not exist.");
            }
        } finally {
            rwLock.readLock().unlock();
        }
        
        long expiryTimeMs = System.currentTimeMillis() + (ttlSeconds * 1000);
        String payload = albumId + ":" + expiryTimeMs;
        String signature = generateHMAC(payload);

        return "https://gallery.app/shared?albumId=" + albumId + "&expires=" + expiryTimeMs + "&sig=" + signature;
    }

    public boolean validateShareLink(String albumId, long expiryTimeMs, String signature) {
        if (System.currentTimeMillis() > expiryTimeMs) {
            return false; // Link expired
        }
        String payload = albumId + ":" + expiryTimeMs;
        String expectedSignature = generateHMAC(payload);
        return constantTimeEquals(expectedSignature, signature);
    }

    public Folder getFolderContents(String folderId) {
        rwLock.readLock().lock();
        try {
            return folders.get(folderId);
        } finally {
            rwLock.readLock().unlock();
        }
    }

    public Image getImage(String imageId) {
        rwLock.readLock().lock();
        try {
            return images.get(imageId);
        } finally {
            rwLock.readLock().unlock();
        }
    }

    private String generateHMAC(String data) {
        try {
            Mac sha256HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
            sha256HMAC.init(secretKeySpec);
            byte[] hash = sha256HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8));
            
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException("HMAC computation failed", e);
        }
    }

    private boolean constantTimeEquals(String a, String b) {
        if (a == null || b == null) return false;
        if (a.length() != b.length()) return false;
        
        int result = 0;
        for (int i = 0; i < a.length(); i++) {
            result |= a.charAt(i) ^ b.charAt(i);
        }
        return result == 0;
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println("=== JAVA IMAGE GALLERY DEMO ===");
        GalleryService service = new GalleryService();

        // 1. Create album folders
        Folder vacationAlbum = service.createFolder("Vacation 2026", null);
        Folder subFolderPhotos = service.createFolder("Scenery", vacationAlbum.getId());
        System.out.println("Created folder hierarchy structure.");

        // 2. Upload images with EXIF metadata
        ExifMetadata exif1 = new ExifMetadata(5420000L, 4032, 3024, "iPhone 15 Pro", 37.7749, -122.4194);
        Image img1 = service.uploadImage("sunset.png", "/vacation/scenery/sunset.png", 
            new HashSet<>(Arrays.asList("nature", "sunset", "scenery")), exif1, subFolderPhotos.getId());
        System.out.println("Uploaded Sunset Photo to scenery album: " + img1.getId());

        ExifMetadata exif2 = new ExifMetadata(2150000L, 2048, 1536, "Canon EOS", 34.0522, -118.2437);
        Image img2 = service.uploadImage("mountains.jpg", "/vacation/scenery/mountains.jpg", 
            new HashSet<>(Arrays.asList("nature", "mountain", "scenery")), exif2, subFolderPhotos.getId());
        System.out.println("Uploaded Mountains Photo to scenery album: " + img2.getId());

        // 3. Search photos via Multi-Tag AND intersection lookup
        Set<String> searchTags = new HashSet<>(Arrays.asList("nature", "scenery"));
        List<Image> searchResults = service.searchImagesByTags(searchTags);
        System.out.println("Tag search for [nature, scenery] found " + searchResults.size() + " matches:");
        for (Image img : searchResults) {
            System.out.println(" - " + img.getFilename() + " (Camera: " + img.getExifMetadata().getCameraModel() + ")");
        }

        // 4. Shared stateful link generation with secure HMAC validation
        String shareLink = service.generateShareLink(vacationAlbum.getId(), 2); // 2-second TTL expiration
        System.out.println("Generated secure stateless share link:\n " + shareLink);

        // Parse query params to validate link
        String albumIdParam = vacationAlbum.getId();
        long expiresParam = System.currentTimeMillis() + 2000;
        String sigParam = shareLink.substring(shareLink.lastIndexOf("sig=") + 4);

        boolean isValidImmediate = service.validateShareLink(albumIdParam, expiresParam, sigParam);
        System.out.println("Validation check immediately: " + (isValidImmediate ? "Valid Access" : "Access Denied"));

        System.out.println("Sleeping 2.5 seconds to force HMAC token expiration...");
        Thread.sleep(2500);

        boolean isValidPostSleep = service.validateShareLink(albumIdParam, expiresParam, sigParam);
        System.out.println("Validation check after expiration: " + (isValidPostSleep ? "Valid Access" : "Access Denied"));
        System.out.println("=== END OF JAVA DEMO ===");
    }
}