Alias produktů
Alias produktů
Aliasy produktů jsou speciálním typem produktů, které umožňují vytvořit zástupce (alias) pro jiný produkt v systému.
Běžně se aliasy používají například pro více-katalogové e-shopy, kde produkt je definován pouze v "origin-katalogu" (resp. v katalogu produktových předloh), kde se spravuje jeho kompletní obsah a v ostatních "cílových" katalogech se používají aliasy, které odkazují na tento origin produkt a případně přepisují některé jeho vlastnosti (např. cena, dostupnost, název). V cílovém katalogu se pak spravují pouze vlastnosti, které jsou specifické pro tento katalog, např. zařazení do kategorií, zařazení do skupin, případně některé marketingové vlastnosti.
Alias produkt obsahuje odkaz na origin produkt, ze kterého je vytvořen. Tento odkaz umožňuje systému načíst všechny relevantní informace o produktu, jako jsou cena, popis, obrázky atd.
Vlastnosti aliasu se dají rozdělit:
- na vlastnosti, které jsou specifické pro alias (např. id, code),
- na vlastnosti, které se mohou přebírat z origin produktu (např. name, price, availability), ale je možné je přepsat,
- a na vlastnosti, které se vždy přebírají z origin produktu a nelze je přepsat (např. skladová dostupnost).
Toto rozdělení je popsáno v dokumentu Datový model a dědičnost vlastností produktu.
Zkopírovat odkaz na sekciTerminologie
- Alias produkt: konkrétní produkt v cílovém katalogu, který odkazuje na jiný (origin) produkt a může přepisovat vybrané vlastnosti.
- Origin produkt (předloha): zdrojový produkt, z něhož alias dědí vlastnosti.
- Wrapovaný produkt: objekt produktu zabalený do wrapperu (např. ProductAliasWrapper), který při čtení vlastností respektuje pravidla dědičnosti.
- Overrides: přepisy vlastností na aliasu; jejich stav drží objekt AliasOverrides (rozšiřitelný přes traity).
- Trait: interface rozšiřující rozhraní/typ o další chování nebo data; registruje se do modelu/wrapperu v beforeSpringInitialization.
Zkopírovat odkaz na sekciAliasOverrides
AliasOverrides je objekt, který obsahuje informace o tom, které vlastnosti alias dědí a které naopak přepisuje. Získat ho lze z alias produktu pomocí rozhraní ProductWithAliasData.
1 Product alias = ...; // loaded alias product2AliasOverrides aliasOverrides = ((ProductWithAliasData)alias).getAliasOverride();
Definici AliasOverrides lze rozšířit o traity, které přidají další vlastnosti, které lze přepsat. Příklad takového traitu je zde:
1 @Trait2public interface BrandAliasOverrides {3 4 String CODE_OVERRIDE_BRAND = "brand";5 6 /**7 * [cs] Metoda vrací, zda jsou data pro {@link WithBrand} pro alias přetížena.8 */9 boolean isBrandOverridden();10 /**11 * [cs] Metoda nastaví, zda má být data pro {@link WithBrand} pro alias přetížena.12 */13 void setBrandOverridden(boolean overridden);14}
Registrace traitů do AliasOverrides se provádí pomocí metody com.fg.cps.eshop.productAlias.model.AliasOverrides.registerTrait v rámci beforeSpringInitialization odpovídajícího rozšíření. Příklad registrace traitu:
1 AliasOverrides.registerTrait(BrandAliasOverrides.class);Zkopírovat odkaz na sekciProductAliasWrapper - vyhodnocení dědičnosti aliasu
Vyhodnocení dědičnosti je primárně určeno pro publikaci a publikovaná data produktů, kde je potřeba mít cílovou podobu produktu pro zobrazení na e-shopu. V primárních (zdrojových) datech se běžně pracuje s neobaleným produktem, tedy s aliasem jako samostatným produktem, z důvodu potřeby editace vlastností přímo daného aliasu.
Vyhodnocení dědičnosti aliasu, tedy zda se vlastnost přebírá z origin produktu nebo je přepsána v aliasu, zajišťuje com.fg.cps.eshop.productAlias.model.ProductAliasWrapper a případně jeho traity.
Pozn: Vyhodnocení dědičnosti se nevztahuje pouze na alias-produkty, ale také na varianty produktů, které dědí vlastnosti z jejich "master" produktu, případně kombinace aliasů a variant.
Zkopírovat odkaz na sekciNačtení wrapovaného produktu
Nejsnadnější způsob, jak získat wrapovaný produkt (s vyhodnocenou dědičností), je pomocí "wrap" varianty metod přímo v com.fg.cps.eshop.product.service.AbstractProductService. Další možností je načtení produktu pomocí query s com.fg.cps.eshop.catalogEntity.model.query.WrapHint, případně přímo přes com.fg.cps.eshop.catalogEntity.service.wrapping.WrappingService.
Takto načtený alias je obalený do ProductAliasWrapper, který zajišťuje přístup jak k samotnému aliasu, tak i k jeho origin produktu a vyhodnocení dědičnosti.
Příklad práce s wrapovaným aliasem – získání origin produktu:
1 Product alias = ...; // alias načtený již jako wrapovaný2Product origin = ProductAliasWrapper.getOrigin(alias); // vyhodí IllegalArgumentException, pokud alias není wrapovaný
Zkopírovat odkaz na sekciRozšíření aliasu o další vlastnosti a určení jejich dědičnosti
Chcete‑li alias rozšířit o novou vlastnost a určit, zda se má dědit z origin produktu nebo přepisovat na aliasu, postupujte podle následujícího vzoru. Níže je použitá existující implementace značky (brand) jako referenční příklad.
- Definujte override trait pro AliasOverrides
- Vytvořte trait, kterým rozšíříte AliasOverrides o příznak(y) přetížení pro novou vlastnost. Doporučuje se vystavit i konstantu s kódem override, která se může hodit např. pro publikaci.
1 @Trait2public interface BrandAliasOverrides {3 String CODE_OVERRIDE_BRAND = "brand";4 5 /** Vrátí, zda jsou data pro WithBrand na aliasu přetížena. */6 boolean isBrandOverridden();7 /** Nastaví, zda má být WithBrand pro alias přetíženo. */8 void setBrandOverridden(boolean overridden);9}
Registrace traitu do AliasOverrides (typicky v Feature.beforeSpringInitialization):
1 AliasOverrides.registerTrait(BrandAliasOverrides.class);- Rozšiřte produkt o „WithXAndOverrides“
- Přidejte trait, který rozšíří doménové rozhraní (např. WithBrand) o metody pro práci s přepisem přes ProductWithAliasData. Tento trait je dostupný i na neobaleném produktu, aby bylo možné číst/řídit stav přepisů na aliasu.
1 @Trait2public interface WithBrandAndOverrides extends WithBrand, ProductWithAliasData {3 default void setBrandOverridden(boolean overridden) {4 ((BrandAliasOverrides) getRequiredOverrides()).setBrandOverridden(overridden);5 }6 @ApiIgnore7 default boolean isBrandOverridden() {8 return ((BrandAliasOverrides) getRequiredOverrides()).isBrandOverridden();9 }10}
Registrace traitu k modelu produktu (typicky v Feature.beforeSpringInitialization):
1 final ModelClassDescriptor productModelDescriptor = entityModel.getModelDescriptor(CatalogEntityType.PRODUCT);2productModelDescriptor.addTrait(WithBrandAndOverrides.class);
- Implementujte wrapper trait pro vyhodnocení dědičnosti
- Vytvořte trait pro ProductAliasWrapper, který implementuje logiku „pokud je přepsáno, ber data z aliasu, jinak z originu“. Zápisy ukládejte vždy na alias. Samotný příznak přepisu se obvykle nastavuje zvlášť (např. přes setBrandOverridden), automaticky se nenastavuje.
1 @Trait2public interface ProductWithBrandAlias extends ProductAliasAccessor, WithBrandAndOverrides {3 @Override4 default BrandDataWithCatalogEntity getBrand() {5 if (((WithBrandAndOverrides) getAlias()).isBrandOverridden()) {6 return ((WithBrand) getAlias()).getBrand();7 } else {8 return ((WithBrand) getOrigin()).getBrand();9 }10 }11 12 default void setBrand(Brand brand) {13 ((WithBrand) getAlias()).setBrand(brand);14 }15 16 @Override17 @ApiIgnore18 default void setIdBrand(Integer idBrand) {19 ((WithBrand) getAlias()).setIdBrand(idBrand);20 }21}
Registrace wrapper traitu pro ProductAliasWrapper (typicky v Feature.beforeSpringInitialization):
1 final ModelClassDescriptor wrapperDescriptor = entityModel.getWrapperDescriptor(2 CatalogEntityType.PRODUCT, ProductAliasWrapper.class3);4wrapperDescriptor.addTrait(ProductWithBrandAlias.class);
- (Volitelné) Napojení na publikační pravidla
- Pokud chcete, aby změna konkrétního override kódu vyvolala specifické publikační požadavky, využijte konstantu override kódu a zaregistrujte pravidlo:
1 aliasPublishingRule.addChangeOverrideRules(2 new AliasPublishingRule.ChangeOverrideRule(3 codes -> codes.stream().anyMatch(it -> it.equals(BrandAliasOverrides.CODE_OVERRIDE_BRAND)),4 PRODUCT_BRAND5 )6);
Poznámky a doporučení:
- Přístup k origin a alias instancím ve wrapper traitech zajišťuje rozhraní ProductAliasAccessor (getOrigin(), getAlias()).
- Obecné AOP pro AliasOverrides (AliasOverrideAdvice) řeší mapování generických override kódů i lokalizovaných/galerie příznaků. Pro jednoduché booleovské přepínače stačí mít v AliasOverrides odpovídající trait s is*/set* metodami.
- V administračním UI či službách je dobré při zápisu hodnot na alias současně nastavit i příznak přepsání (např. setBrandOverridden(true)), aby se při čtení použila aliasová hodnota.
- Stejný vzor lze použít pro jakoukoli další vlastnost: vytvořte AliasOverrides trait (CODE_OVERRIDE_...), WithXAndOverrides trait a ProductWithXAlias trait; vše zaregistrujte do modelu a wrapperu.