Class ProductRowConverter

java.lang.Object
com.broadleafcommerce.common.dataimport.conversion.AbstractRowConverter<com.broadleafcommerce.common.dataimport.util.ConversionUtils.ConversionResponse<Product>>
com.broadleafcommerce.catalog.dataimport.converter.ProductRowConverter

public class ProductRowConverter extends com.broadleafcommerce.common.dataimport.conversion.AbstractRowConverter<com.broadleafcommerce.common.dataimport.util.ConversionUtils.ConversionResponse<Product>>
Row converter to convert a Map (or row from a CSV file) into a Product.
Author:
Kelly Tisdell (ktisdell)
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final class 
    Properties that can be provided in a product option column to configure an option.
    static final class 
     
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final String
    In BatchRequest.BatchContext.getAdditionalContextMap(), we expect a nested map under this key to contain prefetched products by their external ID.
    static final String
    In BatchRequest.BatchContext.getAdditionalContextMap(), we expect a nested map under this key to contain prefetched products by their ID.

    Fields inherited from class com.broadleafcommerce.common.dataimport.conversion.AbstractRowConverter

    COMPLEX_COLUMN_HEADER_PREFIX_DELIMITER
  • Constructor Summary

    Constructors
    Constructor
    Description
    ProductRowConverter(com.fasterxml.jackson.databind.ObjectMapper mapper, com.broadleafcommerce.common.extension.TypeFactory typeFactory, com.broadleafcommerce.common.dataimport.util.IdResolver idResolver)
     
  • Method Summary

    Modifier and Type
    Method
    Description
    boolean
    canConvert(@NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
     
    com.broadleafcommerce.common.dataimport.util.ConversionUtils.ConversionResponse<Product>
    convert(Object parent, @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
     
    protected com.broadleafcommerce.data.tracking.core.type.OperationType
    determineOperationType(@NonNull Product product, boolean productAlreadyExistsInDatastore, @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
    Determine the effective operation type for the given batch record and product instance.
    protected Map<String,String>
    extractSpecialColumns(@NonNull Map<String,String> mutableRow, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
     
    protected com.broadleafcommerce.common.dataimport.util.IdResolver
     
    protected com.fasterxml.jackson.databind.ObjectMapper
     
    protected Product
    getPrefetchedProduct(com.broadleafcommerce.common.dataimport.messaging.BatchRecord batchRecord, Map<String,String> batchRecordRow, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
    Checks the BatchRequest.BatchContext.getAdditionalContextMap() to see if there is already a pre-fetched product matching the batchRecord.
    protected com.broadleafcommerce.common.extension.TypeFactory
     
    Lazy injection to avoid circular dependency issues.
    protected void
    initializeData(@NonNull Product product, @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull Map<String,String> mutableRow, @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operation, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
    Initialize the data from the row onto the product.
    protected org.springframework.data.util.Pair<Boolean,Product>
    instantiateOrGetPrefetchedProduct(@NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord batchRecord, @NonNull Map<String,String> mutableRow, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
    We expect the CompleteProductImportBatchHandler to have pre-fetched products by various identifier fields if supplied in the original rows.
    protected Product
    modifyProduct(@NonNull Product product, @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
    Hook point to allow implementers to modify the details of the product or return a different product instance.
    protected void
    parseAndSetAttributes(@NonNull Product product, @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operationType, @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull Map<String,String> specialColumns, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
     
    protected void
    parseAndSetFulfillmentFlatRates(@NonNull Product product, @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operationType, @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull Map<String,String> mutableRow, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
     
    protected void
    parseAndSetKeywords(@NonNull Product product, @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operationType, @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull Map<String,String> specialColumns, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
     
    protected void
    parseAndSetOptions(@NonNull Product product, @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operationType, @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull Map<String,String> mutableRow, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
    The syntax we expect for the ProductRowConverter.ProductProperties.OPTIONS_HEADER column is a series of individual option values separated by RowUtils.VALUE_SEPARATOR.
    protected String
    resolveProductId(@NonNull Product product, @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operation, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
     
    protected void
    setProductPricingKeyIfNeeded(Product product, com.broadleafcommerce.common.dataimport.messaging.BatchRecord productRecord, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context, com.broadleafcommerce.data.tracking.core.type.OperationType operationType)
     
    protected void
    setProductTypeBasedOnRecord(Product product, com.broadleafcommerce.common.dataimport.messaging.BatchRecord productRecord, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context, com.broadleafcommerce.data.tracking.core.type.OperationType operationType)
    Set Product.getProductType() based on whether or not the given BatchRecord for product has any variants.
    protected void
    setProductUriIfNeeded(Product product, com.broadleafcommerce.common.dataimport.messaging.BatchRecord productRecord, com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context, com.broadleafcommerce.data.tracking.core.type.OperationType operationType)
     
    void
    Lazy injection to avoid circular dependency issues.
    protected org.springframework.data.util.Pair<String,Attribute>
    toKeyAttributePair(String[] keyValueArray)
     
    protected org.springframework.data.util.Pair<String,FulfillmentFlatRate>
     

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • BATCH_CONTEXT_PREFETCHED_PRODUCTS_BY_ID_MAP

      public static final String BATCH_CONTEXT_PREFETCHED_PRODUCTS_BY_ID_MAP
      In BatchRequest.BatchContext.getAdditionalContextMap(), we expect a nested map under this key to contain prefetched products by their ID.
      See Also:
    • BATCH_CONTEXT_PREFETCHED_PRODUCTS_BY_EXTERNAL_ID_MAP

      public static final String BATCH_CONTEXT_PREFETCHED_PRODUCTS_BY_EXTERNAL_ID_MAP
      In BatchRequest.BatchContext.getAdditionalContextMap(), we expect a nested map under this key to contain prefetched products by their external ID.
      See Also:
  • Constructor Details

    • ProductRowConverter

      public ProductRowConverter(com.fasterxml.jackson.databind.ObjectMapper mapper, com.broadleafcommerce.common.extension.TypeFactory typeFactory, com.broadleafcommerce.common.dataimport.util.IdResolver idResolver)
  • Method Details

    • convert

      @NonNull public com.broadleafcommerce.common.dataimport.util.ConversionUtils.ConversionResponse<Product> convert(@Nullable Object parent, @NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
      Specified by:
      convert in class com.broadleafcommerce.common.dataimport.conversion.AbstractRowConverter<com.broadleafcommerce.common.dataimport.util.ConversionUtils.ConversionResponse<Product>>
    • canConvert

      public boolean canConvert(@NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
      Specified by:
      canConvert in class com.broadleafcommerce.common.dataimport.conversion.AbstractRowConverter<com.broadleafcommerce.common.dataimport.util.ConversionUtils.ConversionResponse<Product>>
    • determineOperationType

      protected com.broadleafcommerce.data.tracking.core.type.OperationType determineOperationType(@NonNull @NonNull Product product, boolean productAlreadyExistsInDatastore, @NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
      Determine the effective operation type for the given batch record and product instance. This can help inform decisions on how to instantiate/map fields.
      Parameters:
      product - the resolved product instance
      productAlreadyExistsInDatastore - whether the product was determined to already exist in the datastore. See instantiateOrGetPrefetchedProduct(BatchRecord, Map, BatchContext)
      record - the original batch record
      context - the batch context
      Returns:
      the effective operation type for the given batch record
    • resolveProductId

      protected String resolveProductId(@NonNull @NonNull Product product, @NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operation, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
    • parseAndSetKeywords

      protected void parseAndSetKeywords(@NonNull @NonNull Product product, @NonNull @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operationType, @NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull @NonNull Map<String,String> specialColumns, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
    • parseAndSetAttributes

      protected void parseAndSetAttributes(@NonNull @NonNull Product product, @NonNull @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operationType, @NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull @NonNull Map<String,String> specialColumns, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
    • toKeyAttributePair

      protected org.springframework.data.util.Pair<String,Attribute> toKeyAttributePair(String[] keyValueArray)
    • parseAndSetOptions

      protected void parseAndSetOptions(@NonNull @NonNull Product product, @NonNull @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operationType, @NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull @NonNull Map<String,String> mutableRow, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
      The syntax we expect for the ProductRowConverter.ProductProperties.OPTIONS_HEADER column is a series of individual option values separated by RowUtils.VALUE_SEPARATOR.

      Each option value consists of a few properties separated by RowUtils.PROPERTY_SEPARATOR. Assignment of property values is done with RowUtils.VALUE_ASSIGNMENT_SEPARATOR.

      For convenience, some properties can be omitted in certain scenarios with an implied default. Here are a few examples of option values:

      • label::Label for Option and Attribute Choice;required::true;type::Size
      • label::Label for Option and Attribute Choice;type::Size -> implies 'required' is false
      • label::Size -> implies 'required' is false, and 'type' will be set to match 'label' since it matches one of DefaultAttributeChoiceType
      • Size -> implies 'required' is false, and both 'label' and 'type' will be set to match the given value since it matches one of DefaultAttributeChoiceType

      Note that 'type' is only optional in situations where the given 'label' value matches (ignoring case) one of DefaultAttributeChoiceType. This prevents inadvertent creation/usage of random types. If custom types need to be used, they should be explicitly provided.

      Furthermore, AttributeChoice.getAllowedValues() are set on each option from the values found in CompleteProductImportBatchHandler.RecordTypes.VARIANT dependent records of the product record.

      Parameters:
      product - the product to set the parsed options on
      operationType - the determined operation type
      record - the original product batch record
      mutableRow - the row from which to obtain the options column
      context - the batch context
    • parseAndSetFulfillmentFlatRates

      protected void parseAndSetFulfillmentFlatRates(@NonNull @NonNull Product product, @NonNull @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operationType, @NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull @NonNull Map<String,String> mutableRow, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
    • toKeyFulfillmentFlatRatePair

      protected org.springframework.data.util.Pair<String,FulfillmentFlatRate> toKeyFulfillmentFlatRatePair(String[] keyValueArray)
    • instantiateOrGetPrefetchedProduct

      protected org.springframework.data.util.Pair<Boolean,Product> instantiateOrGetPrefetchedProduct(@NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord batchRecord, @NonNull @NonNull Map<String,String> mutableRow, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
      We expect the CompleteProductImportBatchHandler to have pre-fetched products by various identifier fields if supplied in the original rows. Any products that were found in the datastore should have been populated into BatchRequest.BatchContext.getAdditionalContextMap().

      If a product is present in this map, we will use this existing instance.

      If a product is not present in this map, we will simply instantiate a new instance.

      Parameters:
      batchRecord - the original BatchRecord
      mutableRow - the row from the batch record (usually with any special columns pre-removed via extractSpecialColumns(Map, BatchContext))
      context - the BatchRequest.BatchContext, which should have any pre-fetched products in BatchRequest.BatchContext.getAdditionalContextMap()
      Returns:
      a Pair containing a boolean describing whether the product was found in the pre-fetched map, as well as the product instance itself
    • getPrefetchedProduct

      @Nullable protected Product getPrefetchedProduct(com.broadleafcommerce.common.dataimport.messaging.BatchRecord batchRecord, Map<String,String> batchRecordRow, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
      Checks the BatchRequest.BatchContext.getAdditionalContextMap() to see if there is already a pre-fetched product matching the batchRecord.
      Parameters:
      batchRecord - the batch record for which to find the corresponding pre-fetched product instance (if exists)
      batchRecordRow - the row from the batch record (pre-processed if necessary)
      context - the batch context which should contain pre-fetched products set by CompleteProductImportBatchHandler
      Returns:
      the pre-fetched product instance if found, or null
    • modifyProduct

      protected Product modifyProduct(@NonNull @NonNull Product product, @NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
      Hook point to allow implementers to modify the details of the product or return a different product instance.

      This MUST return a non-null value. By default, it returns the provided value.

      Parameters:
      product - the product that has been created populated with data from the row
      record - the record that represents the row that was mapped to the product
      context - the batch context
    • initializeData

      protected void initializeData(@NonNull @NonNull Product product, @NonNull @NonNull com.broadleafcommerce.common.dataimport.messaging.BatchRecord record, @NonNull @NonNull Map<String,String> mutableRow, @NonNull @NonNull com.broadleafcommerce.data.tracking.core.type.OperationType operation, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
      Initialize the data from the row onto the product. Set additional data as needed. For example, set ID and activeStartDate.
      Parameters:
      product - the target product onto which we set data.
      record - the original BatchRecord
      mutableRow - the mutable row from the BatchRecord with entries removed that cannot be handled by reflection
      operation - the operation; typically CREATE or UPDATE
      context - the BatchContext
    • extractSpecialColumns

      protected Map<String,String> extractSpecialColumns(@NonNull @NonNull Map<String,String> mutableRow, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context)
      Overrides:
      extractSpecialColumns in class com.broadleafcommerce.common.dataimport.conversion.AbstractRowConverter<com.broadleafcommerce.common.dataimport.util.ConversionUtils.ConversionResponse<Product>>
    • setProductTypeBasedOnRecord

      protected void setProductTypeBasedOnRecord(Product product, com.broadleafcommerce.common.dataimport.messaging.BatchRecord productRecord, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context, com.broadleafcommerce.data.tracking.core.type.OperationType operationType)

      Set Product.getProductType() based on whether or not the given BatchRecord for product has any variants. If it does, Product.getProductType() is set to VARIANT_BASED. Otherwise, STANDARD. This way, the Product.getProductType() wouldn't need to be explicitly declared.

      The Product.getProductType() should only be set if the BatchRecord.getOperation() is CREATE, since Product.getProductType() should never be changed once it's set.

      This method will set the product type to null if the operation is anything but create. This will cause the eventual update operation to skip updating the field.

      Parameters:
      product - product created from the BatchRecord
      productRecord - BatchRecord for the product
      context - BatchRequest.BatchContext
    • setProductUriIfNeeded

      protected void setProductUriIfNeeded(Product product, com.broadleafcommerce.common.dataimport.messaging.BatchRecord productRecord, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context, com.broadleafcommerce.data.tracking.core.type.OperationType operationType)
    • setProductPricingKeyIfNeeded

      protected void setProductPricingKeyIfNeeded(Product product, com.broadleafcommerce.common.dataimport.messaging.BatchRecord productRecord, @Nullable com.broadleafcommerce.common.dataimport.messaging.BatchRequest.BatchContext context, com.broadleafcommerce.data.tracking.core.type.OperationType operationType)
    • getMapper

      protected com.fasterxml.jackson.databind.ObjectMapper getMapper()
    • getTypeFactory

      protected com.broadleafcommerce.common.extension.TypeFactory getTypeFactory()
    • getIdResolver

      protected com.broadleafcommerce.common.dataimport.util.IdResolver getIdResolver()
    • getVariantRowConverter

      protected VariantRowConverter getVariantRowConverter()
      Lazy injection to avoid circular dependency issues.
    • setVariantRowConverter

      @Autowired @Lazy public void setVariantRowConverter(VariantRowConverter variantRowConverter)
      Lazy injection to avoid circular dependency issues.