Enumerations
Broadleaf provides two data structures to store enumeration like data, a BroadleafEnumerationType
and a DataDrivenEnumeration
. Both are, in essence, just a collection of String
values. A BroadleafEnumerationType
is used to provide a predefined set of values to use in business logic, while a DataDrivenEnumeration
is used to provide a variable set of values to use in places like drop-down menus in the admin console.
BroadleafEnumerationType
The BroadleafEnumerationType
is an interface that is implemented to create a custom enumeration of predefined hard-coded String
values. An example from the Broadleaf framework would be FulfillmentType
. FulfillmentType
is an enumeration that contains values corresponding to the available FulfillmentGroup
types. Here is how BroadleafEnumerationType
is implemented by FulfillmentType
:
public class FulfillmentType implements Serializable, BroadleafEnumerationType {
private static final long serialVersionUID = 1L;
private static final Map<String, FulfillmentType> TYPES = new LinkedHashMap<String, FulfillmentType>();
public static final FulfillmentType DIGITAL = new FulfillmentType("DIGITAL", "Digital");
public static final FulfillmentType PHYSICAL_SHIP = new FulfillmentType("PHYSICAL_SHIP", "Physical Ship");
public static final FulfillmentType PHYSICAL_PICKUP = new FulfillmentType("PHYSICAL_PICKUP", "Physical Pickup");
public static final FulfillmentType PHYSICAL_PICKUP_OR_SHIP = new FulfillmentType("PHYSICAL_PICKUP_OR_SHIP", "Physical Pickup or Ship");
public static final FulfillmentType GIFT_CARD = new FulfillmentType("GIFT_CARD", "Gift Card");
@Deprecated
public static final FulfillmentType SHIPPING = new FulfillmentType("SHIPPING", "Shipping");
public static FulfillmentType getInstance(final String type) {
return TYPES.get(type);
}
private String type;
private String friendlyType;
and here is an example of how FulfillmentType
is used in business logic:
if(!FulfillmentType.GIFT_CARD.equals(fulfillmentGroup.getType())) {
shippableFulfillmentGroups++;
}
Adding new values to an existing BroadleafEnumeration type
At times there is a need to add a new value to an existing out-of-box enumeration. This is easily done by creating a new bean, adding the new value, and then making sure Spring creates that bean. For example, to add a new FulfillmentType value:
1) Create a new bean
package com.mycompany.type;
...
public class MyFulfillmentType extends FulfillmentType {
public static final FulfillmentType DIGITAL = new FulfillmentType("COUPON", "Customer Coupon Code");
}
2) Register the bean with Spring by creating the new bean in the appropriate applicationContext.xml:
<bean class="com.mycompany.type.MyFulfillmentType"/>
Removing values from an existing BroadleafEnumeration type
In some cases, there may be a need to remove values from an out-of-box BroadleafEnumeration type. In this instance, the existing enumeration bean will need to be replaced and the field that uses that enumeration (for admin purposes) would need to have the metadata overridden
1) Create a new BroadleafEnumeration entity
public class ClientFulfillmentType implements Serializable, BroadleafEnumerationType {
private static final long serialVersionUID = 1L;
private static final Map<String, ClientFulfillmentType> TYPES = new LinkedHashMap<String, ClientFulfillmentType>();
public static final ClientFulfillmentType MY_NEW_TYPE = new ClientFulfillmentType("MY_NEW_TYPE", "My new type");
public static ClientFulfillmentType getInstance(final String type) {
return TYPES.get(type);
}
private String type;
private String friendlyType;
public ClientFulfillmentType() {
//do nothing
}
public ClientFulfillmentType(final String type, final String friendlyType) {
this.friendlyType = friendlyType;
setType(type);
}
@Override
public String getType() {
return type;
}
@Override
public String getFriendlyType() {
return friendlyType;
}
private void setType(final String type) {
this.type = type;
if (!TYPES.containsKey(type)) {
TYPES.put(type, this);
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!getClass().isAssignableFrom(obj.getClass()))
return false;
ClientFulfillmentType other = (ClientFulfillmentType) obj;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
}
2) For use in the admin, override the field that uses the enumeration with the newly created enumeration in the applicationContext-admin.xml file
<mo:override id="blMetadataOverrides">
<mo:overrideItem ceilingEntity="org.broadleafcommerce.core.catalog.domain.Product">
<mo:field name="defaultSku.fulfillmentType">
<mo:property name="broadleafEnumeration" value="org.broadleafcommerce.core.order.service.type.ClientFulfillmentType" />
</mo:field>
</mo:overrideItem>
</mo:override>
DataDrivenEnumeration
A DataDrivenEnumeration
is an entity that contains a list of DataDrivenEnumerationValue
values. A DataDrivenEnumerationValue
is also an entity and provides structure to a single String
value. In contrast to the BroadleafEnumerationType
, which is used to hard-code a set of values, the DataDrivenEnumeration
contains a set of database stored values which can be changed as needed.
The admin console provides configuration screens to create and edit DataDrivenEnumerations
(under the Utilities
tab in the sidebar). Once an enumeration is created using the admin console, it is saved to the database for future use.
An example of how use a DataDrivenEnumeration
is the creation of drop-down menus in the admin console. In order to use a DataDrivenEnumeration
to supply values to an admin drop-down menu; the @AdminPresentation
annotation is used with the @AdminPresentationDataDrivenEnumeration
annotation. Below is an example:
@Column(name = "TAX_CODE")
@AdminPresentation(friendlyName = "SkuImpl_Sku_TaxCode")
@AdminPresentationDataDrivenEnumeration(optionFilterParams = { @OptionFilterParam(param = "type.key", value = "TAX_CODE", paramType = OptionFilterParamType.STRING) })
protected String taxCode;
@AdminPresentation
- Used to style and place the field.@AdminPresentationDataDrivenEnumeration
- Used to specify that the field will be assigned a value from a specific subset ofDataDrivenEnumerationValue
values.optionFilterParams
- Additional parameters to refine the query that is used to specify which values will be visible in the drop-down menu.param = "type.key"
- The field name in the target entity that should be used to refine the query. In this case, type is from theDataDrivenEnumerationValue
and key is fromDataDrivenEnumeration
.value = "TAX_CODE"
- The field value that should match for any items returned from the query.paramType = OptionFilterParamType.STRING
- This is the type for the value stored in thisOptionFilterParam
annotation.
@AdminPresentationDataDrivenEnumeration
specifies that the field taxCode
will be assigned a value from the set of DataDrivenEnumerationValue
values which have type.key = "TAX_CODE"
. The admin console will display a drop-down menu containing this set of values.
Here is alternate example illustrating the creation of a drop-down whose values come from CategoryImpl.name
:
@Column(name = "NAME")
@AdminPresentation(friendlyName = "CategoryImpl_Category_Name")
@AdminPresentationDataDrivenEnumeration(optionListEntity = CategoryImpl.class, optionValueFieldName = "name",
optionDisplayFieldName = "name", optionCanEditValues = true)
protected String name;
optionListEntity
- Specifies the target entity that should be queried for the list of options that will be presented to the user in a drop-down list. In this case, it will useCategoryImpl.class
.optionValueFieldName = "name"
- Specify the field in the target entity that contains the value that will be persisted into this annotated field. In this case, it will useCategoryImpl.name
.optionDisplayFieldName = "name"
- Specify the field in the target entity that contains the display value that will be shown to the user in the drop-down field. In this case, it will useCategoryImpl.name
.optionCanEditValues = true
- Whether or not the user can edit (or enter new values) in the drop-down menu.
The @AdminPresentationDataDrivenEnumeration
annotation specifies that the field name will be assigned a value from the set of all CategoryImpl.name
values (no optionFilterParams
were used to refine the query).