Blame | Last modification | View Log | RSS feed
package com.smartdukaan.cron.offercircular;import java.util.HashMap;import java.util.Map;import java.util.regex.Matcher;import java.util.regex.Pattern;import com.spice.profitmandi.dao.repository.offers.CircularIngestRepository;/*** Human-confirmed exceptions from offers.product_alias, consulted BEFORE any matching.** These exist because the circular and our catalog sometimes name the same product* differently - Apple ship "iPhone Air" while our catalog rows read "iPhone 17 Air" -* and because some products are genuinely not ours (no Pixel SKUs are stocked). A* confirmation recorded once keeps applying every following month, which is the whole* point: without it the same review queue regenerates identically.*/public final class ProductAliases {private static final Pattern VARIANT_SPEC = Pattern.compile("\\(?\\s*\\d+\\s*[+/]\\s*\\d+\\s*(?:GB|TB|G|T)?\\s*\\)?|\\d+\\s*(?:GB|TB)",Pattern.CASE_INSENSITIVE);public static final class Alias {private final String action;private final String canonicalText;private final Integer catalogId;private final Integer superCatalogId;Alias(String action, String canonicalText, Integer catalogId, Integer superCatalogId) {this.action = action;this.canonicalText = canonicalText;this.catalogId = catalogId;this.superCatalogId = superCatalogId;}public boolean isIgnore() { return "IGNORE".equals(action); }public boolean isPin() { return "PIN".equals(action) && (catalogId != null || superCatalogId != null); }public boolean isRewrite() { return "REWRITE".equals(action) && canonicalText != null; }public Integer getCatalogId() { return catalogId; }public Integer getSuperCatalogId() { return superCatalogId; }/*** Substitutes the catalog's spelling while preserving whatever variant spec* the circular gave, so "iPhone Air" becomes "iPhone 17 Air" and* "RENO16C 12+256GB" would become "<canonical> 12+256GB".*/public String rewrite(String rawText) {StringBuilder sb = new StringBuilder(canonicalText);Matcher m = VARIANT_SPEC.matcher(rawText);while (m.find()) {sb.append(' ').append(m.group());}return sb.toString().trim();}}private final Map<String, Alias> byLabelAndText = new HashMap<>();private ProductAliases() { }public static ProductAliases load(CircularIngestRepository repository) {ProductAliases aliases = new ProductAliases();for (Object[] row : repository.selectProductAliases()) {String label = (String) row[0];String rawText = (String) row[1];String action = (String) row[2];String canonical = (String) row[3];int catalogId = ((Number) row[4]).intValue();int superCatalogId = ((Number) row[5]).intValue();aliases.byLabelAndText.put(key(label, rawText),new Alias(action,canonical == null || canonical.isEmpty() ? null : canonical,catalogId == 0 ? null : catalogId,superCatalogId == 0 ? null : superCatalogId));}return aliases;}/** Keyed on the normalised product text so trivial spacing differences still hit. */private static String key(String divisionLabel, String rawText) {return divisionLabel + "" + ProductNames.norm(rawText);}public Alias find(String divisionLabel, String rawText) {return byLabelAndText.get(key(divisionLabel, rawText));}public int size() { return byLabelAndText.size(); }}