(Recovered from my old Blog).
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:
1 2 3 |
public enum TransactionSource implements TransactionAttributeInterface { TRADING_SYSTEM, SETTLEMENT_FACTORY; } |
Then, the consuming code becomes simple:
1 2 3 4 5 6 7 8 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 |
@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(); } |