As we know, enums are great for storing (relatively) static domain information.
But let’s say we want an object which models (and can persist) a collection of elements where we are not sure at design time which domain information will be stored. For example, a set of attributes describing a financial trade – TransactionSource, BusinessFlow, TradingStrategy, etc. While we could model these all separately, it would be nice to have a single collection of attributes.
In this scenario, we could create a collection (and associated methods) which manipulate Object, but in today’s typesafe world there has to be something better.
I propose creating an empty interface, then having all enums implement it:
public enum TransactionSource implements TransactionAttributeInterface {
TRADING_SYSTEM, SETTLEMENT_FACTORY;
}
Then, the consuming code becomes simple:
public interface TransactionAttribute {
void setTransactionAttributeValue(TransactionAttributeInterface transactionAttributeValue);
TransactionAttributeInterface getTransactionAttributeValue();
}
private Map<TransactionAttributeType, TransactionAttribute> transactionAttributeMap;
TransactionAttribute transactionAttribute = new TransactionAttributeImpl();
transactionAttribute.setTransactionAttributeValue(TransactionSource.TRADING_SYSTEM);
Note that Hibernate will confused when trying to persist TransactionAttribute (as it won’t be able to determine the type of TransactionAttributeInterface). This could be solved by creating a new Hibernate UserType (see https://www.hibernate.org/272.html), or more easily by mapping to a String internally for persistence:
@Column(name = "tran_attribute_value")
private String transactionAttributeValue;
@Override
public TransactionAttributeInterface getTransactionAttributeValue() {
return (TransactionAttributeInterface) Enum.valueOf((Class<? extends Enum>)transactionAttributeType.getTransactionAttributeTypeClass(), transactionAttributeValue);
}
@Override
public void setTransactionAttributeValue(TransactionAttributeInterface transactionAttributeValue) {
this.transactionAttributeValue = transactionAttributeValue.toString();
}