Blame | Last modification | View Log | RSS feed
package com.smartdukaan.cron.offercircular;import java.util.Collections;import java.util.HashMap;import java.util.List;import java.util.Map;import com.spice.profitmandi.dao.repository.offers.CircularIngestRepository;/*** Catalog rows bucketed by (brand, category), which is what makes the matcher's* brand -> category -> model staging enforceable: a lookup can only ever see* candidates from the right bucket, so there is no way to accidentally match a* tablet offer against a phone.*/public final class CatalogIndex {private final Map<String, List<ProductMatcher.Candidate>> buckets = new HashMap<>();private CatalogIndex() { }public static CatalogIndex load(CircularIngestRepository repository) {CatalogIndex index = new CatalogIndex();for (Object[] row : repository.selectCatalogCandidates()) {String brand = (String) row[0];int categoryId = ((Number) row[1]).intValue();int catalogId = ((Number) row[2]).intValue();String display = (String) row[3];int superCatalogId = ((Number) row[4]).intValue();index.buckets.computeIfAbsent(key(brand, categoryId), k -> new java.util.ArrayList<>()).add(new ProductMatcher.Candidate(catalogId, display, superCatalogId));}return index;}private static String key(String brand, int categoryId) {return (brand == null ? "" : brand.toLowerCase()) + "|" + categoryId;}/** Never null - an unknown bucket yields no candidates, which becomes CATALOG_GAP. */public List<ProductMatcher.Candidate> candidates(String brand, int categoryId) {List<ProductMatcher.Candidate> found = buckets.get(key(brand, categoryId));return found == null ? Collections.emptyList() : found;}public int size() {int total = 0;for (List<ProductMatcher.Candidate> bucket : buckets.values()) {total += bucket.size();}return total;}}