java.lang.Object
com.broadleafcommerce.common.dataimport.util.RowUtils

public final class RowUtils extends Object
Convenience methods pertaining to processing BatchRecord.getRow().
Author:
Samarth Dhruva (samarthd)
  • Field Details

    • NESTED_FIELD_PATH_SEPARATOR

      public static final String NESTED_FIELD_PATH_SEPARATOR
      An object can have deeply nested properties - for example, you may have the following structure:

      { propertyX: { propertyY: { propertyZ: "some_value" } } } .

      If an import specification wants to support references to such nested properties in a 'flattened' manner in one of the row headers, it can use this separator between properties. For example, 'propertyX_propertyY_propertyZ'. The unflatten(Map) method will support 'unflattening' rows that use this mechanism.

      See Also:
    • VALUE_SEPARATOR

      public static final String VALUE_SEPARATOR
      Constant to allow the separation between groups of properties (e.g. foo::bar|fiz::biz;faz::baz). This usually indicates separation between different objects.
      See Also:
    • VALUE_ASSIGNMENT_SEPARATOR

      public static final String VALUE_ASSIGNMENT_SEPARATOR
      Constant to allow the separation between key/value pairs (e.g. foo::bar)
      See Also:
    • PROPERTY_SEPARATOR

      public static final String PROPERTY_SEPARATOR
      Constant to indicate separation between different properties. (e.g. name::foo;description::bar)
      See Also:
    • LIST_VALUE_ELEMENT_SEPARATOR

      public static final String LIST_VALUE_ELEMENT_SEPARATOR
      Value separator (e.g. "foo::bar,bif,baz") - NOTE that the cell value must be quoted when there is a comma in the data and the originating format is CSV.
      See Also:
  • Method Details

    • copyRecordToEntity

      public static <E> void copyRecordToEntity(@NonNull @NonNull Map<String,String> record, @NonNull @NonNull com.fasterxml.jackson.databind.ObjectMapper mapper, @NonNull E target, boolean ignoreNullValues)
      This method takes the row data, typically from the BatchRecord, and calls the unflatten(Map) method. If copyNulls is false, then all null values are recursively removed from the un-flattened map. Then the ObjectMapper is used to copy the values from the unflattened map to the provided target entity.
      Type Parameters:
      E - the type of the target instance on which data will be set
      Parameters:
      record - the batch record from which the data will be copied
      mapper - the Jackson ObjectMapper to use to handle the mapping
      target - the target object or entity to which the data will be copied
      ignoreNullValues - if true, then null values in the record will not be copied to the target
    • removeNullKeysAndValues

      public static <K, V> void removeNullKeysAndValues(@NonNull @NonNull Map<K,V> map)
      This basic utility simply removes all null values and keys from the Map. If the value is, itself, a Map, then this will continue recursively.

      This is generally used if we want to use reflection to copy a Map onto an entity such as a projection entity, but where we do not want to override existing values with null values.

      Type Parameters:
      K - the type of keys in the map
      V - the type of values in the map
      Parameters:
      map - the input map to modify
    • unflatten

      public static Map<String,Object> unflatten(Map<String,String> fullyQualifiedFieldPathsToValues)
      This method accepts a "flat" map of field names to field values, where the field names can be underscore-separated names to indicate a nested structure of complex object fields. This map is then "unflattened" to produce a map where complex objects are maps, and simple values are just strings.

      For example, given a map with the following key/values:

      • "fieldA" -> "fieldAVal"
      • "fieldB" -> "fieldBVal"
      • "fieldC_fieldC1" -> "fieldC1Val"
      • "fieldC_fieldC2" -> "fieldC2Val"
      • "fieldD_fieldD1" -> "fieldD1Val"
      • "fieldD_fieldD2_fieldD2a" -> "fieldD2aVal"
      • "fieldD_fieldD2_fieldD2b" -> "fieldD2bVal"
      The output map would look like this:
      • "fieldA" -> "fieldAVal"
      • "fieldB" -> "fieldBVal"
      • "fieldC" -> {
        • "fieldC1" -> "fieldC1Val",
        • "fieldC2" -> "fieldC2Val"
        }
      • "fieldD" -> {
        • "fieldD1" -> "fieldD1Val",
        • "fieldD2" -> {
          • "fieldD2a" -> "fieldD2aVal",
          • "fieldD2b" -> "fieldD2bVal"
          }
        }
      Parameters:
      fullyQualifiedFieldPathsToValues - a "flattened" representation of field names to field values, with underscore-separated field names indicating values for complex objects
      Returns:
      the "unflattened" representation of the map, where complex objects are maps and simple values are just strings. If no nested-path field names were found, the output will be effectively equivalent to the input.
      Throws:
      IllegalArgumentException - if any of the complex object fields had their values directly specified. For example, if fullyQualifiedFieldPathsToValues had both of these entries: <"a_b_field1", "some value"> and <"a_b", "some other value">, then this exception would be thrown. "b" is supposed to be a complex object with a field "field1", but its value is also directly assigned to "some other value", which is incorrect.