Question

Hi I am new on broadleaf and trying to understand it , so while going through the code of broadleaf commerce I have found the @AdminPresentation over the Entity fields and so many @Admin related like @AdminPresentationAdornedTargetCollection,@AdminPresentationCollection etc. related annotation so please explain what is the role of these annotation or any reference link to understand these annotation is very helpful

    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.collections.Predicate;
    import org.broadleafcommerce.common.admin.domain.AdminMainEntity;
    import org.broadleafcommerce.common.media.domain.Media;
    import org.broadleafcommerce.common.persistence.ArchiveStatus;
    import org.broadleafcommerce.common.persistence.Status;
    import org.broadleafcommerce.common.presentation.AdminPresentation;
    import org.broadleafcommerce.common.presentation.AdminPresentationAdornedTargetCollection;
    import org.broadleafcommerce.common.presentation.AdminPresentationClass;
    import org.broadleafcommerce.common.presentation.AdminPresentationCollection;
    import org.broadleafcommerce.common.presentation.AdminPresentationMap;
    import org.broadleafcommerce.common.presentation.AdminPresentationOperationTypes;
    import org.broadleafcommerce.common.presentation.AdminPresentationToOneLookup;
    import org.broadleafcommerce.common.presentation.PopulateToOneFieldsEnum;
    import org.broadleafcommerce.common.presentation.RequiredOverride;
    import org.broadleafcommerce.common.presentation.client.AddMethodType;
    import org.broadleafcommerce.common.presentation.client.OperationType;
    import org.broadleafcommerce.common.presentation.client.VisibilityEnum;
    import org.broadleafcommerce.common.util.DateUtil;
    import org.broadleafcommerce.common.vendor.service.type.ContainerShapeType;
    import org.broadleafcommerce.common.vendor.service.type.ContainerSizeType;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@javax.persistence.Table(name="BLC_PRODUCT")
//multi-column indexes don't appear to get exported correctly when declared at the field level, so declaring here as a workaround
@org.hibernate.annotations.Table(appliesTo = "BLC_PRODUCT", indexes = {
    @Index(name = "PRODUCT_URL_INDEX",
            columnNames = {"URL","URL_KEY"}
    )
})
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="blStandardElements")
@AdminPresentationClass(populateToOneFields = PopulateToOneFieldsEnum.TRUE, friendlyName = "baseProduct")
@SQLDelete(sql="UPDATE BLC_PRODUCT SET ARCHIVED = 'Y' WHERE PRODUCT_ID = ?")
public class ProductImpl implements Product, Status, AdminMainEntity {

    private static final Log LOG = LogFactory.getLog(ProductImpl.class);
    /** The Constant serialVersionUID. */
    private static final long serialVersionUID = 1L;

    /** The id. */
    @Id
    @GeneratedValue(generator= "ProductId")
    @GenericGenerator(
        name="ProductId",
        strategy="org.broadleafcommerce.common.persistence.IdOverrideTableGenerator",
        parameters = {
            @Parameter(name="segment_value", value="ProductImpl"),
            @Parameter(name="entity_name", value="org.broadleafcommerce.core.catalog.domain.ProductImpl")
        }
    )
    @Column(name = "PRODUCT_ID")
    @AdminPresentation(friendlyName = "ProductImpl_Product_ID", visibility = VisibilityEnum.HIDDEN_ALL)
    protected Long id;

    @Column(name = "URL")
    @AdminPresentation(friendlyName = "ProductImpl_Product_Url", order = Presentation.FieldOrder.URL,
        group = Presentation.Group.Name.General, groupOrder = Presentation.Group.Order.General, 
        prominent = true, gridOrder = 3, columnWidth = "200px",
        requiredOverride = RequiredOverride.REQUIRED)
    protected String url;

    @Column(name = "URL_KEY")
    @AdminPresentation(friendlyName = "ProductImpl_Product_UrlKey",
        tab = Presentation.Tab.Name.Advanced, tabOrder = Presentation.Tab.Order.Advanced,
        group = Presentation.Group.Name.General, groupOrder = Presentation.Group.Order.General, 
        excluded = true)
    protected String urlKey;

    @Column(name = "DISPLAY_TEMPLATE")
    @AdminPresentation(friendlyName = "ProductImpl_Product_Display_Template", 
        tab = Presentation.Tab.Name.Advanced, tabOrder = Presentation.Tab.Order.Advanced,
        group = Presentation.Group.Name.Advanced, groupOrder = Presentation.Group.Order.Advanced)
    protected String displayTemplate;

    @Column(name = "MODEL")
    @AdminPresentation(friendlyName = "ProductImpl_Product_Model",
        tab = Presentation.Tab.Name.Advanced, tabOrder = Presentation.Tab.Order.Advanced,
        group = Presentation.Group.Name.Advanced, groupOrder = Presentation.Group.Order.Advanced)
    protected String model;

    @Column(name = "MANUFACTURE")
    @AdminPresentation(friendlyName = "ProductImpl_Product_Manufacturer", order = Presentation.FieldOrder.MANUFACTURER,
        group = Presentation.Group.Name.General, groupOrder = Presentation.Group.Order.General, 
        prominent = true, gridOrder = 4)
    protected String manufacturer;

    @Column(name = "TAX_CODE")
    protected String taxCode;

    @Column(name = "IS_FEATURED_PRODUCT", nullable=false)
    @AdminPresentation(friendlyName = "ProductImpl_Is_Featured_Product", requiredOverride = RequiredOverride.NOT_REQUIRED,
        tab = Presentation.Tab.Name.Marketing, tabOrder = Presentation.Tab.Order.Marketing,
        group = Presentation.Group.Name.Badges, groupOrder = Presentation.Group.Order.Badges)
    protected Boolean isFeaturedProduct = false;

    @OneToOne(optional = false, targetEntity = SkuImpl.class, cascade={CascadeType.ALL}, mappedBy = "defaultProduct")
    @Cascade(value={org.hibernate.annotations.CascadeType.ALL})
    protected Sku defaultSku;

    @Column(name = "CAN_SELL_WITHOUT_OPTIONS")
    @AdminPresentation(friendlyName = "ProductImpl_Can_Sell_Without_Options",
        tab = Presentation.Tab.Name.Advanced, tabOrder = Presentation.Tab.Order.Advanced,
        group = Presentation.Group.Name.Advanced, groupOrder = Presentation.Group.Order.Advanced)
    protected Boolean canSellWithoutOptions = false;

    @Transient
    protected List<Sku> skus = new ArrayList<Sku>();

    @Transient
    protected String promoMessage;

    @OneToMany(mappedBy = "product", targetEntity = CrossSaleProductImpl.class, cascade = {CascadeType.ALL})
    @Cascade(value={org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="blStandardElements")
    @OrderBy(value="sequence")
    @AdminPresentationAdornedTargetCollection(friendlyName = "crossSaleProductsTitle", order = 1000,
        tab = Presentation.Tab.Name.Marketing, tabOrder = Presentation.Tab.Order.Marketing,
        targetObjectProperty = "relatedSaleProduct", 
        sortProperty = "sequence", 
        maintainedAdornedTargetFields = { "promotionMessage" }, 
        gridVisibleFields = { "defaultSku.name", "promotionMessage" })
    protected List<RelatedProduct> crossSaleProducts = new ArrayList<RelatedProduct>();

    @OneToMany(mappedBy = "product", targetEntity = UpSaleProductImpl.class, cascade = {CascadeType.ALL})
    @Cascade(value={org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="blStandardElements")
    @OrderBy(value="sequence")
    @AdminPresentationAdornedTargetCollection(friendlyName = "upsaleProductsTitle", order = 2000,
        tab = Presentation.Tab.Name.Marketing, tabOrder = Presentation.Tab.Order.Marketing,
        targetObjectProperty = "relatedSaleProduct", 
        sortProperty = "sequence",
        maintainedAdornedTargetFields = { "promotionMessage" }, 
        gridVisibleFields = { "defaultSku.name", "promotionMessage" })
    protected List<RelatedProduct> upSaleProducts  = new ArrayList<RelatedProduct>();

    @OneToMany(fetch = FetchType.LAZY, targetEntity = SkuImpl.class, mappedBy="product")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="blStandardElements")
    @BatchSize(size = 50)
    @AdminPresentationCollection(friendlyName="ProductImpl_Additional_Skus", order = 1000,
        tab = Presentation.Tab.Name.ProductOptions, tabOrder = Presentation.Tab.Order.ProductOptions)
    protected List<Sku> additionalSkus = new ArrayList<Sku>();

    @ManyToOne(targetEntity = CategoryImpl.class)
    @JoinColumn(name = "DEFAULT_CATEGORY_ID")
    @Index(name="PRODUCT_CATEGORY_INDEX", columnNames={"DEFAULT_CATEGORY_ID"})
    @AdminPresentation(friendlyName = "ProductImpl_Product_Default_Category", order = Presentation.FieldOrder.DEFAULT_CATEGORY,
        group = Presentation.Group.Name.General, groupOrder = Presentation.Group.Order.General, 
        prominent = true, gridOrder = 2, 
        requiredOverride = RequiredOverride.REQUIRED)
    @AdminPresentationToOneLookup()
    protected Category defaultCategory;

    @OneToMany(targetEntity = CategoryProductXrefImpl.class, mappedBy = "categoryProductXref.product")
    @Cascade(value={org.hibernate.annotations.CascadeType.MERGE, org.hibernate.annotations.CascadeType.PERSIST})
    @OrderBy(value="displayOrder")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="blStandardElements")
    @BatchSize(size = 50)
    @AdminPresentationAdornedTargetCollection(friendlyName = "allParentCategoriesTitle", order = 3000,
        tab = Presentation.Tab.Name.Marketing, tabOrder = Presentation.Tab.Order.Marketing,
        joinEntityClass = "org.broadleafcommerce.core.catalog.domain.CategoryProductXrefImpl",
        targetObjectProperty = "categoryProductXref.category",
        parentObjectProperty = "categoryProductXref.product",
        sortProperty = "displayOrder",
        gridVisibleFields = { "name" })
    protected List<CategoryProductXref> allParentCategoryXrefs = new ArrayList<CategoryProductXref>();

    @OneToMany(mappedBy = "product", targetEntity = ProductAttributeImpl.class, cascade = { CascadeType.ALL }, orphanRemoval = true)
    @Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region="blStandardElements")
    @MapKey(name="name")
    @BatchSize(size = 50)
    @AdminPresentationMap(friendlyName = "productAttributesTitle",
        tab = Presentation.Tab.Name.Advanced, tabOrder = Presentation.Tab.Order.Advanced,
        deleteEntityUponRemove = true, forceFreeFormKeys = true, keyPropertyFriendlyName = "ProductAttributeImpl_Attribute_Name"
    )
    protected Map<String, ProductAttribute> productAttributes = new HashMap<String, ProductAttribute>();

    @ManyToMany(fetch = FetchType.LAZY, targetEntity = ProductOptionImpl.class)
    @JoinTable(name = "BLC_PRODUCT_OPTION_XREF", 
        joinColumns = @JoinColumn(name = "PRODUCT_ID", referencedColumnName = "PRODUCT_ID"), 
        inverseJoinColumns = @JoinColumn(name = "PRODUCT_OPTION_ID", referencedColumnName = "PRODUCT_OPTION_ID"))
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="blStandardElements")
    @BatchSize(size = 50)
    @AdminPresentationCollection(friendlyName = "productOptionsTitle",
        tab = Presentation.Tab.Name.ProductOptions, tabOrder = Presentation.Tab.Order.ProductOptions,
        addType = AddMethodType.LOOKUP,
        manyToField = "products",
        operationTypes = @AdminPresentationOperationTypes(removeType = OperationType.NONDESTRUCTIVEREMOVE))
    protected List<ProductOption> productOptions = new ArrayList<ProductOption>();

    @Embedded
    protected ArchiveStatus archiveStatus = new ArchiveStatus();

   }


}
Was it helpful?

Solution

The purpose of the @Admin... annotations are to allow for an easy way to render class fields in the Admin.

For example, the friendlyName will dictate the name that will be displayed for said field when rendered in the admin. If I were to extend Product and add a new field productOrigin like

@AdminPresentation(friendlyName = "Product Origin")
public String productOrigin;

It would show up in the admin as a text box with the name Product Origin allowing us to enter data into our new field which would be persisted to the database. All with a simple annotation.

In a similar fashion, tab will specify which tab to display the field in while tabOrder dictates in what order to display the tab. As a note, if you provide a new name for a tab that doesn't previously exist a new tab will be created. If you look at AdminPresentation.java you can find the source code is well documented and you can get an idea of what each parameter will provide.

@AdminPresentation is the simplest case as it is used to render fields that are not linked to other classes. The others that you see in the class you provided are used to render more complex relationships like displaying a list parent Categories (@ AdminPresentationAdornedTargetCollection).

Hope this helps! Jerry

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top